diff options
6 files changed, 130 insertions, 179 deletions
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/ImsMediaDefine.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/ImsMediaDefine.h index 045051c1..891513dd 100644 --- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/ImsMediaDefine.h +++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/ImsMediaDefine.h @@ -360,7 +360,6 @@ enum ImsMediaTextMsgResponse #define RTT_MAX_CHAR_PER_SEC (30) // ATIS_GTT : 30 characters per second #define RTT_MAX_UNICODE_UTF8 (4) #define MAX_RTT_LEN (RTT_MAX_CHAR_PER_SEC * RTT_MAX_UNICODE_UTF8) -#define T140_MAX_CHUNK (1) #define PAYLOADENCODER_TEXT_MAX_REDUNDANT_INTERVAL (16383) struct EventParamOpenSession 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 9ca79518..c7270c6b 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 @@ -237,6 +237,26 @@ public: uint32_t* arrivalTime = nullptr); /** + * @brief This method is to add data frame to the queue in the node + * + * @param data The data buffer + * @param size The size of data + * @param timestamp The timestamp of data, it can be milliseconds unit or rtp timestamp unit + * @param mark It is true when the data has marker bit set + * @param seq The sequence number of data. it is 0 when there is no valid sequence number set + * @param subtype The subtype of data stored in the queue. It can be various subtype according + * to the characteristics of the given data + * @param dataType The additional data type for the video frames + * @param arrivalTime The arrival time of the packet + * @param index The index of the queue to add, if it is not set, add the frame to the end of + * the queue + */ + virtual void AddData(uint8_t* data, uint32_t size, uint32_t timestamp, bool mark, uint32_t seq, + ImsMediaSubType subtype = ImsMediaSubType::MEDIASUBTYPE_UNDEFINED, + ImsMediaSubType dataType = ImsMediaSubType::MEDIASUBTYPE_UNDEFINED, + uint32_t arrivalTime = 0, int32_t index = -1); + + /** * @brief Deletes the data stored in the front of the data queue * */ diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/text/nodes/TextSourceNode.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/text/nodes/TextSourceNode.h index 5b61a77e..5b690c90 100644 --- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/text/nodes/TextSourceNode.h +++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/text/nodes/TextSourceNode.h @@ -45,7 +45,7 @@ public: void SendRtt(const android::String8* text); private: - void SendBOM(); + void SendBom(); int32_t mCodecType; int8_t mRedundantLevel; @@ -54,9 +54,6 @@ private: int32_t mBitrate; bool mBomEnabled; bool mSentBOM; - std::list<uint32_t> mListTextSourceSize; - std::list<uint8_t*> mListTextSource; - uint8_t mTextToSend[MAX_RTT_LEN]; std::mutex mMutex; }; 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 6ee0e6b5..70986fac 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 @@ -268,6 +268,21 @@ bool BaseNode::GetData(ImsMediaSubType* psubtype, uint8_t** ppData, uint32_t* pn } } +void BaseNode::AddData(uint8_t* data, uint32_t size, uint32_t timestamp, bool mark, uint32_t seq, + ImsMediaSubType subtype, ImsMediaSubType dataType, uint32_t arrivalTime, int32_t index) +{ + DataEntry entry = DataEntry(); + entry.pbBuffer = data; + entry.nBufferSize = size; + entry.nTimestamp = timestamp; + entry.bMark = mark; + entry.nSeqNum = seq; + entry.eDataType = dataType; + entry.subtype = subtype; + entry.arrivalTime = arrivalTime; + index == -1 ? mDataQueue.Add(&entry) : mDataQueue.InsertAt(index, &entry); +} + void BaseNode::DeleteData() { mDataQueue.Delete(); diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/text/nodes/TextSourceNode.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/text/nodes/TextSourceNode.cpp index 82fc1b58..20a01154 100644 --- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/text/nodes/TextSourceNode.cpp +++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/text/nodes/TextSourceNode.cpp @@ -30,17 +30,7 @@ TextSourceNode::TextSourceNode(BaseSessionCallback* callback) : mSentBOM = false; } -TextSourceNode::~TextSourceNode() -{ - while (mListTextSource.size() > 0) - { - uint8_t* text = mListTextSource.front(); - delete text; - mListTextSource.pop_front(); - } - - mListTextSourceSize.clear(); -} +TextSourceNode::~TextSourceNode() {} kBaseNodeId TextSourceNode::GetNodeId() { @@ -49,7 +39,7 @@ kBaseNodeId TextSourceNode::GetNodeId() ImsMediaResult TextSourceNode::Start() { - IMLOGD2("[Start] codec[%d], Redundant Level[%d]", mCodecType, mRedundantLevel); + IMLOGD2("[Start] codec[%d], redundant level[%d]", mCodecType, mRedundantLevel); if (mCodecType == TextConfig::TEXT_CODEC_NONE) { @@ -117,52 +107,27 @@ void TextSourceNode::ProcessData() return; } - std::lock_guard<std::mutex> guard(mMutex); - - if (mBomEnabled == true && mSentBOM == false) + if (mBomEnabled && !mSentBOM) { - SendBOM(); + SendBom(); mSentBOM = true; } - uint32_t nLoopCount = 1; - - if (mListTextSource.size() >= T140_MAX_CHUNK) - { - nLoopCount = T140_MAX_CHUNK; - } - - uint32_t nSendingDataSize = 0; - memset(mTextToSend, 0, MAX_RTT_LEN); - - for (uint32_t i = 0; - (i < nLoopCount && !mListTextSource.empty() && !mListTextSourceSize.empty()); i++) - { - // get first node data - uint8_t* pData = mListTextSource.front(); - uint32_t nDataSize = mListTextSourceSize.front(); - - if (pData == nullptr || nDataSize == 0) - { - continue; - } + std::lock_guard<std::mutex> guard(mMutex); - memcpy(mTextToSend + nSendingDataSize, pData, nDataSize); - nSendingDataSize += nDataSize; + ImsMediaSubType subtype = MEDIASUBTYPE_UNDEFINED; + ImsMediaSubType datatype = MEDIASUBTYPE_UNDEFINED; + uint8_t* data = NULL; + uint32_t size = 0; + uint32_t timestamp = 0; + bool mark = false; + uint32_t seq = 0; - free(pData); - mListTextSourceSize.pop_front(); - mListTextSource.pop_front(); - } - - if (nSendingDataSize > 0) + if (GetData(&subtype, &data, &size, ×tamp, &mark, &seq, &datatype)) { - // send it one char - IMLOGD_PACKET1(IM_PACKET_LOG_TEXT, "[ProcessData] send[%s]", mTextToSend); - mTimeLastSent = ImsMediaTimer::GetTimeInMilliSeconds(); - SendDataToRearNode(MEDIASUBTYPE_BITSTREAM_T140, mTextToSend, nSendingDataSize, - mTimeLastSent, false, 0); + SendDataToRearNode(MEDIASUBTYPE_BITSTREAM_T140, data, size, mTimeLastSent, false, 0); + DeleteData(); mRedundantCount = mRedundantLevel; @@ -178,7 +143,7 @@ void TextSourceNode::ProcessData() * after the selected buffering time, an empty T140block SHOULD be transmitted. This * situation is regarded as the beginning of an idle period. */ - IMLOGD1("[ProcessData] send empty, nRedCount[%d]", mRedundantCount); + IMLOGD1("[ProcessData] send empty, redundant count[%d]", mRedundantCount); // send default if there is no data to send SendDataToRearNode(MEDIASUBTYPE_BITSTREAM_T140, nullptr, 0, ImsMediaTimer::GetTimeInMilliSeconds(), false, 0); @@ -188,72 +153,26 @@ void TextSourceNode::ProcessData() void TextSourceNode::SendRtt(const android::String8* text) { - if (text == nullptr || text->length() == 0) + if (text == NULL || text->length() == 0 || text->length() > MAX_RTT_LEN) { IMLOGE0("[SendRtt] invalid data"); return; } - IMLOGD2("[SendRtt] size[%u], listSize[%d]", text->length(), mListTextSource.size()); - std::lock_guard<std::mutex> guard(mMutex); + IMLOGD2("[SendRtt] size[%u], listSize[%d]", text->length(), mDataQueue.GetCount()); - uint8_t* pData = (uint8_t*)text->string(); - uint32_t nSize = text->length(); - uint32_t nChunkSize = 0; + uint8_t tempBuffer[MAX_RTT_LEN] = {'\0'}; + memcpy(tempBuffer, text->string(), text->length()); - while (nSize > 0) - { - // split with UTF-8 - if (pData[0] >= 0xC2 && pData[0] <= 0xDF && nSize >= 2) - { - nChunkSize = 2; - } - else if (pData[0] >= 0xE0 && pData[0] <= 0xEF && nSize >= 3) - { - nChunkSize = 3; - } - else if (pData[0] >= 0xF0 && pData[0] <= 0xFF && nSize >= 4) - { - nChunkSize = 4; - } - else // 1byte - { - nChunkSize = 1; - } - - uint8_t* buffer = (uint8_t*)calloc(nChunkSize, sizeof(uint8_t)); - - if (buffer == nullptr) - { - IMLOGE0("[SendRtt] allocated data is null"); - return; - } - - memcpy(buffer, pData, nChunkSize); - mListTextSource.push_back(buffer); - mListTextSourceSize.push_back(nChunkSize); - pData += nChunkSize; - nSize -= nChunkSize; - } + std::lock_guard<std::mutex> guard(mMutex); + AddData(tempBuffer, text->length(), 0, false, 0); } -void TextSourceNode::SendBOM() +void TextSourceNode::SendBom() { - const uint32_t sizeofBom = 3; - uint8_t* buffer = (uint8_t*)calloc(sizeofBom, sizeof(uint8_t)); - - if (buffer == nullptr) - { - IMLOGE0("[SendBOM] allocated data is null"); - return; - } - - // send BOM - The BOM character shall be 0xEFBBBF for UTF-8 - buffer[0] = 0xef; - buffer[1] = 0xbb; - buffer[2] = 0xbf; - IMLOGD0("[ProcessData] send BOM"); - mListTextSource.push_front(buffer); - mListTextSourceSize.push_front(sizeofBom); + uint8_t bom[3] = {0xEF, 0xBB, 0xBF}; + + std::lock_guard<std::mutex> guard(mMutex); + AddData(bom, sizeof(bom), 0, false, 0, MEDIASUBTYPE_UNDEFINED, MEDIASUBTYPE_UNDEFINED, 0, 0); }
\ No newline at end of file diff --git a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/text/nodes/TextSourceNodeTest.cpp b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/text/nodes/TextSourceNodeTest.cpp index d4ae8902..69a17eb4 100644 --- a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/text/nodes/TextSourceNodeTest.cpp +++ b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/text/nodes/TextSourceNodeTest.cpp @@ -15,17 +15,14 @@ */ #include <gtest/gtest.h> -#include <gmock/gmock.h> #include <TextConfig.h> #include <TextSourceNode.h> #include <ImsMediaCondition.h> -#include <MockBaseNode.h> +#include <string.h> using namespace android::telephony::imsmedia; using namespace android; -using ::testing::Return; - // RtpConfig const int32_t kMediaDirection = RtpConfig::MEDIA_DIRECTION_SEND_ONLY; const String8 kRemoteAddress("127.0.0.1"); @@ -48,41 +45,40 @@ const int8_t kRedundantPayload = 102; const int8_t kRedundantLevel = 3; const bool kKeepRedundantLevel = true; const int kTextInterval = 300; -const char* kBom = {"\xEF\xBB\xBF\0"}; +const uint8_t kBom[] = {0xEF, 0xBB, 0xBF}; -class FakeBaseNode : public BaseNode +class FakeTextNode : public BaseNode { public: - FakeBaseNode() { mEmptyFlag = false; } - virtual ~FakeBaseNode() {} + FakeTextNode() + { + mEmptyFlag = false; + memset(mData, 0, sizeof(mData)); + } + virtual ~FakeTextNode() {} virtual ImsMediaResult Start() { return RESULT_SUCCESS; } virtual void Stop() {} virtual bool IsRunTime() { return true; } virtual bool IsSourceNode() { return false; } virtual void SetConfig(void* config) { (void)config; } - virtual void OnDataFromFrontNode(ImsMediaSubType subtype, uint8_t* data, uint32_t size, - uint32_t timestamp, bool mark, uint32_t seq, ImsMediaSubType dataType, - uint32_t arrivalTime) + virtual void OnDataFromFrontNode(ImsMediaSubType /*subtype*/, uint8_t* data, uint32_t size, + uint32_t /*timestamp*/, bool /*mark*/, uint32_t /*seq*/, ImsMediaSubType /*dataType*/, + uint32_t /*arrivalTime*/) { - (void)subtype; - (void)timestamp; - (void)mark; - (void)seq; - (void)dataType; - (void)arrivalTime; - if (size != 0 && size <= MAX_RTT_LEN) { memset(mData, 0, sizeof(mData)); memcpy(mData, data, size); mEmptyFlag = false; } - else if (size == 0 && data == nullptr) + else if (data == nullptr) { mEmptyFlag = true; } } + virtual kBaseNodeState GetState() { return kNodeStateRunning; } + uint8_t* getData() { return mData; } bool getEmptyFlag() { return mEmptyFlag; } @@ -94,7 +90,11 @@ private: class TextSourceNodeTest : public ::testing::Test { public: - TextSourceNodeTest() {} + TextSourceNodeTest() + { + mNode = NULL; + mFakeNode = NULL; + } virtual ~TextSourceNodeTest() {} protected: @@ -102,8 +102,7 @@ protected: RtcpConfig mRtcp; ImsMediaCondition mCondition; TextSourceNode* mNode; - MockBaseNode* mMockNode; - FakeBaseNode mFakeNode; + FakeTextNode* mFakeNode; std::list<BaseNode*> mNodes; virtual void SetUp() override @@ -132,18 +131,12 @@ protected: mNode->SetConfig(&mConfig); mNodes.push_back(mNode); - mMockNode = new MockBaseNode(); - mMockNode->SetDelegate(&mFakeNode); - mMockNode->DelegateToFake(); - - mMockNode->SetMediaType(IMS_MEDIA_TEXT); - mMockNode->SetConfig(&mConfig); - mNodes.push_back(mMockNode); - - mNode->ConnectRearNode(mMockNode); - - ON_CALL(*mMockNode, GetState()).WillByDefault(Return(kNodeStateRunning)); - ON_CALL(*mMockNode, IsRunTime()).WillByDefault(Return(true)); + mFakeNode = new FakeTextNode(); + mFakeNode->SetMediaType(IMS_MEDIA_TEXT); + mFakeNode->SetConfig(&mConfig); + mNodes.push_back(mFakeNode); + mNode->ConnectRearNode(mFakeNode); + mCondition.reset(); } virtual void TearDown() override @@ -165,26 +158,46 @@ TEST_F(TextSourceNodeTest, startFail) EXPECT_EQ(mNode->Start(), RESULT_INVALID_PARAM); } +TEST_F(TextSourceNodeTest, sendRttDisableBom) +{ + mConfig.setKeepRedundantLevel(false); + mNode->SetConfig(&mConfig); + + EXPECT_EQ(mNode->Start(), RESULT_SUCCESS); + EXPECT_FALSE(mFakeNode->getEmptyFlag()); + + String8 testText1 = String8("a"); + mNode->SendRtt(&testText1); + + mNode->ProcessData(); + EXPECT_EQ(memcmp(mFakeNode->getData(), testText1.string(), testText1.length()), 0); + + mCondition.wait_timeout(kTextInterval); + mNode->ProcessData(); + // expect empty flag set + EXPECT_TRUE(mFakeNode->getEmptyFlag()); +} + TEST_F(TextSourceNodeTest, sendRttTestChunkSizeOne) { String8 testText1 = String8("a"); EXPECT_EQ(mNode->Start(), RESULT_SUCCESS); - EXPECT_FALSE(mFakeNode.getEmptyFlag()); + EXPECT_FALSE(mFakeNode->getEmptyFlag()); mNode->SendRtt(&testText1); mNode->ProcessData(); // expect BOM - EXPECT_EQ(String8((char*)mFakeNode.getData()), String8(kBom)); + EXPECT_EQ(memcmp(mFakeNode->getData(), kBom, sizeof(kBom)), 0); mCondition.wait_timeout(kTextInterval); mNode->ProcessData(); - EXPECT_EQ(String8((char*)mFakeNode.getData()), testText1); + EXPECT_EQ(memcmp(mFakeNode->getData(), testText1.string(), testText1.length()), 0); mCondition.wait_timeout(kTextInterval); mNode->ProcessData(); // expect empty flag set - EXPECT_TRUE(mFakeNode.getEmptyFlag()); + EXPECT_TRUE(mFakeNode->getEmptyFlag()); } TEST_F(TextSourceNodeTest, sendRttTestChunkSizeTwo) @@ -192,21 +205,21 @@ TEST_F(TextSourceNodeTest, sendRttTestChunkSizeTwo) String8 testText2 = String8("\xC2\xA9"); EXPECT_EQ(mNode->Start(), RESULT_SUCCESS); - EXPECT_FALSE(mFakeNode.getEmptyFlag()); + EXPECT_FALSE(mFakeNode->getEmptyFlag()); mNode->SendRtt(&testText2); mNode->ProcessData(); // expect BOM - EXPECT_EQ(String8((char*)mFakeNode.getData()), String8(kBom)); + EXPECT_EQ(memcmp(mFakeNode->getData(), kBom, sizeof(kBom)), 0); mCondition.wait_timeout(kTextInterval); mNode->ProcessData(); - EXPECT_EQ(String8((char*)mFakeNode.getData()), testText2); + EXPECT_EQ(memcmp(mFakeNode->getData(), testText2.string(), testText2.length()), 0); mCondition.wait_timeout(kTextInterval); mNode->ProcessData(); // expect empty flag set - EXPECT_TRUE(mFakeNode.getEmptyFlag()); + EXPECT_TRUE(mFakeNode->getEmptyFlag()); } TEST_F(TextSourceNodeTest, sendRttTestChunkSizeThree) @@ -214,21 +227,21 @@ TEST_F(TextSourceNodeTest, sendRttTestChunkSizeThree) String8 testText3 = String8("\xE2\x9C\x82"); EXPECT_EQ(mNode->Start(), RESULT_SUCCESS); - EXPECT_FALSE(mFakeNode.getEmptyFlag()); + EXPECT_FALSE(mFakeNode->getEmptyFlag()); mNode->SendRtt(&testText3); mNode->ProcessData(); // expect BOM - EXPECT_EQ(String8((char*)mFakeNode.getData()), String8(kBom)); + EXPECT_EQ(memcmp(mFakeNode->getData(), kBom, sizeof(kBom)), 0); mCondition.wait_timeout(kTextInterval); mNode->ProcessData(); - EXPECT_EQ(String8((char*)mFakeNode.getData()), testText3); + EXPECT_EQ(memcmp(mFakeNode->getData(), testText3.string(), testText3.length()), 0); mCondition.wait_timeout(kTextInterval); mNode->ProcessData(); // expect empty flag set - EXPECT_TRUE(mFakeNode.getEmptyFlag()); + EXPECT_TRUE(mFakeNode->getEmptyFlag()); } TEST_F(TextSourceNodeTest, sendRttTestChunkSizeFour) @@ -236,21 +249,21 @@ TEST_F(TextSourceNodeTest, sendRttTestChunkSizeFour) String8 testText4 = String8("\xF0\x9F\x9A\x80"); EXPECT_EQ(mNode->Start(), RESULT_SUCCESS); - EXPECT_FALSE(mFakeNode.getEmptyFlag()); + EXPECT_FALSE(mFakeNode->getEmptyFlag()); mNode->SendRtt(&testText4); mNode->ProcessData(); // expect BOM - EXPECT_EQ(String8((char*)mFakeNode.getData()), String8(kBom)); + EXPECT_EQ(memcmp(mFakeNode->getData(), kBom, sizeof(kBom)), 0); mCondition.wait_timeout(kTextInterval); mNode->ProcessData(); - EXPECT_EQ(String8((char*)mFakeNode.getData()), testText4); + EXPECT_EQ(memcmp(mFakeNode->getData(), testText4.string(), testText4.length()), 0); mCondition.wait_timeout(kTextInterval); mNode->ProcessData(); // expect empty flag set - EXPECT_TRUE(mFakeNode.getEmptyFlag()); + EXPECT_TRUE(mFakeNode->getEmptyFlag()); } TEST_F(TextSourceNodeTest, sendRttTestLongString) @@ -267,31 +280,19 @@ TEST_F(TextSourceNodeTest, sendRttTestLongString) testText5.append(testText4); EXPECT_EQ(mNode->Start(), RESULT_SUCCESS); - EXPECT_FALSE(mFakeNode.getEmptyFlag()); + EXPECT_FALSE(mFakeNode->getEmptyFlag()); mNode->SendRtt(&testText5); mNode->ProcessData(); // expect BOM - EXPECT_EQ(String8((char*)mFakeNode.getData()), String8(kBom)); - - mCondition.wait_timeout(kTextInterval); - mNode->ProcessData(); - EXPECT_EQ(String8((char*)mFakeNode.getData()), testText1); - - mCondition.wait_timeout(kTextInterval); - mNode->ProcessData(); - EXPECT_EQ(String8((char*)mFakeNode.getData()), testText2); - - mCondition.wait_timeout(kTextInterval); - mNode->ProcessData(); - EXPECT_EQ(String8((char*)mFakeNode.getData()), testText3); + EXPECT_EQ(memcmp(mFakeNode->getData(), kBom, sizeof(kBom)), 0); mCondition.wait_timeout(kTextInterval); mNode->ProcessData(); - EXPECT_EQ(String8((char*)mFakeNode.getData()), testText4); + EXPECT_EQ(memcmp(mFakeNode->getData(), testText5.string(), testText5.length()), 0); mCondition.wait_timeout(kTextInterval); mNode->ProcessData(); // expect empty flag set - EXPECT_TRUE(mFakeNode.getEmptyFlag()); + EXPECT_TRUE(mFakeNode->getEmptyFlag()); } |