Merge "Move existing active audio session to inactive before modifying current session to active" into udc-qpr-dev am: 099ccf9561 am: 5ec229e1ef

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/modules/ImsMedia/+/25407138

Change-Id: I991cf0fa68786054ffa2cb7d3cc8112c74995b17
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.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/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/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/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