Merge Android 14 QPR2 to AOSP main
Bug: 319669529
Merged-In: I204e27a5a66b713002bd39ba57c7498147956a59
Change-Id: I46b4c2f5c7d57ebe588d8a000d46cd790ee1891d
diff --git a/OWNERS b/OWNERS
index 116f70a..0ba79c4 100644
--- a/OWNERS
+++ b/OWNERS
@@ -3,4 +3,5 @@
amruthr@google.com
seheele@google.com
koshytc@google.com
-
+ericdavison@google.com
+radhikaagrawal@google.com
diff --git a/service/src/com/android/telephony/imsmedia/AudioSession.java b/service/src/com/android/telephony/imsmedia/AudioSession.java
index c3331d9..20a6781 100644
--- a/service/src/com/android/telephony/imsmedia/AudioSession.java
+++ b/service/src/com/android/telephony/imsmedia/AudioSession.java
@@ -469,6 +469,9 @@
private void handleModifySessionRespose(AudioConfig config, int error) {
try {
+ if (error != ImsMediaSession.RESULT_SUCCESS) {
+ Log.e(TAG, "modifySession failed with error: " + error);
+ }
mCallback.onModifySessionResponse(config, error);
} catch (RemoteException e) {
Log.e(TAG, "Failed to notify modifySessionResponse: " + e);
diff --git a/service/src/com/android/telephony/imsmedia/TextSession.java b/service/src/com/android/telephony/imsmedia/TextSession.java
index 37dd047..6c216c1 100644
--- a/service/src/com/android/telephony/imsmedia/TextSession.java
+++ b/service/src/com/android/telephony/imsmedia/TextSession.java
@@ -247,6 +247,9 @@
private void handleModifySessionRespose(TextConfig config, int error) {
try {
+ if (error != ImsMediaSession.RESULT_SUCCESS) {
+ Log.e(TAG, "modifySession failed with error: " + error);
+ }
mCallback.onModifySessionResponse(config, error);
} catch (RemoteException e) {
Log.e(TAG, "Failed to notify modifySessionResponse: " + e);
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/Android.bp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/Android.bp
index c92b7a1..903f469 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/Android.bp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/Android.bp
@@ -57,6 +57,9 @@
cflags: [
"-Wall",
],
+ shared_libs: [
+ "libmediautils",
+ ],
sanitize: {
cfi: true,
scs: true,
@@ -91,5 +94,6 @@
"libmediandk",
"libnativewindow",
"libutils",
+ "libmediautils",
],
}
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/src/TextConfig.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/src/TextConfig.cpp
index 4181fc5..b1fb5ea 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/src/TextConfig.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/src/TextConfig.cpp
@@ -64,6 +64,7 @@
{
if (this != &config)
{
+ RtpConfig::operator=(config);
this->mCodecType = config.mCodecType;
this->mBitrate = config.mBitrate;
this->mRedundantPayload = config.mRedundantPayload;
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/Android.bp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/Android.bp
index a6832c7..eee19e6 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/Android.bp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/Android.bp
@@ -119,7 +119,7 @@
shared_libs: [
"libnativewindow",
"libcamera2ndk",
- "libandroid"
+ "libandroid",
],
include_dirs: [
"frameworks/av/camera/ndk/include",
@@ -159,6 +159,9 @@
local_include_dirs: [
"include",
],
+ include_dirs: [
+ "frameworks/av/media/utils/include",
+ ],
header_libs: [
"libimsmedia_jni_headers",
"libimsmedia_protocol_interface_headers",
@@ -177,5 +180,6 @@
"liblog",
"libmediandk",
"libutils",
+ "libmediautils",
],
}
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/JitterNetworkAnalyser.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/JitterNetworkAnalyser.cpp
index ee5f7a6..d19045b 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/JitterNetworkAnalyser.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/JitterNetworkAnalyser.cpp
@@ -21,13 +21,15 @@
#include <numeric>
#include <cmath>
#include <algorithm>
+#include <climits>
#define MAX_JITTER_LIST_SIZE (150)
#define PACKET_INTERVAL (20) // milliseconds
#define BUFFER_INCREASE_TH (200) // milliseconds
-#define BUFFER_DECREASE_TH (3000) // milliseconds
-#define MARGIN_WEIGHT (1.8f)
-#define BUFFER_IN_DECREASE_SIZE (1)
+#define BUFFER_DECREASE_TH (2000) // milliseconds
+#define MARGIN_WEIGHT (1.0f)
+#define BUFFER_IN_DECREASE_SIZE (2)
+#define ROUNDUP_MARGIN (10) // milliseconds
JitterNetworkAnalyser::JitterNetworkAnalyser()
{
@@ -38,7 +40,7 @@
mBufferStepSize = BUFFER_IN_DECREASE_SIZE;
mBufferWeight = MARGIN_WEIGHT;
- IMLOGD4("[JitterNetworkAnalyser] incThreshold[%d], decThreshold[%d], stepSize[%d], "
+ IMLOGD4("[JitterNetworkAnalyser] incThreshold=%d, decThreshold=%d, stepSize=%d, "
"weight[%.3f]",
mBufferIncThreshold, mBufferDecThreshold, mBufferStepSize, mBufferWeight);
Reset();
@@ -54,9 +56,12 @@
{
std::lock_guard<std::mutex> guard(mMutex);
- mListJitters.clear();
- mMapDelta.clear();
+ mListAccumDeltas.clear();
+ mPrevTimestamp = 0;
+ mPrevArrivalTime = 0;
mTimeLateArrivals = 0;
+ mPrevDelta = 0;
+ minJitterInBeginning = INT_MAX;
}
}
@@ -75,7 +80,7 @@
mBufferStepSize = stepSize;
mBufferWeight = weight;
- IMLOGD4("[SetJitterOptions] incThreshold[%d], decThreshold[%d], stepSize[%d], weight[%.3f]",
+ IMLOGD4("[SetJitterOptions] incThreshold=%d, decThreshold=%d, stepSize=%d, weight[%.3f]",
mBufferIncThreshold, mBufferDecThreshold, mBufferStepSize, mBufferWeight);
}
@@ -95,40 +100,39 @@
{
std::lock_guard<std::mutex> guard(mMutex);
- if (mMapDelta.size() == 0)
+ if (mPrevTimestamp == 0)
{
- mMapDelta.insert({timestamp, arrivalTime});
+ mPrevTimestamp = timestamp;
+ mPrevArrivalTime = arrivalTime;
+ minJitterInBeginning = INT_MAX;
return 0;
}
- if (mMapDelta.size() > MAX_JITTER_LIST_SIZE)
+ int32_t inputTimestampGap = timestamp - mPrevTimestamp;
+ int32_t inputTimeGap = arrivalTime - mPrevArrivalTime;
+ int32_t delta = inputTimeGap - inputTimestampGap;
+
+ mPrevTimestamp = timestamp;
+ mPrevArrivalTime = arrivalTime;
+
+ mPrevDelta += delta;
+ mListAccumDeltas.push_back(
+ minJitterInBeginning == INT_MAX ? mPrevDelta : mPrevDelta - minJitterInBeginning);
+
+ if (mListAccumDeltas.size() > MAX_JITTER_LIST_SIZE)
{
- mMapDelta.erase(mMapDelta.begin());
+ mListAccumDeltas.pop_front();
+ }
+ else
+ {
+ // for normalization
+ if (minJitterInBeginning > mPrevDelta)
+ {
+ minJitterInBeginning = mPrevDelta;
+ }
}
- mMapDelta.insert({timestamp, arrivalTime});
-
- if (getGreatestLess(mMapDelta, timestamp) == mMapDelta.end())
- {
- mListJitters.push_back(0);
- return 0;
- }
-
- int32_t inputTimestampGap = timestamp - getGreatestLess(mMapDelta, timestamp)->first;
- int32_t inputTimeGap = arrivalTime - getGreatestLess(mMapDelta, timestamp)->second;
- int32_t jitter = std::abs(inputTimeGap - inputTimestampGap);
-
- if (jitter < mMaxJitterBufferSize * PACKET_INTERVAL)
- {
- mListJitters.push_back(jitter);
- }
-
- if (mListJitters.size() > MAX_JITTER_LIST_SIZE)
- {
- mListJitters.pop_front();
- }
-
- return jitter;
+ return delta;
}
void JitterNetworkAnalyser::SetLateArrivals(uint32_t time)
@@ -140,23 +144,23 @@
{
std::lock_guard<std::mutex> guard(mMutex);
- if (mListJitters.empty())
+ if (mListAccumDeltas.empty())
{
*pMean = 0;
return 0.0f;
}
- double mean =
- std::accumulate(mListJitters.begin(), mListJitters.end(), 0.0f) / mListJitters.size();
+ double mean = std::accumulate(mListAccumDeltas.begin(), mListAccumDeltas.end(), 0.0f) /
+ mListAccumDeltas.size();
*pMean = mean;
- double dev = sqrt(std::accumulate(mListJitters.begin(), mListJitters.end(), 0.0f,
+ double dev = sqrt(std::accumulate(mListAccumDeltas.begin(), mListAccumDeltas.end(), 0.0f,
[mean](int x, int y)
{
return x + std::pow(y - mean, 2);
}) /
- mListJitters.size());
+ mListAccumDeltas.size());
return dev;
}
@@ -165,12 +169,12 @@
{
std::lock_guard<std::mutex> guard(mMutex);
- if (mListJitters.empty())
+ if (mListAccumDeltas.empty())
{
return 0;
}
- return *std::max_element(mListJitters.begin(), mListJitters.end());
+ return *std::max_element(mListAccumDeltas.begin(), mListAccumDeltas.end());
}
uint32_t JitterNetworkAnalyser::GetNextJitterBufferSize(
@@ -183,15 +187,14 @@
double calcJitterSize = 0;
int32_t maxJitter = GetMaxJitterValue();
dev = CalculateDeviation(&mean);
- calcJitterSize = (double)maxJitter * mBufferWeight;
+ calcJitterSize = (double)maxJitter * mBufferWeight + ROUNDUP_MARGIN;
+ uint32_t bufferSize = calcJitterSize / PACKET_INTERVAL;
- if (calcJitterSize >= nCurrJitterBufferSize * PACKET_INTERVAL ||
- maxJitter >= nCurrJitterBufferSize * PACKET_INTERVAL)
+ if (bufferSize > nCurrJitterBufferSize)
{
networkStatus = NETWORK_STATUS_BAD;
}
- else if (calcJitterSize < (nCurrJitterBufferSize - 1) * PACKET_INTERVAL &&
- maxJitter < (nCurrJitterBufferSize - 1) * PACKET_INTERVAL - 10)
+ else if (bufferSize < nCurrJitterBufferSize - 1)
{
networkStatus = NETWORK_STATUS_GOOD;
}
@@ -201,35 +204,28 @@
}
IMLOGD_PACKET6(IM_PACKET_LOG_JITTER,
- "[GetNextJitterBufferSize] size[%4.2f], mean[%4.2f], dev[%4.2f], max[%d], curr[%d], "
- "status[%d]",
+ "[GetNextJitterBufferSize] size=%4.2f, mean=%4.2f, dev=%4.2f, max=%d, curr=%d, "
+ "status=%d",
calcJitterSize, mean, dev, maxJitter, nCurrJitterBufferSize, networkStatus);
switch (networkStatus)
{
case NETWORK_STATUS_BAD:
{
- if (mBadStatusChangedTime == 0 ||
- (currentTime - mBadStatusChangedTime) >= mBufferIncThreshold)
+ nextJitterBuffer = bufferSize;
+
+ if (nextJitterBuffer > mMaxJitterBufferSize)
{
- nextJitterBuffer = (calcJitterSize + PACKET_INTERVAL) / PACKET_INTERVAL;
-
- if (nextJitterBuffer > mMaxJitterBufferSize)
- {
- nextJitterBuffer = mMaxJitterBufferSize;
- }
-
- if (nextJitterBuffer < mMinJitterBufferSize)
- {
- nextJitterBuffer = mMinJitterBufferSize;
- }
-
- IMLOGD_PACKET2(IM_PACKET_LOG_JITTER,
- "[GetNextJitterBufferSize] increase curr[%d], next[%d]",
- nCurrJitterBufferSize, nextJitterBuffer);
- mBadStatusChangedTime = currentTime;
+ nextJitterBuffer = mMaxJitterBufferSize;
+ }
+ else if (nextJitterBuffer < mMinJitterBufferSize)
+ {
+ nextJitterBuffer = mMinJitterBufferSize;
}
+ IMLOGD_PACKET2(IM_PACKET_LOG_JITTER,
+ "[GetNextJitterBufferSize] increase curr=%d, next=%d", nCurrJitterBufferSize,
+ nextJitterBuffer);
break;
}
case NETWORK_STATUS_GOOD:
@@ -246,13 +242,19 @@
(mTimeLateArrivals == 0 ||
currentTime - mTimeLateArrivals > mBufferDecThreshold))
{
- if (nCurrJitterBufferSize > mMinJitterBufferSize)
+ uint32_t decreaseStep = nCurrJitterBufferSize - bufferSize;
+
+ decreaseStep > mBufferStepSize
+ ? nextJitterBuffer = nCurrJitterBufferSize - mBufferStepSize
+ : nextJitterBuffer = nCurrJitterBufferSize - decreaseStep;
+
+ if (nextJitterBuffer < mMinJitterBufferSize)
{
- nextJitterBuffer = nCurrJitterBufferSize - mBufferStepSize;
+ nextJitterBuffer = mMinJitterBufferSize;
}
IMLOGD_PACKET2(IM_PACKET_LOG_JITTER,
- "[GetNextJitterBufferSize] decrease curr[%d], next[%d]",
+ "[GetNextJitterBufferSize] decrease curr=%d, next=%d",
nCurrJitterBufferSize, nextJitterBuffer);
networkStatus = NETWORK_STATUS_NORMAL;
}
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/StreamScheduler.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/StreamScheduler.cpp
index 9184212..f75efd2 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/StreamScheduler.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/StreamScheduler.cpp
@@ -72,7 +72,7 @@
if (!mlistRegisteredNode.empty())
{
IMLOGD1("[Start] [%p] Start thread", this);
- StartThread();
+ StartThread("StreamScheduler");
}
IMLOGD1("[Start] [%p] exit", this);
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioJitterBuffer.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioJitterBuffer.cpp
index 1a2cda5..74aad1e 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioJitterBuffer.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioJitterBuffer.cpp
@@ -134,7 +134,7 @@
void AudioJitterBuffer::SetEvsRedundantFrameOffset(const int32_t offset)
{
- IMLOGD1("[SetEvsRedundantFrameOffset] offset[%d]", offset);
+ IMLOGD1("[SetEvsRedundantFrameOffset] offset=%d", offset);
mEvsRedundantFrameOffset = offset;
}
@@ -156,13 +156,13 @@
if (subtype == MEDIASUBTYPE_REFRESHED)
{
- // nBufferSize is ssrc value
+ std::lock_guard<std::mutex> guard(mMutex);
mSsrc = nBufferSize;
- mTimeStarted = ImsMediaTimer::GetTimeInMilliSeconds();
+ mTimeStarted = arrivalTime;
mJitterAnalyzer.Reset();
mDataQueue.Add(&currEntry);
- IMLOGI2("[Add] ssrc[%u], startTime[%d]", mSsrc, mTimeStarted);
+ IMLOGI2("[Add] ssrc=%u, startTime=%d", mSsrc, mTimeStarted);
return;
}
@@ -198,8 +198,8 @@
std::lock_guard<std::mutex> guard(mMutex);
IMLOGD_PACKET8(IM_PACKET_LOG_JITTER,
- "[Add] seq[%d], mark[%d], TS[%d], size[%d], jitter[%d], queue[%d], playingDiff[%d], "
- "arrival[%d]",
+ "[Add] seq=%d, mark=%d, TS=%d, size=%d, jitter=%d, queue=%d, playingDiff=%d, "
+ "arrival=%d",
nSeqNum, bMark, nTimestamp, nBufferSize, jitter, mDataQueue.GetCount() + 1,
mCurrPlayingTS - nTimestamp, arrivalTime);
@@ -249,6 +249,15 @@
mListVoiceFrames.pop_front();
}
}
+
+ // update jitter buffer size
+ if (!mWaiting && mUpdatedDelay == 0)
+ {
+ uint32_t nextJitterBufferSize =
+ mJitterAnalyzer.GetNextJitterBufferSize(mCurrJitterBufferSize, arrivalTime);
+ mCheckUpdateJitterPacketCnt = 0;
+ mUpdatedDelay = nextJitterBufferSize - mCurrJitterBufferSize;
+ }
}
bool AudioJitterBuffer::Get(ImsMediaSubType* psubtype, uint8_t** ppData, uint32_t* pnDataSize,
@@ -257,15 +266,8 @@
{
std::lock_guard<std::mutex> guard(mMutex);
- if (mPrevGetTime == 0)
- {
- mPrevGetTime = currentTime;
- }
- else
- {
- IMLOGD_PACKET1(IM_PACKET_LOG_JITTER, "[Get] time diff[%d]", currentTime - mPrevGetTime);
- mPrevGetTime = currentTime;
- }
+ IMLOGD_PACKET1(IM_PACKET_LOG_JITTER, "[Get] time diff=%d", currentTime - mPrevGetTime);
+ mPrevGetTime = currentTime;
DataEntry* pEntry = nullptr;
bool bForceToPlay = false;
@@ -283,34 +285,12 @@
}
}
- // update jitter buffer size
- if (!mWaiting && mUpdatedDelay == 0 &&
- ((mDtxPlayed && mDataQueue.Get(&pEntry) &&
- pEntry->eDataType != MEDIASUBTYPE_AUDIO_SID) ||
- mCheckUpdateJitterPacketCnt * FRAME_INTERVAL > JITTER_BUFFER_UPDATE_INTERVAL))
- {
- uint32_t nextJitterBufferSize =
- mJitterAnalyzer.GetNextJitterBufferSize(mCurrJitterBufferSize, currentTime);
- mCheckUpdateJitterPacketCnt = 0;
- mUpdatedDelay = nextJitterBufferSize - mCurrJitterBufferSize;
-
- if (mDataQueue.GetCount() < mMinJitterBufferSize && mUpdatedDelay < 0)
- {
- IMLOGD_PACKET1(
- IM_PACKET_LOG_JITTER, "[Get] ignore decrease[%d]", mDataQueue.GetCount());
- mUpdatedDelay = 0;
- }
- else
- {
- mCurrJitterBufferSize = nextJitterBufferSize;
- }
- }
-
// increase delay
if (!mWaiting && mDtxPlayed && mUpdatedDelay > 0)
{
- IMLOGD2("[Get] increase delay[%d], curTS[%d]", mUpdatedDelay, mCurrPlayingTS);
+ IMLOGD2("[Get] increase delay=%d, curTS=%d", mUpdatedDelay, mCurrPlayingTS);
mUpdatedDelay--;
+ mCurrJitterBufferSize++;
return false;
}
@@ -318,9 +298,10 @@
if (!mWaiting && mDataQueue.Get(&pEntry) && pEntry->eDataType == MEDIASUBTYPE_AUDIO_SID &&
mUpdatedDelay < 0)
{
- IMLOGD3("[Get] decrease delay[%d], curTS[%u], queue[%u]", mUpdatedDelay, mCurrPlayingTS,
+ IMLOGD3("[Get] decrease delay=%d, curTS=%u, queue=%u", mUpdatedDelay, mCurrPlayingTS,
mDataQueue.GetCount());
mUpdatedDelay++;
+ mCurrJitterBufferSize--;
mCurrPlayingTS += FRAME_INTERVAL;
}
@@ -332,13 +313,13 @@
{
if (mCurrJitterBufferSize == mMaxJitterBufferSize)
{
- IMLOGD1("[Get] resync, drop rate[%u]", dropRate);
+ IMLOGD1("[Get] resync, drop rate=%u", dropRate);
mWaiting = true;
mTimeStarted = currentTime;
}
else
{
- IMLOGD1("[Get] increase delay by drop rate[%u]", dropRate);
+ IMLOGD1("[Get] increase delay by drop rate=%u", dropRate);
mCurrPlayingTS -= FRAME_INTERVAL;
mCurrJitterBufferSize++;
}
@@ -348,7 +329,7 @@
if (mDataQueue.GetCount() == 0)
{
- IMLOGD_PACKET1(IM_PACKET_LOG_JITTER, "[Get] fail - empty, curTS[%u]", mCurrPlayingTS);
+ IMLOGD_PACKET1(IM_PACKET_LOG_JITTER, "[Get] fail - empty, curTS=%u", mCurrPlayingTS);
if (!mWaiting)
{
@@ -359,7 +340,7 @@
}
else if (mDataQueue.Get(&pEntry) && mWaiting)
{
- if (currentTime - mTimeStarted < mInitJitterBufferSize * FRAME_INTERVAL)
+ if (currentTime - mTimeStarted + ALLOWABLE_ERROR < mInitJitterBufferSize * FRAME_INTERVAL)
{
if (psubtype)
*psubtype = MEDIASUBTYPE_UNDEFINED;
@@ -376,10 +357,11 @@
if (pDataType)
*pDataType = MEDIASUBTYPE_UNDEFINED;
- IMLOGD_PACKET4(IM_PACKET_LOG_JITTER,
- "[Get] Wait - seq[%u], CurrJBSize[%u], delay[%u], QueueCount[%u]",
- pEntry->nSeqNum, mCurrJitterBufferSize, currentTime - pEntry->arrivalTime,
- GetCount());
+ IMLOGD_PACKET5(IM_PACKET_LOG_JITTER,
+ "[Get] Wait - timeStarted=%d, seq=%u, CurrJBSize=%u, delay=%u, "
+ "QueueCount=%u",
+ mTimeStarted, pEntry->nSeqNum, mCurrJitterBufferSize,
+ currentTime - pEntry->arrivalTime, GetCount());
return false;
}
else
@@ -400,7 +382,7 @@
// discard duplicated packet
if (mDataQueue.Get(&pEntry) && mFirstFrameReceived && pEntry->nSeqNum == mLastPlayedSeqNum)
{
- IMLOGD6("[Get] duplicate - curTS[%u], seq[%d], mark[%d], TS[%u], size[%d], queue[%d]",
+ IMLOGD6("[Get] duplicate - curTS=%u, seq=%d, mark=%d, TS=%u, size=%d, queue=%d",
mCurrPlayingTS, pEntry->nSeqNum, pEntry->bMark, pEntry->nTimestamp,
pEntry->nBufferSize, mDataQueue.GetCount());
CollectRxRtpStatus(pEntry->nSeqNum, kRtpStatusDuplicated);
@@ -419,11 +401,12 @@
// adjust the playing timestamp
if (mDataQueue.Get(&pEntry) && pEntry->nTimestamp != mCurrPlayingTS &&
- ((mCurrPlayingTS - ALLOWABLE_ERROR) < pEntry->nTimestamp) &&
- (pEntry->nTimestamp < (mCurrPlayingTS + ALLOWABLE_ERROR)))
+ ((mCurrPlayingTS - ALLOWABLE_ERROR) <= pEntry->nTimestamp) &&
+ (pEntry->nTimestamp <= (mCurrPlayingTS + ALLOWABLE_ERROR)))
{
+ IMLOGD3("[Get] sync playing curTS=%u, TS=%u, seq=%d", mCurrPlayingTS, pEntry->nTimestamp,
+ pEntry->nSeqNum);
mCurrPlayingTS = pEntry->nTimestamp;
- IMLOGD2("[Get] sync playing curTS[%u], seq[%d]", mCurrPlayingTS, pEntry->nSeqNum);
}
// delete late arrival
@@ -439,9 +422,9 @@
mLastPlayedSeqNum = pEntry->nSeqNum;
}
- IMLOGD_PACKET3(IM_PACKET_LOG_JITTER,
- "[Get] delete late arrival seq[%d], curTS[%u], dtx[%d]", pEntry->nSeqNum,
- mCurrPlayingTS, mDtxPlayed);
+ IMLOGD_PACKET4(IM_PACKET_LOG_JITTER,
+ "[Get] delete late arrival, dtx=%d, seq=%d, curTS=%u, TS=%u", mDtxPlayed,
+ pEntry->nSeqNum, mCurrPlayingTS, pEntry->nTimestamp);
if (mPreservedDtx != nullptr)
{
@@ -505,9 +488,9 @@
}
IMLOGD_PACKET7(IM_PACKET_LOG_JITTER,
- "[Get] OK - dtx[%d], curTS[%u], seq[%u], TS[%u], size[%u], delay[%u], queue[%u]",
+ "[Get] OK, dtx=%d, curTS=%u, seq=%u, TS=%u, size=%u, delay=%u, curSize=%u",
mDtxPlayed, mCurrPlayingTS, pEntry->nSeqNum, pEntry->nTimestamp,
- pEntry->nBufferSize, currentTime - pEntry->arrivalTime, mDataQueue.GetCount());
+ pEntry->nBufferSize, currentTime - pEntry->arrivalTime, mCurrJitterBufferSize);
mCurrPlayingTS = pEntry->nTimestamp + FRAME_INTERVAL;
mFirstFrameReceived = true;
@@ -552,7 +535,7 @@
*pDataType = pEntry->eDataType;
IMLOGD_PACKET3(IM_PACKET_LOG_JITTER,
- "[Get] preserved frame, dtx[%d], curTS[%u], current[%u]", mDtxPlayed,
+ "[Get] OK, preserved frame, dtx=%d, curTS=%u, current=%u", mDtxPlayed,
mCurrPlayingTS, currentTime);
mLastPlayedSeqNum = pEntry->nSeqNum;
@@ -574,7 +557,7 @@
if (pDataType)
*pDataType = MEDIASUBTYPE_UNDEFINED;
- IMLOGD_PACKET3(IM_PACKET_LOG_JITTER, "[Get] fail - dtx[%d], curTS[%u], current[%u]",
+ IMLOGD_PACKET3(IM_PACKET_LOG_JITTER, "[Get] fail - dtx=%d, curTS=%u, current=%u",
mDtxPlayed, mCurrPlayingTS, currentTime);
mCurrPlayingTS += FRAME_INTERVAL;
@@ -597,9 +580,9 @@
while (mDataQueue.Get(&entry) && GetCount() > spareFrames)
{
- IMLOGD6("[Resync] state[%d], seq[%d], TS[%d], dtx[%d], queue[%d], spareFrames[%d]",
- mWaiting, entry->nSeqNum, entry->nTimestamp,
- entry->eDataType == MEDIASUBTYPE_AUDIO_SID, GetCount(), spareFrames);
+ IMLOGD6("[Resync] state=%d, seq=%d, TS=%d, dtx=%d, queue=%d, spareFrames=%d", mWaiting,
+ entry->nSeqNum, entry->nTimestamp, entry->eDataType == MEDIASUBTYPE_AUDIO_SID,
+ GetCount(), spareFrames);
if (entry->eDataType != MEDIASUBTYPE_AUDIO_SID)
{
@@ -629,7 +612,7 @@
if (lostGap > 1 && lostGap < SEQ_OUTLIER_THRESHOLD)
{
uint16_t lostSeq = lastSeq + 1;
- IMLOGD_PACKET2(IM_PACKET_LOG_JITTER, "[CountLostFrames] lost seq[%u], num[%u]", lostSeq,
+ IMLOGD_PACKET2(IM_PACKET_LOG_JITTER, "[CountLostFrames] lost seq=%u, num=%u", lostSeq,
lostGap - 1);
SessionCallbackParameter* param =
@@ -663,8 +646,6 @@
void AudioJitterBuffer::CollectRxRtpStatus(int32_t seq, kRtpPacketStatus status)
{
- IMLOGD_PACKET2(IM_PACKET_LOG_JITTER, "[CollectRxRtpStatus] seq[%d], status[%d]", seq, status);
-
if (mCallback != nullptr)
{
SessionCallbackParameter* param =
@@ -675,9 +656,6 @@
void AudioJitterBuffer::CollectJitterBufferStatus(int32_t currSize, int32_t maxSize)
{
- IMLOGD_PACKET2(IM_PACKET_LOG_JITTER, "[CollectJitterBufferStatus] currSize[%d], maxSize[%d]",
- currSize, maxSize);
-
if (mCallback != nullptr)
{
mCallback->SendEvent(kCollectJitterBufferSize, currSize, maxSize);
@@ -710,7 +688,7 @@
{
*entry = nullptr;
IMLOGD_PACKET1(IM_PACKET_LOG_JITTER,
- "[GetPartialRedundancyFrame] lostSeq[%d] Redundant Frame not found", lostSeq);
+ "[GetPartialRedundancyFrame] lostSeq=%d Redundant Frame not found", lostSeq);
return false;
}
@@ -718,7 +696,7 @@
{
*entry = nullptr;
IMLOGD_PACKET1(IM_PACKET_LOG_JITTER,
- "[GetPartialRedundancyFrame] lostSeq[%d] Redundant Frame is SID", lostSeq);
+ "[GetPartialRedundancyFrame] lostSeq=%d Redundant Frame is SID", lostSeq);
return false;
}
@@ -729,7 +707,7 @@
*entry = nullptr;
IMLOGD_PACKET2(IM_PACKET_LOG_JITTER,
"[GetPartialRedundancyFrame] RF not in offset timeframe. \
- RF_timestamp[%u] LostFrame_timestamp[%u]",
+ RF_timestamp=%u LostFrame_timestamp=%u",
tempEntry->nTimestamp, currentTimestamp);
return false;
}
@@ -738,14 +716,14 @@
{
*entry = tempEntry;
IMLOGD_PACKET4(IM_PACKET_LOG_JITTER,
- "[GetPartialRedundancyFrame] lostSeq[%d] RFSeq[%d], size[%d] , curTS[%u]", lostSeq,
+ "[GetPartialRedundancyFrame] lostSeq=%d RFSeq=%d, size=%d , curTS=%u", lostSeq,
tempEntry->nSeqNum, tempEntry->nBufferSize, mCurrPlayingTS);
return true;
}
*entry = nullptr;
IMLOGD_PACKET1(IM_PACKET_LOG_JITTER,
- "[GetPartialRedundancyFrame] lostSeq[%d] Redundant Frame not found", lostSeq);
+ "[GetPartialRedundancyFrame] lostSeq=%d Redundant Frame not found", lostSeq);
return false;
}
@@ -761,7 +739,7 @@
? 1
: 0];
IMLOGD_PACKET2(IM_PACKET_LOG_JITTER,
- "[GetNextFrameFirstByte] nextSeq[%d] nextFrameFirstByte[%02X]", pEntry->nSeqNum,
+ "[GetNextFrameFirstByte] nextSeq=%d nextFrameFirstByte[%02X]", pEntry->nSeqNum,
nextFrameFirstByte[0]);
return true;
}
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 b7ce3db..b3b51bd 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
@@ -108,22 +108,22 @@
{
if ((config->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_RECEIVE ||
config->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_RECEIVE_ONLY ||
- config->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_ONLY) &&
- isOtherSessionActive(sessionId))
+ config->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_ONLY))
{
- return RESULT_NO_RESOURCES;
+ if (!deactivateOtherSessionIfActive(sessionId))
+ {
+ return RESULT_NO_RESOURCES;
+ }
+ }
+
+ if ((session->second)->IsGraphAlreadyExist(config) ||
+ (session->second)->getGraphSize(kStreamRtpTx) == 0)
+ {
+ return (session->second)->startGraph(config);
}
else
{
- if ((session->second)->IsGraphAlreadyExist(config) ||
- (session->second)->getGraphSize(kStreamRtpTx) == 0)
- {
- return (session->second)->startGraph(config);
- }
- else
- {
- return (session->second)->addGraph(config, false);
- }
+ return (session->second)->addGraph(config, false);
}
}
else
@@ -566,7 +566,7 @@
}
}
-bool AudioManager::isOtherSessionActive(const int sessionId)
+bool AudioManager::deactivateOtherSessionIfActive(const int sessionId)
{
for (auto const& session : mSessions)
{
@@ -577,9 +577,15 @@
state == kSessionStateSending)
{
IMLOGE1("[modifySession] Another session id[%d] is active", session.first);
- return true;
+ if ((session.second)->deactivate())
+ {
+ IMLOGI1("[modifySession] Moved session id[%d] to inactive", session.first);
+ return true;
+ }
+ IMLOGE1("[modifySession] Failed to move session id[%d] to inactive", session.first);
+ return false;
}
}
}
- return false;
-}
+ return true;
+}
\ No newline at end of file
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 dd763e3..c06ddc3 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
@@ -657,4 +657,34 @@
default:
break;
}
+}
+
+bool AudioSession::deactivate()
+{
+ IMLOGI0("[deactivate]");
+
+ for (auto& graph : mListGraphRtpTx)
+ {
+ if (graph != nullptr)
+ {
+ graph->stop();
+ }
+ }
+
+ for (auto& graph : mListGraphRtpRx)
+ {
+ if (graph != nullptr)
+ {
+ graph->stop();
+ }
+ }
+
+ SessionState state = getState();
+ if (state == kSessionStateActive || state == kSessionStateReceiving ||
+ state == kSessionStateSending)
+ {
+ return false;
+ }
+
+ return true;
}
\ No newline at end of file
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 7266551..0f19b63 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
@@ -109,24 +109,15 @@
}
ImsMediaResult ret = RESULT_NOT_READY;
+ bool needsToStart = false;
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);
- }
- }
- mScheduler->Start();
+ stop();
+ needsToStart = true;
}
- else if (mGraphState == kStreamStateCreated)
+
+ if (mGraphState == kStreamStateCreated)
{
for (auto& node : mListNodeToStart)
{
@@ -148,6 +139,11 @@
return start();
}
+ if (needsToStart)
+ {
+ return start();
+ }
+
return ret;
}
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 a125eae..8c84509 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
@@ -20,6 +20,7 @@
#include <AudioConfig.h>
#include <IAudioSourceNode.h>
#include <DtmfEncoderNode.h>
+#include <DtmfSenderNode.h>
#include <AudioRtpPayloadEncoderNode.h>
#include <RtpEncoderNode.h>
#include <SocketWriterNode.h>
@@ -196,9 +197,16 @@
AddNode(pDtmfEncoderNode);
mListDtmfNodes.push_back(pDtmfEncoderNode);
+ BaseNode* pDtmfSenderNode = new DtmfSenderNode(mCallback);
+ pDtmfSenderNode->SetMediaType(IMS_MEDIA_AUDIO);
+ pDtmfSenderNode->SetConfig(audioConfig);
+ pDtmfEncoderNode->ConnectRearNode(pDtmfSenderNode);
+ AddNode(pDtmfSenderNode);
+ mListDtmfNodes.push_back(pDtmfSenderNode);
+
if (rtpEncoderNode != nullptr)
{
- pDtmfEncoderNode->ConnectRearNode(rtpEncoderNode);
+ pDtmfSenderNode->ConnectRearNode(rtpEncoderNode);
}
return true;
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/MediaQualityAnalyzer.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/MediaQualityAnalyzer.cpp
index a011217..b361eb6 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/MediaQualityAnalyzer.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/MediaQualityAnalyzer.cpp
@@ -150,7 +150,7 @@
{
IMLOGD0("[start]");
mTimeStarted = ImsMediaTimer::GetTimeInMilliSeconds();
- StartThread();
+ StartThread("MediaQualityAnalyzer");
}
}
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/android/ImsMediaAudioSource.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/android/ImsMediaAudioSource.cpp
index 705bceb..b0467dd 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/android/ImsMediaAudioSource.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/android/ImsMediaAudioSource.cpp
@@ -167,7 +167,7 @@
IMLOGI1("[Start] start stream state[%s]", AAudio_convertStreamStateToText(nextState));
// start audio read thread
- StartThread();
+ StartThread("ImsMediaAudioSource");
return true;
}
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/AudioRtpPayloadDecoderNode.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/AudioRtpPayloadDecoderNode.cpp
index c284b25..d465694 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/AudioRtpPayloadDecoderNode.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/AudioRtpPayloadDecoderNode.cpp
@@ -125,7 +125,8 @@
{
if (subtype == MEDIASUBTYPE_REFRESHED)
{
- SendDataToRearNode(subtype, nullptr, nDataSize, 0, 0, 0, MEDIASUBTYPE_UNDEFINED);
+ SendDataToRearNode(
+ subtype, nullptr, nDataSize, 0, 0, 0, MEDIASUBTYPE_UNDEFINED, arrivalTime);
return;
}
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/AudioRtpPayloadEncoderNode.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/AudioRtpPayloadEncoderNode.cpp
index e342951..4bc2c43 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/AudioRtpPayloadEncoderNode.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/AudioRtpPayloadEncoderNode.cpp
@@ -96,7 +96,7 @@
{
case kAudioCodecAmr:
case kAudioCodecAmrWb:
- EncodePayloadAmr(pData, nDataSize, nTimestamp);
+ EncodePayloadAmr(pData, nDataSize, nTimestamp, arrivalTime);
break;
case kAudioCodecPcmu:
case kAudioCodecPcma:
@@ -104,7 +104,7 @@
nSeqNum, nDataType, arrivalTime);
break;
case kAudioCodecEvs:
- EncodePayloadEvs(pData, nDataSize, nTimestamp);
+ EncodePayloadEvs(pData, nDataSize, nTimestamp, arrivalTime);
break;
default:
IMLOGE1("[OnDataFromFrontNode] invalid codec type[%d]", mCodecType);
@@ -167,7 +167,7 @@
}
void AudioRtpPayloadEncoderNode::EncodePayloadAmr(
- uint8_t* pData, uint32_t nDataSize, uint32_t nTimestamp)
+ uint8_t* pData, uint32_t nDataSize, uint32_t nTimestamp, uint32_t arrivalTime)
{
uint32_t nCmr = 15;
uint32_t f, ft, q, nDataBitSize;
@@ -260,8 +260,8 @@
if (mTotalPayloadSize > 0)
{
- SendDataToRearNode(
- MEDIASUBTYPE_RTPPAYLOAD, mPayload, nTotalSize, mTimestamp, mFirstFrame, 0);
+ SendDataToRearNode(MEDIASUBTYPE_RTPPAYLOAD, mPayload, nTotalSize, mTimestamp,
+ mFirstFrame, 0, MEDIASUBTYPE_UNDEFINED, arrivalTime);
}
mCurrNumOfFrame = 0;
@@ -275,7 +275,7 @@
}
void AudioRtpPayloadEncoderNode::EncodePayloadEvs(
- uint8_t* pData, uint32_t nDataSize, uint32_t nTimeStamp)
+ uint8_t* pData, uint32_t nDataSize, uint32_t nTimeStamp, uint32_t arrivalTime)
{
if (nDataSize == 0)
{
@@ -334,8 +334,8 @@
if (mTotalPayloadSize > 0)
{
- SendDataToRearNode(
- MEDIASUBTYPE_RTPPAYLOAD, mPayload, nTotalSize, mTimestamp, mFirstFrame, 0);
+ SendDataToRearNode(MEDIASUBTYPE_RTPPAYLOAD, mPayload, nTotalSize, mTimestamp,
+ mFirstFrame, 0, MEDIASUBTYPE_UNDEFINED, arrivalTime);
}
mCurrNumOfFrame = 0;
@@ -421,8 +421,8 @@
if (mTotalPayloadSize > 0)
{
- SendDataToRearNode(
- MEDIASUBTYPE_RTPPAYLOAD, mPayload, nTotalSize, mTimestamp, mFirstFrame, 0);
+ SendDataToRearNode(MEDIASUBTYPE_RTPPAYLOAD, mPayload, nTotalSize, mTimestamp,
+ mFirstFrame, 0, MEDIASUBTYPE_UNDEFINED, arrivalTime);
}
mCurrNumOfFrame = 0;
@@ -519,7 +519,8 @@
if (mTotalPayloadSize > 0)
{
SendDataToRearNode(MEDIASUBTYPE_RTPPAYLOAD, mPayload,
- CheckPaddingNecessity(nTotalSize), mTimestamp, mFirstFrame, 0);
+ CheckPaddingNecessity(nTotalSize), mTimestamp, mFirstFrame, 0,
+ MEDIASUBTYPE_UNDEFINED, arrivalTime);
}
mCurrNumOfFrame = 0;
@@ -600,7 +601,8 @@
if (mTotalPayloadSize > 0)
{
SendDataToRearNode(MEDIASUBTYPE_RTPPAYLOAD, mPayload,
- CheckPaddingNecessity(nTotalSize), mTimestamp, mFirstFrame, 0);
+ CheckPaddingNecessity(nTotalSize), mTimestamp, mFirstFrame, 0,
+ MEDIASUBTYPE_UNDEFINED, arrivalTime);
}
mCurrNumOfFrame = 0;
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/DtmfEncoderNode.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/DtmfEncoderNode.cpp
index a3b750e..cb93606 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/DtmfEncoderNode.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/DtmfEncoderNode.cpp
@@ -51,7 +51,7 @@
{
mAudioFrameDuration = mSamplingRate * mPtime;
IMLOGD1("[Start] interval[%d]", mAudioFrameDuration);
- StartThread();
+ StartThread("DtmfEncoderNode");
mNodeState = kNodeStateRunning;
return RESULT_SUCCESS;
}
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/DtmfSenderNode.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/DtmfSenderNode.cpp
new file mode 100644
index 0000000..d7d1120
--- /dev/null
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/DtmfSenderNode.cpp
@@ -0,0 +1,128 @@
+/**
+ * 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 <ImsMediaDefine.h>
+#include <ImsMediaTrace.h>
+#include <DtmfSenderNode.h>
+#include <ImsMediaTimer.h>
+#include <AudioConfig.h>
+
+DtmfSenderNode::DtmfSenderNode(BaseSessionCallback* callback) :
+ BaseNode(callback)
+{
+ mNextTime = 0;
+ mPrevTime = 0;
+ mPtime = 20;
+}
+
+DtmfSenderNode::~DtmfSenderNode() {}
+
+kBaseNodeId DtmfSenderNode::GetNodeId()
+{
+ return kNodeIdDtmfSender;
+}
+
+ImsMediaResult DtmfSenderNode::Start()
+{
+ mNextTime = 0;
+ mNodeState = kNodeStateRunning;
+ return RESULT_SUCCESS;
+}
+
+void DtmfSenderNode::Stop()
+{
+ mNextTime = 0;
+ ClearDataQueue();
+ mNodeState = kNodeStateStopped;
+}
+
+bool DtmfSenderNode::IsRunTime()
+{
+ return false;
+}
+
+bool DtmfSenderNode::IsSourceNode()
+{
+ return false;
+}
+
+void DtmfSenderNode::SetConfig(void* config)
+{
+ AudioConfig* pConfig = reinterpret_cast<AudioConfig*>(config);
+
+ if (pConfig != nullptr)
+ {
+ mPtime = pConfig->getPtimeMillis();
+ }
+}
+
+bool DtmfSenderNode::IsSameConfig(void* config)
+{
+ if (config == nullptr)
+ {
+ return true;
+ }
+
+ AudioConfig* pConfig = reinterpret_cast<AudioConfig*>(config);
+ return (mPtime == pConfig->getPtimeMillis());
+}
+
+void DtmfSenderNode::ProcessData()
+{
+ ImsMediaSubType subtype;
+ uint8_t* data;
+ uint32_t size;
+ uint32_t timestamp;
+ bool bMark;
+ uint32_t currTime;
+
+ if (GetData(&subtype, &data, &size, ×tamp, &bMark, nullptr) == false)
+ {
+ return;
+ }
+
+ currTime = ImsMediaTimer::GetTimeInMilliSeconds();
+
+ if (mNextTime && !(currTime >= mNextTime || currTime < mPrevTime || mNextTime < mPrevTime))
+ {
+ mPrevTime = currTime;
+ return;
+ }
+
+ if (subtype == MEDIASUBTYPE_DTMFSTART)
+ {
+ SendDataToRearNode(subtype, data, size, currTime, bMark, 0);
+ DeleteData();
+ mNextTime = currTime;
+
+ // send the first dtmf packet
+ if (GetData(&subtype, &data, &size, ×tamp, &bMark, nullptr, nullptr) &&
+ subtype == MEDIASUBTYPE_DTMF_PAYLOAD)
+ {
+ SendDataToRearNode(subtype, data, size, currTime, bMark, 0);
+ DeleteData();
+ mNextTime += mPtime;
+ }
+ }
+ else
+ {
+ SendDataToRearNode(subtype, data, size, currTime, bMark, 0);
+ DeleteData();
+ mNextTime += mPtime;
+ }
+
+ mPrevTime = currTime;
+}
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/IAudioPlayerNode.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/IAudioPlayerNode.cpp
index fbc04a9..5fdc9d9 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/IAudioPlayerNode.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/IAudioPlayerNode.cpp
@@ -27,7 +27,7 @@
#define MAX_CODEC_EVS_AMR_IO_MODE 9
#define JITTER_BUFFER_SIZE_INIT 3
#define JITTER_BUFFER_SIZE_MIN 3
-#define JITTER_BUFFER_SIZE_MAX 13
+#define JITTER_BUFFER_SIZE_MAX 11
IAudioPlayerNode::IAudioPlayerNode(BaseSessionCallback* callback) :
JitterBufferControlNode(callback, IMS_MEDIA_AUDIO)
@@ -95,7 +95,7 @@
}
mNodeState = kNodeStateRunning;
- StartThread();
+ StartThread("IAudioPlayerNode");
return RESULT_SUCCESS;
}
@@ -297,7 +297,7 @@
void* IAudioPlayerNode::run()
{
IMLOGD0("[run] enter");
- SetAudioThreadPriority(gettid());
+ SetThreadPriority(getpid(), gettid(), THREAD_PRIORITY_REALTIME);
ImsMediaSubType subtype = MEDIASUBTYPE_UNDEFINED;
ImsMediaSubType datatype = MEDIASUBTYPE_UNDEFINED;
uint8_t* data = nullptr;
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/IAudioSourceNode.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/IAudioSourceNode.cpp
index 89a14b8..51de7fd 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/IAudioSourceNode.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/IAudioSourceNode.cpp
@@ -18,6 +18,7 @@
#include <ImsMediaAudioSource.h>
#include <ImsMediaTrace.h>
#include <ImsMediaAudioUtil.h>
+#include <ImsMediaTimer.h>
#include <string.h>
#include <AudioConfig.h>
#include <RtpConfig.h>
@@ -181,8 +182,8 @@
{
IMLOGD_PACKET3(IM_PACKET_LOG_AUDIO, "[onDataFrame] size[%zu], TS[%ld], flag[%d]", size,
timestamp, flag);
- SendDataToRearNode(
- MEDIASUBTYPE_UNDEFINED, buffer, size, timestamp, !mFirstFrame, MEDIASUBTYPE_UNDEFINED);
+ SendDataToRearNode(MEDIASUBTYPE_UNDEFINED, buffer, size, ImsMediaTimer::GetTimeInMilliSeconds(),
+ !mFirstFrame, 0, MEDIASUBTYPE_UNDEFINED, ImsMediaTimer::GetTimeInMilliSeconds());
if (!mFirstFrame)
{
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/JitterNetworkAnalyser.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/JitterNetworkAnalyser.h
index 77a8910..1de0e7e 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/JitterNetworkAnalyser.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/JitterNetworkAnalyser.h
@@ -73,8 +73,11 @@
std::mutex mMutex;
uint32_t mMinJitterBufferSize;
uint32_t mMaxJitterBufferSize;
- std::map<int32_t, int32_t> mMapDelta;
- std::list<int32_t> mListJitters;
+ uint32_t mPrevTimestamp;
+ uint32_t mPrevArrivalTime;
+ std::list<int32_t> mListAccumDeltas;
+ int32_t mPrevDelta;
+ int32_t minJitterInBeginning;
uint32_t mTimeLateArrivals;
NETWORK_STATUS mNetworkStatus;
uint32_t mGoodStatusEnteringTime;
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioManager.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioManager.h
index d0f9fce..17a1ebd 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioManager.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioManager.h
@@ -71,7 +71,7 @@
virtual void setMediaQualityThreshold(int sessionId, MediaQualityThreshold* threshold);
virtual void SendInternalEvent(
uint32_t event, uint64_t sessionId, uint64_t paramA, uint64_t paramB);
- virtual bool isOtherSessionActive(const int sessionId);
+ virtual bool deactivateOtherSessionIfActive(const int sessionId);
static AudioManager* sManager;
std::unordered_map<int, std::unique_ptr<AudioSession>> mSessions;
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 ac29bfd..40e8313 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
@@ -111,6 +111,13 @@
*/
void sendRtpHeaderExtension(std::list<RtpHeaderExtension>* listExtension);
+ /**
+ * @brief Move session to inactive. i.e., Rtp Tx and Rtp Rx graphs are stopped
+ *
+ * @return bool false if failed to move session to inactive
+ */
+ bool deactivate();
+
private:
std::list<AudioStreamGraphRtpTx*> mListGraphRtpTx;
std::list<AudioStreamGraphRtpRx*> mListGraphRtpRx;
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 36d1b6e..1b7d2c1 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
@@ -35,7 +35,7 @@
*
* @param config AudioConfig for setting the parameters for nodes
* @param rtpEncoderNode The RtpEncoderNode instance to connect as a rear node after the
- * DtmfEncoderNode, if it is null, no dtmf packet will be delivered to RtpEncoderNode.
+ * DtmfSenderNode, if it is null, no dtmf packet will be delivered to RtpEncoderNode.
* @return true Returns when the graph created without error
* @return false Returns when the given parameters are invalid.
*/
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/nodes/AudioRtpPayloadEncoderNode.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/nodes/AudioRtpPayloadEncoderNode.h
index cc3be7f..482e5da 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/nodes/AudioRtpPayloadEncoderNode.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/nodes/AudioRtpPayloadEncoderNode.h
@@ -38,8 +38,10 @@
virtual bool IsSameConfig(void* config);
private:
- void EncodePayloadAmr(uint8_t* pData, uint32_t nDataSize, uint32_t nTimestamp);
- void EncodePayloadEvs(uint8_t* pData, uint32_t nDataSize, uint32_t nTimeStamp);
+ void EncodePayloadAmr(
+ uint8_t* pData, uint32_t nDataSize, uint32_t nTimestamp, uint32_t arrivalTime);
+ void EncodePayloadEvs(
+ uint8_t* pData, uint32_t nDataSize, uint32_t nTimeStamp, uint32_t arrivalTime);
uint32_t CheckPaddingNecessity(uint32_t nTotalSize);
int32_t mCodecType;
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/nodes/DtmfSenderNode.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/nodes/DtmfSenderNode.h
new file mode 100644
index 0000000..7057676
--- /dev/null
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/nodes/DtmfSenderNode.h
@@ -0,0 +1,43 @@
+/**
+ * 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.
+ */
+
+#ifndef DTMFSENDERNODE_H_INCLUDED
+#define DTMFSENDERNODE_H_INCLUDED
+
+#include <ImsMediaDefine.h>
+#include <BaseNode.h>
+
+class DtmfSenderNode : public BaseNode
+{
+public:
+ DtmfSenderNode(BaseSessionCallback* callback = nullptr);
+ virtual ~DtmfSenderNode();
+ virtual kBaseNodeId GetNodeId();
+ virtual ImsMediaResult Start();
+ virtual void Stop();
+ virtual bool IsRunTime();
+ virtual bool IsSourceNode();
+ virtual void SetConfig(void* config);
+ virtual bool IsSameConfig(void* config);
+ virtual void ProcessData();
+
+private:
+ uint32_t mNextTime;
+ uint32_t mPrevTime;
+ int8_t mPtime; // msec unit, interval between dtmf packets
+};
+
+#endif // DTMFSENDERNODE_H_INCLUDED
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/nodes/BaseNode.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/nodes/BaseNode.h
index 8f99c98..f9e0d5b 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/nodes/BaseNode.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/nodes/BaseNode.h
@@ -49,6 +49,7 @@
kNodeIdAudioSource,
kNodeIdAudioPlayer,
kNodeIdDtmfEncoder,
+ kNodeIdDtmfSender,
kNodeIdAudioPayloadEncoder,
kNodeIdAudioPayloadDecoder,
// for Video
@@ -142,7 +143,7 @@
/**
* @brief Checks the node processes data in main thread.
*/
- virtual bool IsRunTime() = 0;
+ virtual bool IsRunTime();
/**
* @brief Checks the node to start in main thread
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/nodes/RtpEncoderNode.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/nodes/RtpEncoderNode.h
index d1446f2..f53829a 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/nodes/RtpEncoderNode.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/nodes/RtpEncoderNode.h
@@ -31,13 +31,15 @@
virtual kBaseNodeId GetNodeId();
virtual ImsMediaResult Start();
virtual void Stop();
- virtual void ProcessData();
- virtual bool IsRunTime();
+ virtual void OnDataFromFrontNode(ImsMediaSubType subtype, uint8_t* data, uint32_t size,
+ uint32_t timestamp, bool mark, uint32_t seq,
+ ImsMediaSubType dataType = ImsMediaSubType::MEDIASUBTYPE_UNDEFINED,
+ uint32_t arrivalTime = 0);
virtual bool IsSourceNode();
virtual void SetConfig(void* config);
virtual bool IsSameConfig(void* config);
// IRtpEncoderListener method
- virtual void OnRtpPacket(unsigned char* pData, uint32_t nSize);
+ virtual void OnRtpPacket(unsigned char* data, uint32_t nSize);
/**
* @brief Set the local ip address and port number
@@ -76,17 +78,18 @@
void GetRtpContext(RtpContextParams& rtpContextParams);
private:
- bool ProcessAudioData(ImsMediaSubType subtype, uint8_t* pData, uint32_t nDataSize);
- void ProcessVideoData(ImsMediaSubType subtype, uint8_t* pData, uint32_t nDataSize,
- uint32_t timestamp, bool mark);
- void ProcessTextData(ImsMediaSubType subtype, uint8_t* pData, uint32_t nDataSize,
- uint32_t timestamp, bool mark);
+ void ProcessAudioData(
+ ImsMediaSubType subtype, uint8_t* data, uint32_t size, uint32_t timestamp);
+ void ProcessVideoData(
+ ImsMediaSubType subtype, uint8_t* data, uint32_t size, uint32_t timestamp, bool mark);
+ void ProcessTextData(
+ ImsMediaSubType subtype, uint8_t* data, uint32_t size, uint32_t timestamp, bool mark);
IRtpSession* mRtpSession;
std::mutex mMutex;
RtpAddress mLocalAddress;
RtpAddress mPeerAddress;
- bool mDTMFMode;
+ bool mDtmfMode;
bool mMark;
uint32_t mPrevTimestamp;
int8_t mSamplingRate;
@@ -101,6 +104,7 @@
int8_t mRedundantLevel;
std::list<RtpHeaderExtensionInfo> mListRtpExtension;
RtpContextParams mRtpContextParams;
+ int32_t mArrivalTime;
};
#endif
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/nodes/SocketReaderNode.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/nodes/SocketReaderNode.h
index 15d13a1..37892bb 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/nodes/SocketReaderNode.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/nodes/SocketReaderNode.h
@@ -30,7 +30,6 @@
virtual bool Prepare();
virtual ImsMediaResult Start();
virtual void Stop();
- virtual void ProcessData();
virtual bool IsRunTime();
virtual bool IsSourceNode();
void SetConfig(void* config);
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/text/TextManager.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/text/TextManager.h
index f9e158a..f23ac8f 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/text/TextManager.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/text/TextManager.h
@@ -62,12 +62,12 @@
ImsMediaResult openSession(
const int sessionId, const int rtpFd, const int rtcpFd, TextConfig* config);
ImsMediaResult closeSession(const int sessionId);
- virtual bool isOtherSessionActive(const int sessionId);
+ virtual bool deactivateOtherSessionIfActive(const int sessionId);
ImsMediaResult modifySession(const int sessionId, TextConfig* config);
virtual void setMediaQualityThreshold(const int sessionId, MediaQualityThreshold* threshold);
virtual ImsMediaResult sendRtt(const int sessionId, const android::String8* text);
- static TextManager* manager;
+ static TextManager* sManager;
std::unordered_map<int, std::unique_ptr<TextSession>> mSessions;
RequestHandler mRequestHandler;
ResponseHandler mResponseHandler;
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/text/TextSession.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/text/TextSession.h
index 25e05a6..ea1c636 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/text/TextSession.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/text/TextSession.h
@@ -35,6 +35,13 @@
virtual void onEvent(int32_t type, uint64_t param1, uint64_t param2);
ImsMediaResult sendRtt(const android::String8* text);
+ /**
+ * @brief move session to inactive. i.e., Rtp Tx and Rtp Rx graphs are stopped
+ *
+ * @return bool false if failed to move session to inactive
+ */
+ bool deactivate();
+
private:
TextStreamGraphRtpTx* mGraphRtpTx;
TextStreamGraphRtpRx* mGraphRtpRx;
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/utils/IImsMediaThread.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/utils/IImsMediaThread.h
index 8c2012c..45ffb84 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/utils/IImsMediaThread.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/utils/IImsMediaThread.h
@@ -21,6 +21,9 @@
#define MAX_EVENTHANDLER_NAME 256
+// Thread priority value used with SCH_FIFO scheduling policy to set Real-Time priority.
+#define THREAD_PRIORITY_REALTIME 2
+
/**
* @class IImsMediaThread
* @brief Base class of thread
@@ -32,8 +35,8 @@
public:
IImsMediaThread();
virtual ~IImsMediaThread();
- bool StartThread();
- void SetAudioThreadPriority(pid_t tid);
+ bool StartThread(const char* name = nullptr);
+ static void SetThreadPriority(pid_t pid, pid_t tid, int priority);
void StopThread();
bool IsThreadStopped();
void* runBase();
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/VideoManager.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/VideoManager.h
index 91c2747..4b04baf 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/VideoManager.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/VideoManager.h
@@ -78,21 +78,21 @@
* @param event The event type
* @param sessionId The session id
*/
- void SendInternalEvent(
+ virtual void SendInternalEvent(
uint32_t event, uint64_t sessionId, uint64_t paramA = 0, uint64_t paramB = 0);
-private:
+protected:
VideoManager();
virtual ~VideoManager();
ImsMediaResult openSession(
const int sessionId, const int rtpFd, const int rtcpFd, VideoConfig* config);
ImsMediaResult closeSession(const int sessionId);
- ImsMediaResult setPreviewSurfaceToSession(const int sessionId, ANativeWindow* surface);
- ImsMediaResult setDisplaySurfaceToSession(const int sessionId, ANativeWindow* surface);
+ virtual ImsMediaResult setPreviewSurfaceToSession(const int sessionId, ANativeWindow* surface);
+ virtual ImsMediaResult setDisplaySurfaceToSession(const int sessionId, ANativeWindow* surface);
ImsMediaResult modifySession(const int sessionId, VideoConfig* config);
- void setMediaQualityThreshold(const int sessionId, MediaQualityThreshold* threshold);
+ virtual void setMediaQualityThreshold(const int sessionId, MediaQualityThreshold* threshold);
- static VideoManager* manager;
+ static VideoManager* sManager;
std::unordered_map<int, std::unique_ptr<VideoSession>> mSessions;
RequestHandler mRequestHandler;
ResponseHandler mResponseHandler;
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/BaseNode.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/BaseNode.cpp
index 97e388c..d3d797f 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/BaseNode.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/BaseNode.cpp
@@ -30,6 +30,7 @@
std::make_pair(kNodeIdAudioSource, "AudioSource"),
std::make_pair(kNodeIdAudioPlayer, "AudioPlayer"),
std::make_pair(kNodeIdDtmfEncoder, "DtmfEncoder"),
+ std::make_pair(kNodeIdDtmfSender, "DtmfSender"),
std::make_pair(kNodeIdAudioPayloadEncoder, "AudioPayloadEncoder"),
std::make_pair(kNodeIdAudioPayloadDecoder, "AudioPayloadDecoder"),
std::make_pair(kNodeIdVideoSource, "VideoSource"),
@@ -129,6 +130,11 @@
return RESULT_NOT_SUPPORTED;
}
+bool BaseNode::IsRunTime()
+{
+ return true;
+}
+
bool BaseNode::IsRunTimeStart()
{
return true;
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtcpEncoderNode.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtcpEncoderNode.cpp
index 35b4acb..cbdc703 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtcpEncoderNode.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtcpEncoderNode.cpp
@@ -92,13 +92,6 @@
void RtcpEncoderNode::Stop()
{
IMLOGD0("[Stop]");
- std::lock_guard<std::mutex> guard(mMutexTimer);
-
- if (mRtpSession != nullptr)
- {
- mRtpSession->StopRtcp();
- }
-
if (mTimer != nullptr)
{
ImsMediaTimer::TimerStop(mTimer, nullptr);
@@ -106,7 +99,17 @@
IMLOGD0("[Stop] Rtcp Timer stopped");
}
- mNodeState = kNodeStateStopped;
+ {
+ std::lock_guard<std::mutex> guard(mMutexTimer);
+ IMLOGD0("[Stop] mutex taken");
+
+ if (mRtpSession != nullptr)
+ {
+ mRtpSession->StopRtcp();
+ }
+
+ mNodeState = kNodeStateStopped;
+ }
}
bool RtcpEncoderNode::IsRunTime()
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtpDecoderNode.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtpDecoderNode.cpp
index e391952..c36de00 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtpDecoderNode.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtpDecoderNode.cpp
@@ -430,7 +430,8 @@
IMLOGI3("[OnMediaDataInd] media[%d] SSRC changed, [%x] -> [%x]", mMediaType, mReceivingSSRC,
ssrc);
mReceivingSSRC = ssrc;
- SendDataToRearNode(MEDIASUBTYPE_REFRESHED, nullptr, mReceivingSSRC, 0, 0, 0);
+ SendDataToRearNode(MEDIASUBTYPE_REFRESHED, nullptr, mReceivingSSRC, 0, 0, 0,
+ MEDIASUBTYPE_UNDEFINED, mArrivalTime);
}
if (mMediaType == IMS_MEDIA_AUDIO &&
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtpEncoderNode.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtpEncoderNode.cpp
index 2b2b705..930c5d4 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtpEncoderNode.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtpEncoderNode.cpp
@@ -27,7 +27,7 @@
BaseNode(callback)
{
mRtpSession = nullptr;
- mDTMFMode = false;
+ mDtmfMode = false;
mMark = false;
mPrevTimestamp = 0;
mSamplingRate = 0;
@@ -62,7 +62,6 @@
ImsMediaResult RtpEncoderNode::Start()
{
IMLOGD1("[Start] type[%d]", mMediaType);
- bool bResetSsrc = false;
if (mRtpPayloadTx == 0 || mRtpPayloadRx == 0)
{
@@ -94,7 +93,6 @@
}
else if (mMediaType == IMS_MEDIA_TEXT)
{
- bResetSsrc = true;
if (mRedundantPayload > 0)
{
mRtpSession->SetRtpPayloadParam(mRtpPayloadTx, mRtpPayloadRx, mSamplingRate * 1000,
@@ -113,8 +111,8 @@
}
}
- mRtpSession->StartRtp(bResetSsrc);
- mDTMFMode = false;
+ mRtpSession->StartRtp();
+ mDtmfMode = false;
mMark = true;
mPrevTimestamp = 0;
#ifdef DEBUG_JITTER_GEN_SIMULATION_DELAY
@@ -131,7 +129,6 @@
void RtpEncoderNode::Stop()
{
IMLOGD1("[Stop] type[%d]", mMediaType);
- std::lock_guard<std::mutex> guard(mMutex);
if (mRtpSession)
{
@@ -144,49 +141,28 @@
mNodeState = kNodeStateStopped;
}
-void RtpEncoderNode::ProcessData()
+void RtpEncoderNode::OnDataFromFrontNode(ImsMediaSubType subtype, uint8_t* data, uint32_t size,
+ uint32_t timestamp, bool mark, uint32_t /*seq*/, ImsMediaSubType /*dataType*/,
+ uint32_t arrivalTime)
{
- std::lock_guard<std::mutex> guard(mMutex);
-
if (mNodeState != kNodeStateRunning)
{
return;
}
- ImsMediaSubType subtype;
- uint8_t* data = nullptr;
- uint32_t size = 0;
- uint32_t timestamp = 0;
- bool mark = false;
- uint32_t seq = 0;
- ImsMediaSubType datatype;
- uint32_t arrivalTime = 0;
-
- if (GetData(&subtype, &data, &size, ×tamp, &mark, &seq, &datatype, &arrivalTime))
+ if (mMediaType == IMS_MEDIA_AUDIO)
{
- if (mMediaType == IMS_MEDIA_AUDIO)
- {
- if (!ProcessAudioData(subtype, data, size))
- {
- return;
- }
- }
- else if (mMediaType == IMS_MEDIA_VIDEO)
- {
- ProcessVideoData(subtype, data, size, timestamp, mark);
- }
- else if (mMediaType == IMS_MEDIA_TEXT)
- {
- ProcessTextData(subtype, data, size, timestamp, mark);
- }
-
- DeleteData();
+ mArrivalTime = arrivalTime;
+ ProcessAudioData(subtype, data, size, timestamp);
}
-}
-
-bool RtpEncoderNode::IsRunTime()
-{
- return false;
+ else if (mMediaType == IMS_MEDIA_VIDEO)
+ {
+ ProcessVideoData(subtype, data, size, timestamp, mark);
+ }
+ else if (mMediaType == IMS_MEDIA_TEXT)
+ {
+ ProcessTextData(subtype, data, size, timestamp, mark);
+ }
}
bool RtpEncoderNode::IsSourceNode()
@@ -292,7 +268,8 @@
void RtpEncoderNode::OnRtpPacket(unsigned char* data, uint32_t nSize)
{
- SendDataToRearNode(MEDIASUBTYPE_RTPPACKET, data, nSize, 0, 0, 0);
+ SendDataToRearNode(
+ MEDIASUBTYPE_RTPPACKET, data, nSize, 0, 0, 0, MEDIASUBTYPE_UNDEFINED, mArrivalTime);
}
void RtpEncoderNode::SetLocalAddress(const RtpAddress& address)
@@ -437,42 +414,37 @@
delete[] extensionData;
}
-bool RtpEncoderNode::ProcessAudioData(ImsMediaSubType subtype, uint8_t* data, uint32_t size)
+void RtpEncoderNode::ProcessAudioData(
+ ImsMediaSubType subtype, uint8_t* data, uint32_t size, uint32_t timestamp)
{
- uint32_t currentTimestamp;
+ std::lock_guard<std::mutex> guard(mMutex);
+
uint32_t timeDiff;
uint32_t timestampDiff;
if (subtype == MEDIASUBTYPE_DTMFSTART)
{
IMLOGD0("[ProcessAudioData] SetDTMF mode true");
- mDTMFMode = true;
+ mDtmfMode = true;
mMark = true;
}
else if (subtype == MEDIASUBTYPE_DTMFEND)
{
IMLOGD0("[ProcessAudioData] SetDTMF mode false");
- mDTMFMode = false;
+ mDtmfMode = false;
mMark = true;
}
else if (subtype == MEDIASUBTYPE_DTMF_PAYLOAD)
{
- if (mDTMFMode)
+ if (mDtmfMode)
{
- currentTimestamp = ImsMediaTimer::GetTimeInMilliSeconds();
- timeDiff = currentTimestamp - mPrevTimestamp;
-
- if (timeDiff < 20)
- {
- return false;
- }
-
- mMark ? mDtmfTimestamp = currentTimestamp : timeDiff = 0;
- mPrevTimestamp = currentTimestamp;
+ timeDiff = timestamp - mPrevTimestamp;
+ mMark ? mDtmfTimestamp = timestamp : timeDiff = 0;
+ mPrevTimestamp = timestamp;
timestampDiff = timeDiff * mSamplingRate;
IMLOGD_PACKET3(IM_PACKET_LOG_RTP,
- "[ProcessAudioData] dtmf payload, size[%u], TS[%u], diff[%d]", size,
+ "[ProcessAudioData] dtmf payload, size[%u], TS[%u], diff[%u]", size,
mDtmfTimestamp, timestampDiff);
mRtpSession->SendRtpPacket(
mRtpTxDtmfPayload, data, size, mDtmfTimestamp, mMark, timestampDiff);
@@ -481,32 +453,10 @@
}
else // MEDIASUBTYPE_RTPPAYLOAD
{
- if (mDTMFMode == false)
+ if (!mDtmfMode)
{
- currentTimestamp = ImsMediaTimer::GetTimeInMilliSeconds();
-
- if (mPrevTimestamp == 0)
- {
- timeDiff = 0;
- mPrevTimestamp = currentTimestamp;
- }
- else
- {
- timeDiff = ((currentTimestamp - mPrevTimestamp) + 5) / 20 * 20;
-
- if (timeDiff > 20)
- {
- mPrevTimestamp = currentTimestamp;
- }
- else if (timeDiff == 0)
- {
- return false;
- }
- else
- {
- mPrevTimestamp += timeDiff;
- }
- }
+ timeDiff = mPrevTimestamp == 0 ? 0 : ((timestamp - mPrevTimestamp) + 10) / 20 * 20;
+ mPrevTimestamp = timestamp;
RtpPacket* packet = new RtpPacket();
packet->rtpDataType = kRtpDataTypeNormal;
@@ -514,19 +464,19 @@
kCollectPacketInfo, kStreamRtpTx, reinterpret_cast<uint64_t>(packet));
timestampDiff = timeDiff * mSamplingRate;
- IMLOGD_PACKET3(IM_PACKET_LOG_RTP, "[ProcessAudioData] size[%u], TS[%u], diff[%d]", size,
- currentTimestamp, timestampDiff);
+ IMLOGD_PACKET3(IM_PACKET_LOG_RTP, "[ProcessAudioData] size[%u], TS[%u], diff[%u]", size,
+ timestamp, timestampDiff);
if (!mListRtpExtension.empty())
{
- mRtpSession->SendRtpPacket(mRtpPayloadTx, data, size, currentTimestamp, mMark,
+ mRtpSession->SendRtpPacket(mRtpPayloadTx, data, size, timestamp, mMark,
timestampDiff, &mListRtpExtension.front());
mListRtpExtension.pop_front();
}
else
{
mRtpSession->SendRtpPacket(
- mRtpPayloadTx, data, size, currentTimestamp, mMark, timestampDiff);
+ mRtpPayloadTx, data, size, timestamp, mMark, timestampDiff);
}
if (mMark)
@@ -535,8 +485,6 @@
}
}
}
-
- return true;
}
void RtpEncoderNode::ProcessVideoData(
@@ -573,16 +521,7 @@
"[ProcessTextData] subtype[%d], size[%d], timestamp[%d], mark[%d]", subtype, size,
timestamp, mark);
- uint32_t timeDiff;
-
- if (mMark == true)
- {
- timeDiff = 0;
- }
- else
- {
- timeDiff = timestamp - mPrevTimestamp;
- }
+ uint32_t timeDiff = mMark ? 0 : timestamp - mPrevTimestamp;
if (subtype == MEDIASUBTYPE_BITSTREAM_T140)
{
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/SocketReaderNode.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/SocketReaderNode.cpp
index 549056d..4bd392b 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/SocketReaderNode.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/SocketReaderNode.cpp
@@ -53,8 +53,6 @@
ImsMediaResult SocketReaderNode::Start()
{
- ClearDataQueue(); // clear the old data stacked
-
if (mSocketOpened)
{
IMLOGD0("[Start] opened already");
@@ -74,34 +72,13 @@
void SocketReaderNode::Stop()
{
IMLOGD2("[Stop] media[%d], protocolType[%d]", mMediaType, mProtocolType);
+ std::lock_guard<std::mutex> guard(mMutex);
mNodeState = kNodeStateStopped;
}
-void SocketReaderNode::ProcessData()
-{
- uint8_t* data = nullptr;
- uint32_t dataSize = 0;
- uint32_t timeStamp = 0;
- bool bMark = false;
- uint32_t seqNum = 0;
- ImsMediaSubType subtype;
- ImsMediaSubType dataType;
- uint32_t arrivalTime;
-
- while (GetData(
- &subtype, &data, &dataSize, &timeStamp, &bMark, &seqNum, &dataType, &arrivalTime))
- {
- IMLOGD_PACKET3(IM_PACKET_LOG_SOCKET, "[ProcessData] media[%d], size[%d], arrivalTime[%u]",
- mMediaType, dataSize, arrivalTime);
- SendDataToRearNode(MEDIASUBTYPE_UNDEFINED, reinterpret_cast<uint8_t*>(data), dataSize,
- timeStamp, bMark, seqNum, dataType, arrivalTime);
- DeleteData();
- }
-}
-
bool SocketReaderNode::IsRunTime()
{
- return false;
+ return true;
}
bool SocketReaderNode::IsSourceNode()
@@ -198,27 +175,22 @@
void SocketReaderNode::OnReadDataFromSocket()
{
- IMLOGD_PACKET1(IM_PACKET_LOG_SOCKET, "[OnReadDataFromSocket] media[%d]", mMediaType);
std::lock_guard<std::mutex> guard(mMutex);
- // prevent infinite frame stacked in the queue
- if (mDataQueue.GetCount() > MAX_BUFFER_QUEUE)
- {
- mDataQueue.Delete();
- }
-
if (mSocketOpened && mSocket != nullptr)
{
- int nLen = mSocket->ReceiveFrom(mBuffer, DEFAULT_MTU);
+ int len = mSocket->ReceiveFrom(mBuffer, DEFAULT_MTU);
- if (nLen > 0)
+ if (len > 0)
{
- IMLOGD_PACKET3(IM_PACKET_LOG_SOCKET,
- "[OnReadDataFromSocket] media[%d], data size[%d], queue size[%d]", mMediaType,
- nLen, GetDataCount());
+ IMLOGD_PACKET2(IM_PACKET_LOG_SOCKET, "[OnReadDataFromSocket] media[%d], data size[%d]",
+ mMediaType, len);
- OnDataFromFrontNode(MEDIASUBTYPE_UNDEFINED, mBuffer, nLen, 0, 0, 0,
- MEDIASUBTYPE_UNDEFINED, ImsMediaTimer::GetTimeInMilliSeconds());
+ if (mNodeState == kNodeStateRunning)
+ {
+ SendDataToRearNode(MEDIASUBTYPE_UNDEFINED, mBuffer, len, 0, 0, 0,
+ MEDIASUBTYPE_UNDEFINED, ImsMediaTimer::GetTimeInMilliSeconds());
+ }
}
}
}
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/SocketWriterNode.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/SocketWriterNode.cpp
index f2437ea..1947869 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/SocketWriterNode.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/SocketWriterNode.cpp
@@ -16,6 +16,7 @@
#include <SocketWriterNode.h>
#include <ImsMediaTrace.h>
+#include <ImsMediaTimer.h>
SocketWriterNode::SocketWriterNode(BaseSessionCallback* callback) :
BaseNode(callback)
@@ -140,21 +141,18 @@
}
void SocketWriterNode::OnDataFromFrontNode(ImsMediaSubType subtype, uint8_t* pData,
- uint32_t nDataSize, uint32_t nTimestamp, bool bMark, uint32_t nSeqNum,
- ImsMediaSubType nDataType, uint32_t arrivalTime)
+ uint32_t nDataSize, uint32_t nTimestamp, bool /*bMark*/, uint32_t nSeqNum,
+ ImsMediaSubType /*nDataType*/, uint32_t arrivalTime)
{
- (void)nDataType;
- (void)bMark;
- (void)arrivalTime;
-
if (mDisableSocket == true && subtype != MEDIASUBTYPE_RTCPPACKET_BYE)
{
IMLOGW3("[OnDataFromFrontNode] media[%d] subtype[%d] socket is disabled, bytes[%d]",
mMediaType, subtype, nDataSize);
}
- IMLOGD_PACKET3(IM_PACKET_LOG_SOCKET, "[OnDataFromFrontNode] TS[%d], SeqNum[%u], size[%u]",
- nTimestamp, nSeqNum, nDataSize);
+ IMLOGD_PACKET4(IM_PACKET_LOG_SOCKET,
+ "[OnDataFromFrontNode] TS[%d], SeqNum[%u], size[%u], timeDiff[%d]", nTimestamp, nSeqNum,
+ nDataSize, arrivalTime != 0 ? ImsMediaTimer::GetTimeInMilliSeconds() - arrivalTime : 0);
if (mSocket == nullptr)
{
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/text/TextManager.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/text/TextManager.cpp
index 8bff99b..54ca008 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/text/TextManager.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/text/TextManager.cpp
@@ -19,7 +19,7 @@
#include <ImsMediaNetworkUtil.h>
using namespace android;
-TextManager* TextManager::manager;
+TextManager* TextManager::sManager;
TextManager::TextManager()
{
@@ -31,17 +31,17 @@
{
mRequestHandler.Deinit();
mResponseHandler.Deinit();
- manager = nullptr;
+ sManager = nullptr;
}
TextManager* TextManager::getInstance()
{
- if (manager == nullptr)
+ if (sManager == nullptr)
{
- manager = new TextManager();
+ sManager = new TextManager();
}
- return manager;
+ return sManager;
}
int TextManager::getState(int sessionId)
@@ -111,15 +111,15 @@
{
if ((config->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_RECEIVE ||
config->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_RECEIVE_ONLY ||
- config->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_ONLY) &&
- isOtherSessionActive(sessionId))
+ config->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_ONLY))
{
- return RESULT_NO_RESOURCES;
+ if (!deactivateOtherSessionIfActive(sessionId))
+ {
+ return RESULT_NO_RESOURCES;
+ }
}
- else
- {
- return (session->second)->startGraph(config);
- }
+
+ return (session->second)->startGraph(config);
}
else
{
@@ -224,6 +224,12 @@
{
IMLOGI4("[processEvent] event[%d], sessionId[%d], paramA[%d], paramB[%d]", event, sessionId,
paramA, paramB);
+
+ if (sManager == nullptr)
+ {
+ return;
+ }
+
ImsMediaResult result = RESULT_SUCCESS;
switch (event)
@@ -234,7 +240,7 @@
if (param != nullptr)
{
TextConfig* pConfig = reinterpret_cast<TextConfig*>(param->mConfig);
- result = TextManager::getInstance()->openSession(
+ result = sManager->openSession(
static_cast<int>(sessionId), param->rtpFd, param->rtcpFd, pConfig);
if (result == RESULT_SUCCESS)
@@ -263,8 +269,7 @@
}
break;
case kTextCloseSession:
- if (TextManager::getInstance()->closeSession(static_cast<int>(sessionId)) ==
- RESULT_SUCCESS)
+ if (sManager->closeSession(static_cast<int>(sessionId)) == RESULT_SUCCESS)
{
ImsMediaEventHandler::SendEvent(
"TEXT_RESPONSE_EVENT", kTextSessionClosed, sessionId, 0, 0);
@@ -273,7 +278,7 @@
case kTextModifySession:
{
TextConfig* config = reinterpret_cast<TextConfig*>(paramA);
- result = TextManager::getInstance()->modifySession(static_cast<int>(sessionId), config);
+ result = sManager->modifySession(static_cast<int>(sessionId), config);
ImsMediaEventHandler::SendEvent(
"TEXT_RESPONSE_EVENT", kTextModifySessionResponse, sessionId, result, paramA);
}
@@ -284,8 +289,7 @@
if (threshold != nullptr)
{
- TextManager::getInstance()->setMediaQualityThreshold(
- static_cast<int>(sessionId), threshold);
+ sManager->setMediaQualityThreshold(static_cast<int>(sessionId), threshold);
delete threshold;
}
}
@@ -296,7 +300,7 @@
if (text != nullptr)
{
- TextManager::getInstance()->sendRtt(static_cast<int>(sessionId), text);
+ sManager->sendRtt(static_cast<int>(sessionId), text);
delete text;
}
}
@@ -311,6 +315,12 @@
{
IMLOGI4("[processEvent] event[%d], sessionId[%d], paramA[%d], paramB[%d]", event, sessionId,
paramA, paramB);
+
+ if (sManager == nullptr)
+ {
+ return;
+ }
+
android::Parcel parcel;
switch (event)
{
@@ -325,7 +335,7 @@
parcel.writeInt32(static_cast<int>(paramA));
}
- TextManager::getInstance()->sendResponse(sessionId, parcel);
+ sManager->sendResponse(sessionId, parcel);
break;
case kTextModifySessionResponse: // fall through
{
@@ -336,7 +346,7 @@
if (config != nullptr)
{
config->writeToParcel(&parcel);
- TextManager::getInstance()->sendResponse(sessionId, parcel);
+ sManager->sendResponse(sessionId, parcel);
delete config;
}
}
@@ -345,7 +355,7 @@
parcel.writeInt32(event);
parcel.writeInt32(static_cast<int>(paramA)); // type
parcel.writeInt32(static_cast<int>(paramB)); // duration
- TextManager::getInstance()->sendResponse(sessionId, parcel);
+ sManager->sendResponse(sessionId, parcel);
break;
case kTextRttReceived:
{
@@ -356,7 +366,7 @@
{
String16 rttText(*text);
parcel.writeString16(rttText);
- TextManager::getInstance()->sendResponse(sessionId, parcel);
+ sManager->sendResponse(sessionId, parcel);
delete text;
}
}
@@ -364,14 +374,14 @@
case kTextSessionClosed:
parcel.writeInt32(event);
parcel.writeInt32(static_cast<int>(sessionId));
- TextManager::getInstance()->sendResponse(sessionId, parcel);
+ sManager->sendResponse(sessionId, parcel);
break;
default:
break;
}
}
-bool TextManager::isOtherSessionActive(const int sessionId)
+bool TextManager::deactivateOtherSessionIfActive(const int sessionId)
{
for (auto const& session : mSessions)
{
@@ -381,9 +391,15 @@
if (state == kSessionStateActive)
{
IMLOGE1("[modifySession] Another session id[%d] is active", session.first);
- return true;
+ if ((session.second)->deactivate())
+ {
+ IMLOGI1("[modifySession] Moved session id[%d] to inactive", session.first);
+ return true;
+ }
+ IMLOGE1("[modifySession] Failed to move session id[%d] to inactive", session.first);
+ return false;
}
}
}
- return false;
+ return true;
}
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/text/TextSession.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/text/TextSession.cpp
index 2c3cf04..da7664b 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/text/TextSession.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/text/TextSession.cpp
@@ -229,4 +229,38 @@
default:
break;
}
+}
+
+bool TextSession::deactivate()
+{
+ IMLOGI0("[deactivate]");
+
+ if (mGraphRtpTx != nullptr)
+ {
+ if (mGraphRtpTx->getState() == kStreamStateRunning)
+ {
+ mGraphRtpTx->stop();
+ }
+
+ delete mGraphRtpTx;
+ mGraphRtpTx = nullptr;
+ }
+
+ if (mGraphRtpRx != nullptr)
+ {
+ if (mGraphRtpRx->getState() == kStreamStateRunning)
+ {
+ mGraphRtpRx->stop();
+ }
+
+ delete mGraphRtpRx;
+ mGraphRtpRx = nullptr;
+ }
+
+ if (getState() == kSessionStateActive)
+ {
+ return false;
+ }
+
+ return true;
}
\ No newline at end of file
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/utils/IImsMediaThread.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/utils/IImsMediaThread.cpp
index baabe45..20551fa 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/utils/IImsMediaThread.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/utils/IImsMediaThread.cpp
@@ -17,6 +17,9 @@
#include <IImsMediaThread.h>
#include <ImsMediaTrace.h>
#include <thread>
+#include <mediautils/SchedulingPolicyService.h>
+
+#define MAX_THREAD_NAME_LEN 16
extern void setAudioThreadPriority(int threadId);
@@ -39,19 +42,34 @@
return thread->runBase();
}
-bool IImsMediaThread::StartThread()
+bool IImsMediaThread::StartThread(const char* name)
{
std::lock_guard<std::mutex> guard(mThreadMutex);
mThreadStopped = false;
std::thread t1(&runThread, this);
+ if (name)
+ {
+ if (strlen(name) >= MAX_THREAD_NAME_LEN)
+ {
+ char shortname[MAX_THREAD_NAME_LEN];
+ strncpy(shortname, name, MAX_THREAD_NAME_LEN - 1);
+ pthread_setname_np(t1.native_handle(), shortname);
+ }
+ else
+ {
+ pthread_setname_np(t1.native_handle(), name);
+ }
+ }
t1.detach();
return true;
}
-void IImsMediaThread::SetAudioThreadPriority(pid_t tid)
+void IImsMediaThread::SetThreadPriority(pid_t pid, pid_t tid, int priority)
{
- setAudioThreadPriority(tid);
+ const int err =
+ android::requestPriority(pid, tid, priority, false /*isForApp*/, true /*asynchronous*/);
+ IMLOGD3("[SetThreadPriority] tid:%u, returned:%d. Err: %s", tid, err, strerror(errno));
}
void IImsMediaThread::StopThread()
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/utils/ImsMediaEventHandler.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/utils/ImsMediaEventHandler.cpp
index f03c559..bdd83b9 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/utils/ImsMediaEventHandler.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/utils/ImsMediaEventHandler.cpp
@@ -32,7 +32,7 @@
mbTerminate = false;
gListEventHandler.push_back(this);
IMLOGD1("[Init] %s", mName);
- StartThread();
+ StartThread("ImsMediaEventHandler");
}
void ImsMediaEventHandler::Deinit()
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/utils/ImsMediaSocket.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/utils/ImsMediaSocket.cpp
index e8ea46b..1aa317b 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/utils/ImsMediaSocket.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/utils/ImsMediaSocket.cpp
@@ -30,6 +30,7 @@
#include <ImsMediaSocket.h>
#include <ImsMediaTrace.h>
#include <ImsMediaNetworkUtil.h>
+#include <IImsMediaThread.h>
// static valuable
std::list<ImsMediaSocket*> ImsMediaSocket::slistRxSocket;
@@ -542,6 +543,7 @@
static fd_set TmpExcepfds;
int nMaxSD;
IMLOGD0("[SocketMonitorThread] enter");
+ IImsMediaThread::SetThreadPriority(getpid(), gettid(), THREAD_PRIORITY_REALTIME);
nMaxSD = SetSocketFD(&ReadFds, &WriteFds, &ExceptFds);
for (;;)
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/utils/ImsMediaTimer.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/utils/ImsMediaTimer.cpp
index 287a358..143e64f 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/utils/ImsMediaTimer.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/utils/ImsMediaTimer.cpp
@@ -37,9 +37,9 @@
bool mTerminateThread;
uint32_t mStartTimeSec;
uint32_t mStartTimeMSec;
+ std::mutex mMutex;
};
-static std::mutex gMutex;
static std::mutex gMutexList;
static std::list<TimerInstance*> gTimerList;
@@ -135,21 +135,19 @@
pInstance->mStartTimeMSec = nCurrTimeMSec;
}
- gMutex.lock();
+ { // Critical section
+ std::lock_guard<std::mutex> guard(pInstance->mMutex);
+ if (pInstance->mTerminateThread)
+ {
+ break;
+ }
- if (pInstance->mTerminateThread)
- {
- gMutex.unlock();
- break;
+ if (pInstance->mTimerCb)
+ {
+ pInstance->mTimerCb(pInstance, pInstance->mUserData);
+ }
}
- if (pInstance->mTimerCb)
- {
- pInstance->mTimerCb(pInstance, pInstance->mUserData);
- }
-
- gMutex.unlock();
-
if (pInstance->mRepeat == false)
{
break;
@@ -162,7 +160,7 @@
if (pInstance != nullptr)
{
- free(pInstance);
+ delete pInstance;
pInstance = nullptr;
}
@@ -173,7 +171,7 @@
uint32_t nDuration, bool bRepeat, fn_TimerCb pTimerCb, void* pUserData)
{
struct timeval tp;
- TimerInstance* pInstance = reinterpret_cast<TimerInstance*>(malloc(sizeof(TimerInstance)));
+ TimerInstance* pInstance = new TimerInstance;
if (pInstance == nullptr)
{
@@ -186,7 +184,7 @@
pInstance->mUserData = pUserData;
pInstance->mTerminateThread = false;
- IMLOGD3("[TimerStart] Duratation[%u], bRepeat[%d], pUserData[%x]", pInstance->mDuration,
+ IMLOGD3("[TimerStart] Duration[%u], bRepeat[%d], pUserData[%x]", pInstance->mDuration,
bRepeat, pInstance->mUserData);
if (gettimeofday(&tp, nullptr) != -1)
@@ -196,7 +194,7 @@
}
else
{
- free(pInstance);
+ delete pInstance;
return nullptr;
}
@@ -211,6 +209,7 @@
{
TimerInstance* pInstance = reinterpret_cast<TimerInstance*>(hTimer);
+ IMLOGD1("[TimerStop] pInstance[%x]", pInstance);
if (pInstance == nullptr)
{
return false;
@@ -221,15 +220,18 @@
return false;
}
- gMutex.lock(); // just wait until timer callback returns...
- pInstance->mTerminateThread = true;
-
- if (ppUserData)
{
- *ppUserData = pInstance->mUserData;
+ std::lock_guard<std::mutex> guard(pInstance->mMutex);
+ IMLOGD1("[TimerStop] mutex taken pInstance[%x]", pInstance);
+
+ pInstance->mTerminateThread = true;
+
+ if (ppUserData)
+ {
+ *ppUserData = pInstance->mUserData;
+ }
}
- gMutex.unlock();
return true;
}
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoManager.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoManager.cpp
index 4652511..0ad3439 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoManager.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoManager.cpp
@@ -19,7 +19,7 @@
#include <ImsMediaNetworkUtil.h>
using namespace android;
-VideoManager* VideoManager::manager;
+VideoManager* VideoManager::sManager;
VideoManager::VideoManager()
{
@@ -31,17 +31,17 @@
{
mRequestHandler.Deinit();
mResponseHandler.Deinit();
- manager = nullptr;
+ sManager = nullptr;
}
VideoManager* VideoManager::getInstance()
{
- if (manager == nullptr)
+ if (sManager == nullptr)
{
- manager = new VideoManager();
+ sManager = new VideoManager();
}
- return manager;
+ return sManager;
}
int VideoManager::getState(int sessionId)
@@ -261,6 +261,11 @@
paramA, paramB);
ImsMediaResult result = RESULT_SUCCESS;
+ if (sManager == nullptr)
+ {
+ return;
+ }
+
switch (event)
{
case kVideoOpenSession:
@@ -270,7 +275,7 @@
if (param != nullptr)
{
VideoConfig* pConfig = reinterpret_cast<VideoConfig*>(param->mConfig);
- result = VideoManager::getInstance()->openSession(
+ result = sManager->openSession(
static_cast<int>(sessionId), param->rtpFd, param->rtcpFd, pConfig);
if (result == RESULT_SUCCESS)
@@ -299,26 +304,24 @@
}
break;
case kVideoCloseSession:
- if (VideoManager::getInstance()->closeSession(static_cast<int>(sessionId)) ==
- RESULT_SUCCESS)
+ if (sManager->closeSession(static_cast<int>(sessionId)) == RESULT_SUCCESS)
{
ImsMediaEventHandler::SendEvent(
"VIDEO_RESPONSE_EVENT", kVideoSessionClosed, sessionId, 0, 0);
}
break;
case kVideoSetPreviewSurface:
- VideoManager::getInstance()->setPreviewSurfaceToSession(
+ sManager->setPreviewSurfaceToSession(
static_cast<int>(sessionId), reinterpret_cast<ANativeWindow*>(paramA));
break;
case kVideoSetDisplaySurface:
- VideoManager::getInstance()->setDisplaySurfaceToSession(
+ sManager->setDisplaySurfaceToSession(
static_cast<int>(sessionId), reinterpret_cast<ANativeWindow*>(paramA));
break;
case kVideoModifySession:
{
VideoConfig* config = reinterpret_cast<VideoConfig*>(paramA);
- result =
- VideoManager::getInstance()->modifySession(static_cast<int>(sessionId), config);
+ result = sManager->modifySession(static_cast<int>(sessionId), config);
ImsMediaEventHandler::SendEvent(
"VIDEO_RESPONSE_EVENT", kVideoModifySessionResponse, sessionId, result, paramA);
}
@@ -332,8 +335,7 @@
if (threshold != nullptr)
{
- VideoManager::getInstance()->setMediaQualityThreshold(
- static_cast<int>(sessionId), threshold);
+ sManager->setMediaQualityThreshold(static_cast<int>(sessionId), threshold);
delete threshold;
}
}
@@ -346,7 +348,7 @@
case kRequestVideoSendTmmbr:
case kRequestVideoSendTmmbn:
case kRequestRoundTripTimeDelayUpdate:
- VideoManager::getInstance()->SendInternalEvent(event, sessionId, paramA, paramB);
+ sManager->SendInternalEvent(event, sessionId, paramA, paramB);
break;
default:
break;
@@ -358,7 +360,14 @@
{
IMLOGI4("[processEvent] event[%d], sessionId[%d], paramA[%d], paramB[%d]", event, sessionId,
paramA, paramB);
+
+ if (sManager == nullptr)
+ {
+ return;
+ }
+
android::Parcel parcel;
+
switch (event)
{
case kVideoOpenSessionSuccess:
@@ -372,7 +381,7 @@
parcel.writeInt32(static_cast<int>(paramA));
}
- VideoManager::getInstance()->sendResponse(sessionId, parcel);
+ sManager->sendResponse(sessionId, parcel);
break;
case kVideoModifySessionResponse: // fall through
{
@@ -383,20 +392,20 @@
if (config != nullptr)
{
config->writeToParcel(&parcel);
- VideoManager::getInstance()->sendResponse(sessionId, parcel);
+ sManager->sendResponse(sessionId, parcel);
delete config;
}
}
break;
case kVideoFirstMediaPacketInd:
parcel.writeInt32(event);
- VideoManager::getInstance()->sendResponse(sessionId, parcel);
+ sManager->sendResponse(sessionId, parcel);
break;
case kVideoPeerDimensionChanged:
parcel.writeInt32(event);
parcel.writeInt32(static_cast<int>(paramA));
parcel.writeInt32(static_cast<int>(paramB));
- VideoManager::getInstance()->sendResponse(sessionId, parcel);
+ sManager->sendResponse(sessionId, parcel);
break;
case kVideoRtpHeaderExtensionInd:
// TODO : add implementation
@@ -405,17 +414,17 @@
case kVideoBitrateInd:
parcel.writeInt32(event);
parcel.writeInt32(static_cast<int>(paramA));
- VideoManager::getInstance()->sendResponse(sessionId, parcel);
+ sManager->sendResponse(sessionId, parcel);
break;
case kVideoDataUsageInd:
parcel.writeInt32(event);
parcel.writeInt64(static_cast<int>(paramA));
- VideoManager::getInstance()->sendResponse(sessionId, parcel);
+ sManager->sendResponse(sessionId, parcel);
break;
case kVideoSessionClosed:
parcel.writeInt32(event);
parcel.writeInt32(static_cast<int>(sessionId));
- VideoManager::getInstance()->sendResponse(sessionId, parcel);
+ sManager->sendResponse(sessionId, parcel);
break;
default:
break;
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoSession.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoSession.cpp
index ba43d0a..67c5684 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoSession.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoSession.cpp
@@ -249,7 +249,7 @@
break;
case kImsMediaEventFirstPacketReceived:
ImsMediaEventHandler::SendEvent(
- "VIDEO_RESPONSE_EVENT", kVideoFirstMediaPacketInd, param1, param2);
+ "VIDEO_RESPONSE_EVENT", kVideoFirstMediaPacketInd, mSessionId, param1, param2);
break;
case kImsMediaEventResolutionChanged:
ImsMediaEventHandler::SendEvent(
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/android/ImsMediaVideoRenderer.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/android/ImsMediaVideoRenderer.cpp
index 475425b..f3fff62 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/android/ImsMediaVideoRenderer.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/android/ImsMediaVideoRenderer.cpp
@@ -80,13 +80,13 @@
bool ImsMediaVideoRenderer::Start()
{
IMLOGD0("[Start]");
- mMutex.lock();
mFormat = AMediaFormat_new();
AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_WIDTH, mWidth);
AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_HEIGHT, mHeight);
char kMimeType[128] = {'\0'};
sprintf(kMimeType, "video/avc");
+
if (mCodecType == kVideoCodecHevc)
{
sprintf(kMimeType, "video/hevc");
@@ -99,6 +99,7 @@
AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_ROTATION, mFarOrientationDegree);
mCodec = AMediaCodec_createDecoderByType(kMimeType);
+
if (mCodec == nullptr)
{
IMLOGE0("[Start] Unable to create decoder");
@@ -111,6 +112,7 @@
}
media_status_t err = AMediaCodec_configure(mCodec, mFormat, mWindow, nullptr, 0);
+
if (err != AMEDIA_OK)
{
IMLOGE1("[Start] configure error[%d]", err);
@@ -122,6 +124,7 @@
}
err = AMediaCodec_start(mCodec);
+
if (err != AMEDIA_OK)
{
IMLOGE1("[Start] codec start[%d]", err);
@@ -133,7 +136,6 @@
}
mStopped = false;
- mMutex.unlock();
std::thread t1(&ImsMediaVideoRenderer::processBuffers, this);
t1.detach();
return true;
@@ -178,12 +180,17 @@
IMLOGD_PACKET2(IM_PACKET_LOG_VIDEO, "[OnDataFrame] frame size[%u], list[%d]", size,
mFrameDatas.size());
- std::lock_guard<std::mutex> guard(mMutex);
- if (mCodec == nullptr)
+
+ mMutex.lock();
+
+ if (mStopped)
{
+ mMutex.unlock();
return;
}
+ mMutex.unlock();
+
mFrameDatas.push_back(new FrameData(buffer, size, timestamp, isConfigFrame));
}
@@ -197,11 +204,13 @@
while (true)
{
mMutex.lock();
+
if (mStopped)
{
mMutex.unlock();
break;
}
+
mMutex.unlock();
if (mFrameDatas.size() == 0)
diff --git a/tests/native/Android.bp b/tests/native/Android.bp
index 255fa57..cf72ff1 100644
--- a/tests/native/Android.bp
+++ b/tests/native/Android.bp
@@ -23,6 +23,8 @@
export_include_dirs: [
"service/src/com/android/telephony/imsmedia/lib/libimsmedia/include",
"service/src/com/android/telephony/imsmedia/lib/libimsmedia/include/core/audio",
+ "service/src/com/android/telephony/imsmedia/lib/libimsmedia/include/core/video",
+ "service/src/com/android/telephony/imsmedia/lib/libimsmedia/include/core/text",
],
}
diff --git a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/AudioConfigTest.cpp b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/AudioConfigTest.cpp
index 3beca9f..e390835 100644
--- a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/AudioConfigTest.cpp
+++ b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/AudioConfigTest.cpp
@@ -130,7 +130,8 @@
TEST_F(AudioConfigTest, TestAssign)
{
- AudioConfig testConfig = config1;
+ AudioConfig testConfig;
+ testConfig = config1;
EXPECT_EQ(config1, testConfig);
AudioConfig* testConfig2 = new AudioConfig(config1);
diff --git a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/CallQualityTest.cpp b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/CallQualityTest.cpp
index 5fcc6f9..4cad123 100644
--- a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/CallQualityTest.cpp
+++ b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/CallQualityTest.cpp
@@ -93,7 +93,8 @@
TEST_F(CallQualityTest, TestAssign)
{
- CallQuality testQuality = quality1;
+ CallQuality testQuality;
+ testQuality = quality1;
EXPECT_EQ(quality1, testQuality);
}
diff --git a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/MediaQualityStatusTest.cpp b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/MediaQualityStatusTest.cpp
index c32c2d2..aa8aed0 100644
--- a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/MediaQualityStatusTest.cpp
+++ b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/MediaQualityStatusTest.cpp
@@ -62,7 +62,8 @@
TEST_F(MediaQualityStatusTest, TestAssign)
{
- MediaQualityStatus status2 = status;
+ MediaQualityStatus status2;
+ status2 = status;
EXPECT_EQ(status, status2);
}
diff --git a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/MediaQualityThresholdTest.cpp b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/MediaQualityThresholdTest.cpp
index 3349446..a68db0a 100644
--- a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/MediaQualityThresholdTest.cpp
+++ b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/MediaQualityThresholdTest.cpp
@@ -74,7 +74,8 @@
TEST_F(MediaQualityThresholdTest, TestAssign)
{
- MediaQualityThreshold threshold2 = threshold;
+ MediaQualityThreshold threshold2;
+ threshold2 = threshold;
EXPECT_EQ(threshold, threshold2);
}
diff --git a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/TextConfigTest.cpp b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/TextConfigTest.cpp
index 00f4cd6..793bdf0 100644
--- a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/TextConfigTest.cpp
+++ b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/TextConfigTest.cpp
@@ -96,7 +96,8 @@
TEST_F(TextConfigTest, TestAssign)
{
- TextConfig testConfig = config1;
+ TextConfig testConfig;
+ testConfig = config1;
EXPECT_EQ(config1, testConfig);
TextConfig* testConfig2 = new TextConfig(config1);
diff --git a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/VideoConfigTest.cpp b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/VideoConfigTest.cpp
index f18d081..66ba3b1 100644
--- a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/VideoConfigTest.cpp
+++ b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/VideoConfigTest.cpp
@@ -145,7 +145,8 @@
TEST_F(VideoConfigTest, TestAssign)
{
- VideoConfig testConfig = config1;
+ VideoConfig testConfig;
+ testConfig = config1;
EXPECT_EQ(config1, testConfig);
VideoConfig* testConfig2 = new VideoConfig(config1);
diff --git a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioManagerTest.cpp b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioManagerTest.cpp
index 7f81b84..3a28e18 100644
--- a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioManagerTest.cpp
+++ b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioManagerTest.cpp
@@ -30,6 +30,8 @@
using ::testing::Ref;
using ::testing::Return;
+namespace
+{
// RtpConfig
const int32_t kMediaDirection = RtpConfig::MEDIA_DIRECTION_SEND_RECEIVE;
const android::String8 kRemoteAddress("127.0.0.1");
@@ -68,7 +70,6 @@
const int8_t kcodecModeRequest = 15;
int32_t kSessionId = 0;
-
static ImsMediaCondition gCondition;
class AudioManagerCallback
@@ -686,4 +687,5 @@
EXPECT_EQ(callback.resSessionId, kSessionId);
EXPECT_EQ(callback.response, kAudioCallQualityChangedInd);
EXPECT_EQ(callback.callQuality, quality);
-}
\ No newline at end of file
+}
+} // namespace
\ No newline at end of file
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
index bd4a601..524e721 100644
--- 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
@@ -245,6 +245,14 @@
EXPECT_EQ(session->getGraphSize(kStreamRtpTx), 1);
EXPECT_EQ(session->getGraphSize(kStreamRtpRx), 1);
EXPECT_EQ(session->getGraphSize(kStreamRtcp), 1);
+
+ config.setMediaDirection(RtpConfig::MEDIA_DIRECTION_SEND_RECEIVE);
+ 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);
}
TEST_F(AudioSessionTest, testStartAndHoldResumeWithDifferentRemoteAddress)
@@ -334,4 +342,84 @@
EXPECT_EQ(session->getGraphSize(kStreamRtpTx), 1);
EXPECT_EQ(session->getGraphSize(kStreamRtpRx), 1);
EXPECT_EQ(session->getGraphSize(kStreamRtcp), 1);
+}
+
+TEST_F(AudioSessionTest, testDeactivateActiveSession)
+{
+ 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_EQ(session->deactivate(), true);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpTx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpRx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtcp), 1);
+ EXPECT_EQ(session->getState(), kSessionStateSuspended);
+}
+
+TEST_F(AudioSessionTest, testDeactivateSendonlySession)
+{
+ 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);
+
+ EXPECT_EQ(session->deactivate(), true);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpTx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpRx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtcp), 1);
+ EXPECT_EQ(session->getState(), kSessionStateSuspended);
+}
+
+TEST_F(AudioSessionTest, testDeactivateReceiveonlySession)
+{
+ 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);
+
+ EXPECT_EQ(session->deactivate(), true);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpTx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpRx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtcp), 1);
+ EXPECT_EQ(session->getState(), kSessionStateSuspended);
+}
+
+TEST_F(AudioSessionTest, testDeactivateAndResumeSession)
+{
+ 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_EQ(session->deactivate(), true);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpTx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpRx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtcp), 1);
+ EXPECT_EQ(session->getState(), kSessionStateSuspended);
+
+ 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);
+
+ config.setMediaDirection(RtpConfig::MEDIA_DIRECTION_SEND_RECEIVE);
+ 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);
}
\ No newline at end of file
diff --git a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioStreamGraphRtpTxTest.cpp b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioStreamGraphRtpTxTest.cpp
index 18e2eff..156252e 100644
--- a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioStreamGraphRtpTxTest.cpp
+++ b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioStreamGraphRtpTxTest.cpp
@@ -219,7 +219,7 @@
EXPECT_EQ(mockRtpEncoder->GetState(), kNodeStateRunning);
EXPECT_EQ(graph->start(), RESULT_SUCCESS);
- EXPECT_CALL(*mockRtpEncoder, OnDataFromFrontNode(MEDIASUBTYPE_DTMFSTART, _, 0, 0, 0, 0, _, _))
+ EXPECT_CALL(*mockRtpEncoder, OnDataFromFrontNode(MEDIASUBTYPE_DTMFSTART, _, 0, _, _, 0, _, _))
.Times(1)
.WillOnce(Return());
EXPECT_CALL(*mockRtpEncoder,
@@ -230,7 +230,7 @@
OnDataFromFrontNode(MEDIASUBTYPE_DTMF_PAYLOAD, NotNull(), 4, _, false, _, _, _))
.Times(11)
.WillRepeatedly(Return());
- EXPECT_CALL(*mockRtpEncoder, OnDataFromFrontNode(MEDIASUBTYPE_DTMFEND, _, 0, 0, 0, 0, _, _))
+ EXPECT_CALL(*mockRtpEncoder, OnDataFromFrontNode(MEDIASUBTYPE_DTMFEND, _, 0, _, _, 0, _, _))
.Times(1)
.WillOnce(Return());
diff --git a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/JitterNetworkAnalyserTest.cpp b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/JitterNetworkAnalyserTest.cpp
index 58edff7..e37aaa6 100644
--- a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/JitterNetworkAnalyserTest.cpp
+++ b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/JitterNetworkAnalyserTest.cpp
@@ -64,7 +64,8 @@
for (int32_t i = 0; i < kNumFrames; i++)
{
timestamp += TEST_FRAME_INTERVAL;
- arrivalTime += (TEST_FRAME_INTERVAL + kJitter);
+ int32_t jitter = i % 2 == 0 ? kJitter : -kJitter;
+ arrivalTime += (TEST_FRAME_INTERVAL + jitter);
if (i == 0)
{
@@ -72,7 +73,7 @@
}
else
{
- EXPECT_EQ(mAnalyzer->CalculateTransitTimeDifference(timestamp, arrivalTime), kJitter);
+ EXPECT_EQ(mAnalyzer->CalculateTransitTimeDifference(timestamp, arrivalTime), jitter);
}
currentJitterBufferSize =
@@ -128,7 +129,8 @@
for (int32_t i = 0; i < kNumFrames; i++)
{
timestamp += TEST_FRAME_INTERVAL;
- arrivalTime += (TEST_FRAME_INTERVAL + kJitter);
+ int32_t jitter = i % 2 == 0 ? kJitter : -kJitter;
+ arrivalTime += (TEST_FRAME_INTERVAL + jitter);
if (i == 0)
{
@@ -136,7 +138,7 @@
}
else
{
- EXPECT_EQ(mAnalyzer->CalculateTransitTimeDifference(timestamp, arrivalTime), kJitter);
+ EXPECT_EQ(mAnalyzer->CalculateTransitTimeDifference(timestamp, arrivalTime), jitter);
}
currentJitterBufferSize =
diff --git a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtpEncoderNodeTest.cpp b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtpEncoderNodeTest.cpp
index 19c5104..cab0f38 100644
--- a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtpEncoderNodeTest.cpp
+++ b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtpEncoderNodeTest.cpp
@@ -310,7 +310,6 @@
EXPECT_EQ(mFakeNode->GetFrameSize(), 0);
mNode->OnDataFromFrontNode(MEDIASUBTYPE_UNDEFINED, testFrame, sizeof(testFrame), 0, false, 0);
- mNode->ProcessData();
EXPECT_EQ(mFakeNode->GetFrameSize(), sizeof(testFrame) + kRtpHeaderSize);
}
@@ -338,14 +337,12 @@
EXPECT_EQ(mFakeNode->GetFrameSize(), 0);
mNode->OnDataFromFrontNode(MEDIASUBTYPE_RTPPAYLOAD, testFrame, sizeof(testFrame), 0, true, 0);
- mNode->ProcessData();
EXPECT_TRUE(mNode->SetCvoExtension(0, 0));
EXPECT_EQ(mFakeNode->GetFrameSize(), sizeof(testFrame) + kRtpHeaderSize);
mNode->OnDataFromFrontNode(
MEDIASUBTYPE_VIDEO_IDR_FRAME, testFrame, sizeof(testFrame), 0, true, 0);
- mNode->ProcessData();
EXPECT_EQ(mFakeNode->GetFrameSize(), sizeof(testFrame) + kRtpHeaderSizeWithExtension);
}
@@ -373,6 +370,5 @@
EXPECT_EQ(mFakeNode->GetFrameSize(), 0);
mNode->OnDataFromFrontNode(
MEDIASUBTYPE_BITSTREAM_T140_RED, testFrame, sizeof(testFrame), 0, true, 0);
- mNode->ProcessData();
EXPECT_EQ(mFakeNode->GetFrameSize(), sizeof(testFrame) + kRtpHeaderSize);
}
\ No newline at end of file
diff --git a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/SocketNodeTest.cpp b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/SocketNodeTest.cpp
index 71432b0..cb39fb6 100644
--- a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/SocketNodeTest.cpp
+++ b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/SocketNodeTest.cpp
@@ -251,16 +251,22 @@
EXPECT_EQ(mWriter->Start(), RESULT_SUCCESS);
mReader->Stop();
+ EXPECT_EQ(mReader->GetState(), kNodeStateStopped);
uint8_t testPacket[] = {0x80, 0x68, 0x00, 0x0b, 0xbc, 0xbc, 0xe8, 0xa4, 0x00, 0x04, 0x11, 0x68,
0xf4, 0xfa, 0xfe, 0x67, 0x58, 0x84, 0x80};
+ ON_CALL(mMockNode, GetState).WillByDefault(Return(kNodeStateStopped));
+ EXPECT_CALL(mMockNode,
+ OnDataFromFrontNode(MEDIASUBTYPE_UNDEFINED, Pointee(Eq(*testPacket)),
+ sizeof(testPacket), 0, false, 0, _, _))
+ .Times(0);
+
mWriter->OnDataFromFrontNode(
MEDIASUBTYPE_UNDEFINED, testPacket, sizeof(testPacket), 0, false, 0);
mCondition.wait_timeout(20);
- EXPECT_EQ(mReader->GetDataCount(), 1);
EXPECT_EQ(mReader->Start(), RESULT_SUCCESS);
- EXPECT_EQ(mReader->GetDataCount(), 0);
+ EXPECT_EQ(mReader->GetState(), kNodeStateRunning);
mWriter->Stop();
mReader->Stop();
}
diff --git a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/text/TextManagerTest.cpp b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/text/TextManagerTest.cpp
new file mode 100644
index 0000000..d9e6aae
--- /dev/null
+++ b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/text/TextManagerTest.cpp
@@ -0,0 +1,390 @@
+/**
+ * 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 <TextConfig.h>
+#include <MockTextManager.h>
+#include <ImsMediaCondition.h>
+#include <unordered_map>
+#include <algorithm>
+
+using namespace android::telephony::imsmedia;
+
+using ::testing::Eq;
+using ::testing::Pointee;
+using ::testing::Return;
+
+namespace
+{
+// 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 = 100;
+const int8_t kTxPayload = 100;
+const int8_t kSamplingRate = 8;
+
+// RtcpConfig
+const android::String8 kCanonicalName("name");
+const int32_t kTransmitPort = 10001;
+const int32_t kIntervalSec = 3;
+const int32_t kRtcpXrBlockTypes = 0;
+
+// TextConfig
+const int32_t kCodecType = TextConfig::TEXT_T140_RED;
+const int32_t kBitrate = 100;
+const int8_t kRedundantPayload = 102;
+const int8_t kRedundantLevel = 3;
+const bool kKeepRedundantLevel = true;
+
+int32_t kSessionId = 0;
+static ImsMediaCondition gCondition;
+
+class TextManagerCallback
+{
+public:
+ int32_t resSessionId;
+ int32_t response;
+ TextConfig resConfig;
+ ImsMediaResult result;
+ int32_t inactivityType;
+ int32_t inactivityDuration;
+ android::String8 receivedRtt;
+
+ void resetRespond()
+ {
+ resSessionId = -1;
+ response = -1;
+ result = RESULT_NOT_READY;
+ }
+
+ void onCallback(const int id, const int event, const ImsMediaResult res)
+ {
+ resSessionId = id;
+ response = event;
+ result = res;
+ }
+
+ void onCallbackConfig(
+ const int id, const int event, const ImsMediaResult res, const TextConfig& config)
+ {
+ resSessionId = id;
+ response = event;
+ resConfig = config;
+ result = res;
+ }
+
+ void onCallbackInactivity(const int id, const int event, const int type, const int duration)
+ {
+ resSessionId = id;
+ response = event;
+ inactivityType = type;
+ inactivityDuration = duration;
+ }
+
+ void onCallbackRttReceived(const int id, const int event, const android::String16& text)
+ {
+ resSessionId = id;
+ response = event;
+ receivedRtt = android::String8(text);
+ }
+};
+
+static std::unordered_map<int, TextManagerCallback*> gMapCallback;
+
+class TextManagerTest : public ::testing::Test
+{
+public:
+ MockTextManager manager;
+ TextConfig config;
+ RtcpConfig rtcp;
+ int socketRtpFd;
+ int socketRtcpFd;
+ TextManagerCallback callback;
+
+ TextManagerTest()
+ {
+ socketRtpFd = -1;
+ socketRtcpFd = -1;
+ callback.resetRespond();
+ gCondition.reset();
+ }
+ ~TextManagerTest() {}
+
+protected:
+ virtual void SetUp() override
+ {
+ rtcp.setCanonicalName(kCanonicalName);
+ rtcp.setTransmitPort(kTransmitPort);
+ rtcp.setIntervalSec(kIntervalSec);
+ rtcp.setRtcpXrBlockTypes(kRtcpXrBlockTypes);
+
+ 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.setCodecType(kCodecType);
+ config.setBitrate(kBitrate);
+ config.setRedundantPayload(kRedundantPayload);
+ config.setRedundantLevel(kRedundantLevel);
+ config.setKeepRedundantLevel(kKeepRedundantLevel);
+
+ manager.setCallback(&textCallback);
+ gMapCallback.insert(std::make_pair(kSessionId, &callback));
+ const char testIp[] = "127.0.0.1";
+ unsigned int testPortRtp = 50000;
+ socketRtpFd = ImsMediaNetworkUtil::openSocket(testIp, testPortRtp, AF_INET);
+ EXPECT_NE(socketRtpFd, -1);
+ unsigned int testPortRtcp = 50001;
+ socketRtcpFd = ImsMediaNetworkUtil::openSocket(testIp, testPortRtcp, AF_INET);
+ EXPECT_NE(socketRtcpFd, -1);
+ gCondition.reset();
+ }
+
+ virtual void TearDown() override
+ {
+ if (socketRtpFd != -1)
+ {
+ ImsMediaNetworkUtil::closeSocket(socketRtpFd);
+ }
+
+ if (socketRtcpFd != -1)
+ {
+ ImsMediaNetworkUtil::closeSocket(socketRtcpFd);
+ }
+
+ gMapCallback.erase(kSessionId);
+ }
+
+ void openSession(const int32_t sessionId)
+ {
+ callback.resetRespond();
+ android::Parcel parcel;
+ parcel.writeInt32(kTextOpenSession);
+ parcel.writeInt32(socketRtpFd);
+ parcel.writeInt32(socketRtcpFd);
+ parcel.setDataPosition(0);
+ gCondition.reset();
+ manager.sendMessage(sessionId, parcel);
+ EXPECT_TRUE(!gCondition.wait_timeout(1000));
+ EXPECT_EQ(callback.resSessionId, sessionId);
+ EXPECT_EQ(callback.response, kTextOpenSessionSuccess);
+ }
+
+ void closeSession(const int32_t sessionId)
+ {
+ callback.resetRespond();
+ android::Parcel parcel;
+ parcel.writeInt32(kTextCloseSession);
+ parcel.setDataPosition(0);
+ gCondition.reset();
+ manager.sendMessage(sessionId, parcel);
+ EXPECT_TRUE(!gCondition.wait_timeout(1000));
+ EXPECT_EQ(callback.resSessionId, sessionId);
+ EXPECT_EQ(callback.response, kTextSessionClosed);
+ }
+
+ void testEventResponse(const int32_t sessionId, const int32_t event, TextConfig* config,
+ const int32_t response, const int32_t result)
+ {
+ callback.resetRespond();
+ android::Parcel parcel;
+ parcel.writeInt32(event);
+
+ if (config != nullptr)
+ {
+ config->writeToParcel(&parcel);
+ }
+
+ parcel.setDataPosition(0);
+ gCondition.reset();
+ manager.sendMessage(sessionId, parcel);
+ EXPECT_TRUE(!gCondition.wait_timeout(1000));
+ EXPECT_EQ(callback.resSessionId, sessionId);
+ EXPECT_EQ(callback.response, response);
+
+ if (callback.response >= kTextOpenSessionFailure &&
+ callback.response <= kTextModifySessionResponse)
+ {
+ EXPECT_EQ(result, result);
+
+ if (config != nullptr && callback.response == kTextModifySessionResponse)
+ {
+ EXPECT_EQ(callback.resConfig, *config);
+ }
+ }
+ }
+
+ static int32_t textCallback(int sessionId, const android::Parcel& parcel)
+ {
+ parcel.setDataPosition(0);
+
+ int response = parcel.readInt32();
+ ImsMediaResult result = RESULT_INVALID_PARAM;
+
+ auto callback = gMapCallback.find(sessionId);
+
+ if (callback != gMapCallback.end())
+ {
+ if (response >= kTextOpenSessionFailure && response <= kTextModifySessionResponse)
+ {
+ result = static_cast<ImsMediaResult>(parcel.readInt32());
+ }
+
+ switch (response)
+ {
+ case kTextModifySessionResponse:
+ {
+ TextConfig resConfig;
+ resConfig.readFromParcel(&parcel);
+ (callback->second)->onCallbackConfig(sessionId, response, result, resConfig);
+ }
+ break;
+ case kTextMediaInactivityInd:
+ (callback->second)
+ ->onCallbackInactivity(
+ sessionId, response, parcel.readInt32(), parcel.readInt32());
+ break;
+ case kTextRttReceived:
+ {
+ android::String16 text;
+ parcel.readString16(&text);
+ (callback->second)->onCallbackRttReceived(sessionId, response, text);
+ }
+ break;
+ default:
+ (callback->second)->onCallback(sessionId, response, result);
+ break;
+ }
+ }
+
+ gCondition.signal();
+ return 0;
+ }
+};
+
+TEST_F(TextManagerTest, testOpenCloseSession)
+{
+ EXPECT_EQ(manager.getState(kSessionId), kSessionStateClosed);
+ openSession(kSessionId);
+ closeSession(kSessionId);
+}
+
+TEST_F(TextManagerTest, testModifySession)
+{
+ testEventResponse(kSessionId, kTextModifySession, nullptr, kTextModifySessionResponse,
+ RESULT_INVALID_PARAM);
+
+ openSession(kSessionId);
+
+ testEventResponse(kSessionId, kTextModifySession, nullptr, kTextModifySessionResponse,
+ RESULT_INVALID_PARAM);
+
+ testEventResponse(
+ kSessionId, kTextModifySession, &config, kTextModifySessionResponse, RESULT_SUCCESS);
+
+ closeSession(kSessionId);
+}
+
+TEST_F(TextManagerTest, testSendRtt)
+{
+ openSession(kSessionId);
+
+ const android::String8 text = android::String8("hello");
+ android::Parcel parcel;
+ parcel.writeInt32(kTextSendRtt);
+ android::String16 rttText(text);
+ parcel.writeString16(rttText);
+ parcel.setDataPosition(0);
+
+ EXPECT_CALL(manager, sendRtt(kSessionId, Pointee(Eq(text))))
+ .Times(1)
+ .WillOnce(Return(RESULT_NOT_READY));
+ manager.sendMessage(kSessionId, parcel);
+
+ closeSession(kSessionId);
+}
+
+TEST_F(TextManagerTest, testSetMediaQualityThreshold)
+{
+ openSession(kSessionId);
+
+ const std::vector<int32_t> kRtpInactivityTimerMillis = {10000, 20000};
+ const int32_t kRtcpInactivityTimerMillis = 20000;
+ const int32_t kRtpHysteresisTimeInMillis = 3000;
+ const int32_t kRtpPacketLossDurationMillis = 5000;
+ const std::vector<int32_t> kRtpPacketLossRate = {3, 5};
+ const std::vector<int32_t> kRtpJitterMillis = {100, 200};
+ const bool kNotifyCurrentStatus = false;
+
+ MediaQualityThreshold threshold;
+ threshold.setRtpInactivityTimerMillis(kRtpInactivityTimerMillis);
+ threshold.setRtcpInactivityTimerMillis(kRtcpInactivityTimerMillis);
+ threshold.setRtpHysteresisTimeInMillis(kRtpHysteresisTimeInMillis);
+ threshold.setRtpPacketLossDurationMillis(kRtpPacketLossDurationMillis);
+ threshold.setRtpPacketLossRate(kRtpPacketLossRate);
+ threshold.setRtpJitterMillis(kRtpJitterMillis);
+ threshold.setNotifyCurrentStatus(kNotifyCurrentStatus);
+
+ android::Parcel parcel;
+ parcel.writeInt32(kTextSetMediaQualityThreshold);
+ threshold.writeToParcel(&parcel);
+ parcel.setDataPosition(0);
+
+ EXPECT_CALL(manager, setMediaQualityThreshold(kSessionId, Pointee(Eq(threshold))))
+ .Times(1)
+ .WillOnce(Return());
+
+ manager.sendMessage(kSessionId, parcel);
+
+ closeSession(kSessionId);
+}
+
+TEST_F(TextManagerTest, testMediaInactivityInd)
+{
+ const int32_t kInactivityType = kProtocolRtp;
+ const int32_t kInactivityDuration = 10000;
+
+ ImsMediaEventHandler::SendEvent("TEXT_RESPONSE_EVENT", kTextMediaInactivityInd, kSessionId,
+ kInactivityType, kInactivityDuration);
+
+ gCondition.wait_timeout(20);
+ EXPECT_EQ(callback.resSessionId, kSessionId);
+ EXPECT_EQ(callback.response, kTextMediaInactivityInd);
+ EXPECT_EQ(callback.inactivityType, kInactivityType);
+ EXPECT_EQ(callback.inactivityDuration, kInactivityDuration);
+}
+
+TEST_F(TextManagerTest, testRttReceivedInd)
+{
+ const android::String8 testText = android::String8("hello");
+ android::String8* text = new android::String8(testText);
+
+ ImsMediaEventHandler::SendEvent("TEXT_RESPONSE_EVENT", kTextRttReceived, kSessionId,
+ reinterpret_cast<uint64_t>(text), 0);
+
+ gCondition.wait_timeout(20);
+ EXPECT_EQ(callback.resSessionId, kSessionId);
+ EXPECT_EQ(callback.response, kTextRttReceived);
+ EXPECT_EQ(callback.receivedRtt, testText);
+}
+} // namespace
\ No newline at end of file
diff --git a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/text/TextSessionTest.cpp b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/text/TextSessionTest.cpp
new file mode 100644
index 0000000..93cded7
--- /dev/null
+++ b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/text/TextSessionTest.cpp
@@ -0,0 +1,242 @@
+/**
+ * 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 <ImsMediaCondition.h>
+#include <TextConfig.h>
+#include <TextSession.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;
+
+// TextConfig
+const int32_t kCodecType = TextConfig::TEXT_T140_RED;
+const int32_t kBitrate = 100;
+const int8_t kRedundantPayload = 102;
+const int8_t kRedundantLevel = 2;
+const bool kKeepRedundantLevel = true;
+
+class TextSessionTest : public ::testing::Test
+{
+public:
+ TextSessionTest()
+ {
+ session = nullptr;
+ socketRtpFd = -1;
+ socketRtcpFd = -1;
+ }
+ virtual ~TextSessionTest() {}
+
+protected:
+ TextSession* session;
+ TextConfig config;
+ RtcpConfig rtcp;
+ int socketRtpFd;
+ int socketRtcpFd;
+
+ virtual void SetUp() override
+ {
+ rtcp.setCanonicalName(kCanonicalName);
+ rtcp.setTransmitPort(kTransmitPort);
+ rtcp.setIntervalSec(kIntervalSec);
+ rtcp.setRtcpXrBlockTypes(kRtcpXrBlockTypes);
+
+ 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.setCodecType(kCodecType);
+ config.setBitrate(kBitrate);
+ config.setRedundantPayload(kRedundantPayload);
+ config.setRedundantLevel(kRedundantLevel);
+ config.setKeepRedundantLevel(kKeepRedundantLevel);
+
+ session = new TextSession();
+ 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(TextSessionTest, 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(TextSessionTest, 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(TextSessionTest, testStartGraphAndUpdate)
+{
+ session->setLocalEndPoint(socketRtpFd, socketRtcpFd);
+ EXPECT_EQ(session->startGraph(&config), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateActive);
+
+ // normal update
+ config.setTxPayloadTypeNumber(120);
+ EXPECT_EQ(session->startGraph(&config), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateActive);
+
+ // create one more graph
+ config.setRemotePort(20000);
+ EXPECT_EQ(session->startGraph(&config), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateActive);
+}
+
+TEST_F(TextSessionTest, testStartGraphSendOnly)
+{
+ session->setLocalEndPoint(socketRtpFd, socketRtcpFd);
+ config.setMediaDirection(RtpConfig::MEDIA_DIRECTION_SEND_ONLY);
+ EXPECT_EQ(session->startGraph(&config), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateActive);
+}
+
+TEST_F(TextSessionTest, testStartGraphReceiveOnly)
+{
+ session->setLocalEndPoint(socketRtpFd, socketRtcpFd);
+ config.setMediaDirection(RtpConfig::MEDIA_DIRECTION_RECEIVE_ONLY);
+ EXPECT_EQ(session->startGraph(&config), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateActive);
+}
+
+TEST_F(TextSessionTest, testStartGraphInactive)
+{
+ session->setLocalEndPoint(socketRtpFd, socketRtcpFd);
+ config.setMediaDirection(RtpConfig::MEDIA_DIRECTION_INACTIVE);
+ EXPECT_EQ(session->startGraph(&config), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateSuspended);
+}
+
+TEST_F(TextSessionTest, testStartAndHoldResume)
+{
+ session->setLocalEndPoint(socketRtpFd, socketRtcpFd);
+ EXPECT_EQ(session->startGraph(&config), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateActive);
+
+ config.setMediaDirection(RtpConfig::MEDIA_DIRECTION_INACTIVE);
+ EXPECT_EQ(session->startGraph(&config), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateSuspended);
+
+ config.setMediaDirection(RtpConfig::MEDIA_DIRECTION_SEND_RECEIVE);
+ EXPECT_EQ(session->startGraph(&config), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateActive);
+}
+
+TEST_F(TextSessionTest, testDeactivateActiveSession)
+{
+ session->setLocalEndPoint(socketRtpFd, socketRtcpFd);
+ EXPECT_EQ(session->startGraph(&config), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateActive);
+
+ EXPECT_EQ(session->deactivate(), true);
+ EXPECT_EQ(session->getState(), kSessionStateSuspended);
+}
+
+TEST_F(TextSessionTest, testDeactivateSendonlySession)
+{
+ session->setLocalEndPoint(socketRtpFd, socketRtcpFd);
+ config.setMediaDirection(RtpConfig::MEDIA_DIRECTION_SEND_ONLY);
+ EXPECT_EQ(session->startGraph(&config), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateActive);
+
+ EXPECT_EQ(session->deactivate(), true);
+ EXPECT_EQ(session->getState(), kSessionStateSuspended);
+}
+
+TEST_F(TextSessionTest, testDeactivateReceiveonlySession)
+{
+ session->setLocalEndPoint(socketRtpFd, socketRtcpFd);
+ config.setMediaDirection(RtpConfig::MEDIA_DIRECTION_RECEIVE_ONLY);
+ EXPECT_EQ(session->startGraph(&config), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateActive);
+
+ EXPECT_EQ(session->deactivate(), true);
+ EXPECT_EQ(session->getState(), kSessionStateSuspended);
+}
+
+TEST_F(TextSessionTest, testDeactivateAndResumeSession)
+{
+ session->setLocalEndPoint(socketRtpFd, socketRtcpFd);
+ EXPECT_EQ(session->startGraph(&config), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateActive);
+
+ EXPECT_EQ(session->deactivate(), true);
+ EXPECT_EQ(session->getState(), kSessionStateSuspended);
+
+ config.setMediaDirection(RtpConfig::MEDIA_DIRECTION_INACTIVE);
+ EXPECT_EQ(session->startGraph(&config), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateSuspended);
+
+ config.setMediaDirection(RtpConfig::MEDIA_DIRECTION_SEND_RECEIVE);
+ EXPECT_EQ(session->startGraph(&config), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateActive);
+}
diff --git a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoManagerTest.cpp b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoManagerTest.cpp
new file mode 100644
index 0000000..63b8943
--- /dev/null
+++ b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoManagerTest.cpp
@@ -0,0 +1,465 @@
+/**
+ * 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 <media/NdkImageReader.h>
+#include <VideoConfig.h>
+#include <MockVideoManager.h>
+#include <ImsMediaCondition.h>
+#include <unordered_map>
+#include <algorithm>
+
+using namespace android::telephony::imsmedia;
+
+using ::testing::Eq;
+using ::testing::Pointee;
+using ::testing::Return;
+
+namespace
+{
+// RtpConfig
+const int32_t kMediaDirection = RtpConfig::MEDIA_DIRECTION_NO_FLOW;
+const android::String8 kRemoteAddress("0.0.0.0");
+const int32_t kRemotePort = 1000;
+const int32_t kMtu = 1500;
+const int8_t kDscp = 0;
+const int8_t kRxPayload = 102;
+const int8_t kTxPayload = 102;
+const int8_t kSamplingRate = 90;
+
+// RtcpConfig
+const android::String8 kCanonicalName("name");
+const int32_t kTransmitPort = 1001;
+const int32_t kIntervalSec = 1500;
+const int32_t kRtcpXrBlockTypes = RtcpConfig::FLAG_RTCPXR_STATISTICS_SUMMARY_REPORT_BLOCK |
+ RtcpConfig::FLAG_RTCPXR_VOIP_METRICS_REPORT_BLOCK;
+
+// VideoConfig
+const int32_t kVideoMode = VideoConfig::VIDEO_MODE_PREVIEW;
+const int32_t kCodecType = VideoConfig::CODEC_AVC;
+const int32_t kFramerate = DEFAULT_FRAMERATE;
+const int32_t kBitrate = DEFAULT_BITRATE;
+const int32_t kCodecProfile = VideoConfig::AVC_PROFILE_BASELINE;
+const int32_t kCodecLevel = VideoConfig::AVC_LEVEL_12;
+const int32_t kIntraFrameIntervalSec = 1;
+const int32_t kPacketizationMode = VideoConfig::MODE_NON_INTERLEAVED;
+const int32_t kCameraId = 0;
+const int32_t kCameraZoom = 10;
+const int32_t kResolutionWidth = DEFAULT_RESOLUTION_WIDTH;
+const int32_t kResolutionHeight = DEFAULT_RESOLUTION_HEIGHT;
+const android::String8 kPauseImagePath("data/user_de/0/com.android.telephony.imsmedia/test.jpg");
+const int32_t kDeviceOrientationDegree = 0;
+const int32_t kCvoValue = 1;
+const int32_t kRtcpFbTypes = VideoConfig::RTP_FB_NONE;
+
+int32_t kSessionId = 0;
+static ImsMediaCondition gCondition;
+
+class VideoManagerCallback
+{
+public:
+ int32_t resSessionId;
+ int32_t response;
+ VideoConfig resConfig;
+ ImsMediaResult result;
+ int32_t inactivityType;
+ int32_t inactivityDuration;
+ int32_t peerResolutionWidth;
+ int32_t peerResolutionHeight;
+
+ void resetRespond()
+ {
+ resSessionId = -1;
+ response = -1;
+ result = RESULT_NOT_READY;
+ }
+
+ void onCallback(const int id, const int event, const ImsMediaResult res)
+ {
+ resSessionId = id;
+ response = event;
+ result = res;
+ }
+
+ void onCallbackConfig(
+ const int id, const int event, const ImsMediaResult res, const VideoConfig& config)
+ {
+ resSessionId = id;
+ response = event;
+ resConfig = config;
+ result = res;
+ }
+
+ void onCallbackInactivity(const int id, const int event, const int type, const int duration)
+ {
+ resSessionId = id;
+ response = event;
+ inactivityType = type;
+ inactivityDuration = duration;
+ }
+
+ void onCallbackPeerDimensionChanged(
+ const int id, const int event, const int width, const int height)
+ {
+ resSessionId = id;
+ response = event;
+ peerResolutionWidth = width;
+ peerResolutionHeight = height;
+ }
+};
+
+static std::unordered_map<int, VideoManagerCallback*> gMapCallback;
+
+class VideoManagerTest : public ::testing::Test
+{
+public:
+ MockVideoManager manager;
+ VideoConfig config;
+ RtcpConfig rtcp;
+ int socketRtpFd;
+ int socketRtcpFd;
+ VideoManagerCallback callback;
+
+ VideoManagerTest()
+ {
+ socketRtpFd = -1;
+ socketRtcpFd = -1;
+ callback.resetRespond();
+ gCondition.reset();
+ }
+ ~VideoManagerTest() {}
+
+protected:
+ virtual void SetUp() override
+ {
+ rtcp.setCanonicalName(kCanonicalName);
+ rtcp.setTransmitPort(kTransmitPort);
+ rtcp.setIntervalSec(kIntervalSec);
+ rtcp.setRtcpXrBlockTypes(kRtcpXrBlockTypes);
+ config.setMediaDirection(kMediaDirection);
+ config.setRemoteAddress(kRemoteAddress);
+ config.setRemotePort(kRemotePort);
+ config.setRtcpConfig(rtcp);
+ config.setMaxMtuBytes(kMtu);
+ config.setDscp(kDscp);
+ config.setRxPayloadTypeNumber(kRxPayload);
+ config.setTxPayloadTypeNumber(kTxPayload);
+ config.setSamplingRateKHz(kSamplingRate);
+ config.setVideoMode(kVideoMode);
+ config.setCodecType(kCodecType);
+ config.setFramerate(kFramerate);
+ config.setBitrate(kBitrate);
+ config.setCodecProfile(kCodecProfile);
+ config.setCodecLevel(kCodecLevel);
+ config.setIntraFrameInterval(kIntraFrameIntervalSec);
+ config.setPacketizationMode(kPacketizationMode);
+ config.setCameraId(kCameraId);
+ config.setCameraZoom(kCameraZoom);
+ config.setResolutionWidth(kResolutionWidth);
+ config.setResolutionHeight(kResolutionHeight);
+ config.setPauseImagePath(kPauseImagePath);
+ config.setDeviceOrientationDegree(kDeviceOrientationDegree);
+ config.setCvoValue(kCvoValue);
+ config.setRtcpFbType(kRtcpFbTypes);
+
+ manager.setCallback(&VideoCallback);
+ gMapCallback.insert(std::make_pair(kSessionId, &callback));
+ const char testIp[] = "127.0.0.1";
+ unsigned int testPortRtp = 50000;
+ socketRtpFd = ImsMediaNetworkUtil::openSocket(testIp, testPortRtp, AF_INET);
+ EXPECT_NE(socketRtpFd, -1);
+ unsigned int testPortRtcp = 50001;
+ socketRtcpFd = ImsMediaNetworkUtil::openSocket(testIp, testPortRtcp, AF_INET);
+ EXPECT_NE(socketRtcpFd, -1);
+ gCondition.reset();
+ }
+
+ virtual void TearDown() override
+ {
+ if (socketRtpFd != -1)
+ {
+ ImsMediaNetworkUtil::closeSocket(socketRtpFd);
+ }
+
+ if (socketRtcpFd != -1)
+ {
+ ImsMediaNetworkUtil::closeSocket(socketRtcpFd);
+ }
+
+ gMapCallback.erase(kSessionId);
+ }
+
+ void openSession(const int32_t sessionId)
+ {
+ callback.resetRespond();
+ android::Parcel parcel;
+ parcel.writeInt32(kVideoOpenSession);
+ parcel.writeInt32(socketRtpFd);
+ parcel.writeInt32(socketRtcpFd);
+ parcel.setDataPosition(0);
+ gCondition.reset();
+ manager.sendMessage(sessionId, parcel);
+ EXPECT_TRUE(!gCondition.wait_timeout(1000));
+ EXPECT_EQ(callback.resSessionId, sessionId);
+ EXPECT_EQ(callback.response, kVideoOpenSessionSuccess);
+ }
+
+ void closeSession(const int32_t sessionId)
+ {
+ callback.resetRespond();
+ android::Parcel parcel;
+ parcel.writeInt32(kVideoCloseSession);
+ parcel.setDataPosition(0);
+ gCondition.reset();
+ manager.sendMessage(sessionId, parcel);
+ EXPECT_TRUE(!gCondition.wait_timeout(1000));
+ EXPECT_EQ(callback.resSessionId, sessionId);
+ EXPECT_EQ(callback.response, kVideoSessionClosed);
+ }
+
+ void testEventResponse(const int32_t sessionId, const int32_t event, VideoConfig* config,
+ const int32_t response, const int32_t result)
+ {
+ callback.resetRespond();
+ android::Parcel parcel;
+ parcel.writeInt32(event);
+
+ if (config != nullptr)
+ {
+ config->writeToParcel(&parcel);
+ }
+
+ parcel.setDataPosition(0);
+ gCondition.reset();
+ manager.sendMessage(sessionId, parcel);
+ EXPECT_TRUE(!gCondition.wait_timeout(1000));
+ EXPECT_EQ(callback.resSessionId, sessionId);
+ EXPECT_EQ(callback.response, response);
+
+ if (callback.response >= kVideoOpenSessionFailure &&
+ callback.response <= kVideoModifySessionResponse)
+ {
+ EXPECT_EQ(result, result);
+
+ if (config != nullptr && callback.response == kVideoModifySessionResponse)
+ {
+ EXPECT_EQ(callback.resConfig, *config);
+ }
+ }
+ }
+
+ static int32_t VideoCallback(int sessionId, const android::Parcel& parcel)
+ {
+ parcel.setDataPosition(0);
+
+ int response = parcel.readInt32();
+ ImsMediaResult result = RESULT_INVALID_PARAM;
+
+ auto callback = gMapCallback.find(sessionId);
+
+ if (callback != gMapCallback.end())
+ {
+ if (response >= kVideoOpenSessionFailure && response <= kVideoModifySessionResponse)
+ {
+ result = static_cast<ImsMediaResult>(parcel.readInt32());
+ }
+
+ switch (response)
+ {
+ case kVideoModifySessionResponse:
+ {
+ VideoConfig resConfig;
+ resConfig.readFromParcel(&parcel);
+ (callback->second)->onCallbackConfig(sessionId, response, result, resConfig);
+ }
+ break;
+ case kVideoPeerDimensionChanged:
+ (callback->second)
+ ->onCallbackPeerDimensionChanged(
+ sessionId, response, parcel.readInt32(), parcel.readInt32());
+ break;
+ case kVideoMediaInactivityInd:
+ (callback->second)
+ ->onCallbackInactivity(
+ sessionId, response, parcel.readInt32(), parcel.readInt32());
+ break;
+ case kVideoFirstMediaPacketInd:
+ default:
+ (callback->second)->onCallback(sessionId, response, result);
+ break;
+ }
+ }
+
+ gCondition.signal();
+ return 0;
+ }
+};
+
+TEST_F(VideoManagerTest, testOpenCloseSession)
+{
+ EXPECT_EQ(manager.getState(kSessionId), kSessionStateClosed);
+ openSession(kSessionId);
+ closeSession(kSessionId);
+}
+
+TEST_F(VideoManagerTest, testModifySession)
+{
+ testEventResponse(kSessionId, kVideoModifySession, nullptr, kVideoModifySessionResponse,
+ RESULT_INVALID_PARAM);
+
+ openSession(kSessionId);
+
+ testEventResponse(kSessionId, kVideoModifySession, nullptr, kVideoModifySessionResponse,
+ RESULT_INVALID_PARAM);
+
+ testEventResponse(
+ kSessionId, kVideoModifySession, &config, kVideoModifySessionResponse, RESULT_SUCCESS);
+
+ closeSession(kSessionId);
+}
+
+TEST_F(VideoManagerTest, testSetPreviewSurface)
+{
+ openSession(kSessionId);
+
+ AImageReader* previewReader;
+ AImageReader_new(
+ kResolutionWidth, kResolutionHeight, AIMAGE_FORMAT_YUV_420_888, 1, &previewReader);
+
+ ANativeWindow* previewSurface;
+ AImageReader_getWindow(previewReader, &previewSurface);
+
+ EXPECT_CALL(manager, setPreviewSurfaceToSession(kSessionId, Eq(previewSurface)))
+ .Times(1)
+ .WillOnce(Return(RESULT_SUCCESS));
+
+ manager.setPreviewSurface(kSessionId, previewSurface);
+
+ gCondition.wait_timeout(20);
+ closeSession(kSessionId);
+}
+
+TEST_F(VideoManagerTest, testSetDisplaySurface)
+{
+ openSession(kSessionId);
+
+ AImageReader* displayReader;
+ AImageReader_new(
+ kResolutionWidth, kResolutionHeight, AIMAGE_FORMAT_YUV_420_888, 1, &displayReader);
+
+ ANativeWindow* displaySurface;
+ AImageReader_getWindow(displayReader, &displaySurface);
+
+ EXPECT_CALL(manager, setDisplaySurfaceToSession(kSessionId, Eq(displaySurface)))
+ .Times(1)
+ .WillOnce(Return(RESULT_SUCCESS));
+
+ manager.setDisplaySurface(kSessionId, displaySurface);
+
+ gCondition.wait_timeout(20);
+ closeSession(kSessionId);
+}
+
+TEST_F(VideoManagerTest, testSetMediaQualityThreshold)
+{
+ openSession(kSessionId);
+
+ const std::vector<int32_t> kRtpInactivityTimerMillis = {10000, 20000};
+ const int32_t kRtcpInactivityTimerMillis = 20000;
+ const int32_t kRtpHysteresisTimeInMillis = 3000;
+ const int32_t kRtpPacketLossDurationMillis = 5000;
+ const std::vector<int32_t> kRtpPacketLossRate = {3, 5};
+ const std::vector<int32_t> kRtpJitterMillis = {100, 200};
+ const bool kNotifyCurrentStatus = false;
+
+ MediaQualityThreshold threshold;
+ threshold.setRtpInactivityTimerMillis(kRtpInactivityTimerMillis);
+ threshold.setRtcpInactivityTimerMillis(kRtcpInactivityTimerMillis);
+ threshold.setRtpHysteresisTimeInMillis(kRtpHysteresisTimeInMillis);
+ threshold.setRtpPacketLossDurationMillis(kRtpPacketLossDurationMillis);
+ threshold.setRtpPacketLossRate(kRtpPacketLossRate);
+ threshold.setRtpJitterMillis(kRtpJitterMillis);
+ threshold.setNotifyCurrentStatus(kNotifyCurrentStatus);
+
+ android::Parcel parcel;
+ parcel.writeInt32(kVideoSetMediaQualityThreshold);
+ threshold.writeToParcel(&parcel);
+ parcel.setDataPosition(0);
+
+ EXPECT_CALL(manager, setMediaQualityThreshold(kSessionId, Pointee(Eq(threshold))))
+ .Times(1)
+ .WillOnce(Return());
+
+ manager.sendMessage(kSessionId, parcel);
+
+ closeSession(kSessionId);
+}
+
+TEST_F(VideoManagerTest, testFirstMediaPacketInd)
+{
+ ImsMediaEventHandler::SendEvent(
+ "VIDEO_RESPONSE_EVENT", kVideoFirstMediaPacketInd, kSessionId, 0, 0);
+
+ gCondition.wait_timeout(20);
+ EXPECT_EQ(callback.resSessionId, kSessionId);
+ EXPECT_EQ(callback.response, kVideoFirstMediaPacketInd);
+}
+
+TEST_F(VideoManagerTest, testPeerDimensionChangedInd)
+{
+ ImsMediaEventHandler::SendEvent("VIDEO_RESPONSE_EVENT", kVideoPeerDimensionChanged, kSessionId,
+ kResolutionWidth, kResolutionHeight);
+
+ gCondition.wait_timeout(20);
+ EXPECT_EQ(callback.resSessionId, kSessionId);
+ EXPECT_EQ(callback.response, kVideoPeerDimensionChanged);
+ EXPECT_EQ(callback.peerResolutionWidth, kResolutionWidth);
+ EXPECT_EQ(callback.peerResolutionHeight, kResolutionHeight);
+}
+
+TEST_F(VideoManagerTest, testMediaInactivityInd)
+{
+ const int32_t kInactivityType = kProtocolRtp;
+
+ ImsMediaEventHandler::SendEvent(
+ "VIDEO_RESPONSE_EVENT", kVideoMediaInactivityInd, kSessionId, kInactivityType, 0);
+
+ gCondition.wait_timeout(20);
+ EXPECT_EQ(callback.resSessionId, kSessionId);
+ EXPECT_EQ(callback.response, kVideoMediaInactivityInd);
+ EXPECT_EQ(callback.inactivityType, kInactivityType);
+}
+
+TEST_F(VideoManagerTest, testInternalEvent)
+{
+ const uint64_t kParamA = 1;
+ const uint64_t kParamB = 2;
+
+ for (int32_t request = kRequestVideoCvoUpdate; request <= kRequestRoundTripTimeDelayUpdate;
+ request++)
+ {
+ EXPECT_CALL(manager, SendInternalEvent(request, kSessionId, Eq(kParamA), Eq(kParamB)))
+ .Times(1)
+ .WillOnce(Return());
+
+ ImsMediaEventHandler::SendEvent(
+ "VIDEO_REQUEST_EVENT", request, kSessionId, kParamA, kParamB);
+ gCondition.wait_timeout(20);
+ }
+}
+
+} // namespace
\ No newline at end of file
diff --git a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/include/core/text/MockTextManager.h b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/include/core/text/MockTextManager.h
new file mode 100644
index 0000000..c7bbe92
--- /dev/null
+++ b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/include/core/text/MockTextManager.h
@@ -0,0 +1,34 @@
+/**
+ * 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.
+ */
+
+#ifndef MOCK_TEXT_MANAGER_H
+#define MOCK_TEXT_MANAGER_H
+
+#include <TextManager.h>
+#include <ImsMediaDefine.h>
+#include <gmock/gmock.h>
+
+class MockTextManager : public TextManager
+{
+public:
+ MockTextManager() { sManager = this; }
+ virtual ~MockTextManager() { sManager = nullptr; }
+ MOCK_METHOD(ImsMediaResult, sendRtt, (int sessionId, const android::String8* text), (override));
+ MOCK_METHOD(void, setMediaQualityThreshold, (int sessionId, MediaQualityThreshold* threshold),
+ (override));
+};
+
+#endif
\ No newline at end of file
diff --git a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/include/core/video/MockVideoManager.h b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/include/core/video/MockVideoManager.h
new file mode 100644
index 0000000..ff31cbd
--- /dev/null
+++ b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/include/core/video/MockVideoManager.h
@@ -0,0 +1,39 @@
+/**
+ * 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.
+ */
+
+#ifndef MOCK_VIDEO_MANAGER_H
+#define MOCK_VIDEO_MANAGER_H
+
+#include <VideoManager.h>
+#include <ImsMediaDefine.h>
+#include <gmock/gmock.h>
+
+class MockVideoManager : public VideoManager
+{
+public:
+ MockVideoManager() { sManager = this; }
+ virtual ~MockVideoManager() { sManager = nullptr; }
+ MOCK_METHOD(ImsMediaResult, setPreviewSurfaceToSession,
+ (const int sessionId, ANativeWindow* surface), (override));
+ MOCK_METHOD(ImsMediaResult, setDisplaySurfaceToSession,
+ (const int sessionId, ANativeWindow* surface), (override));
+ MOCK_METHOD(void, setMediaQualityThreshold,
+ (const int sessionId, MediaQualityThreshold* threshold), (override));
+ MOCK_METHOD(void, SendInternalEvent,
+ (uint32_t event, uint64_t sessionId, uint64_t paramA, uint64_t paramB), (override));
+};
+
+#endif
\ No newline at end of file