Merge "Audio: voice concurrency support for 8916"
diff --git a/policy_hal/AudioPolicyManager.cpp b/policy_hal/AudioPolicyManager.cpp
index 4501239..03f6c41 100644
--- a/policy_hal/AudioPolicyManager.cpp
+++ b/policy_hal/AudioPolicyManager.cpp
@@ -595,7 +595,63 @@
         return 0;
     }
 
+#ifdef VOICE_CONCURRENCY
 
+    char propValue[PROPERTY_VALUE_MAX];
+    bool prop_rec_enabled=false, prop_voip_enabled = false;
+
+    if(property_get("voice.record.conc.disabled", propValue, NULL)) {
+        prop_rec_enabled = atoi(propValue) || !strncmp("true", propValue, 4);
+    }
+
+    if(property_get("voice.voip.conc.disabled", propValue, NULL)) {
+        prop_voip_enabled = atoi(propValue) || !strncmp("true", propValue, 4);
+    }
+
+    if (prop_rec_enabled) {
+         //check if voice call is active  / running in background
+         //some of VoIP apps(like SIP2SIP call) supports resume of VoIP call when call in progress
+         //Need to block input request
+        if((AudioSystem::MODE_IN_CALL == mPhoneState) ||
+           ((AudioSystem::MODE_IN_CALL == mPrevPhoneState) &&
+             (AudioSystem::MODE_IN_COMMUNICATION == mPhoneState)))
+        {
+            switch(inputSource) {
+                case AUDIO_SOURCE_VOICE_UPLINK:
+                case AUDIO_SOURCE_VOICE_DOWNLINK:
+                case AUDIO_SOURCE_VOICE_CALL:
+                    ALOGD("Creating input during incall mode for inputSource: %d ",inputSource);
+                break;
+
+                 case AUDIO_SOURCE_VOICE_COMMUNICATION:
+                    if(prop_voip_enabled) {
+                        ALOGD("BLOCKING VoIP request during incall mode for inputSource: %d ",inputSource);
+                        return 0;
+                    }
+                break;
+
+               default:
+                   ALOGD("BLOCKING input during incall mode for inputSource: %d ",inputSource);
+               return 0;
+            }
+        }
+    }//check for VoIP flag
+    else if(prop_voip_enabled) {
+         //check if voice call is active  / running in background
+         //some of VoIP apps(like SIP2SIP call) supports resume of VoIP call when call in progress
+         //Need to block input request
+        if((AudioSystem::MODE_IN_CALL == mPhoneState) ||
+           ((AudioSystem::MODE_IN_CALL == mPrevPhoneState) &&
+             (AudioSystem::MODE_IN_COMMUNICATION == mPhoneState)))
+        {
+            if(inputSource == AUDIO_SOURCE_VOICE_COMMUNICATION) {
+                ALOGD("BLOCKING VoIP request during incall mode for inputSource: %d ",inputSource);
+                return 0;
+            }
+        }
+    }
+
+#endif
     IOProfile *profile = getInputProfile(device,
                                          samplingRate,
                                          format,
@@ -1140,13 +1196,49 @@
     IOProfile *profile = NULL;
 
 #ifdef VOICE_CONCURRENCY
-    if (isInCall()) {
-        ALOGV(" IN call mode adding ULL flags .. flags: %x ", flags );
-        //For voip paths
-        if(flags & AudioSystem::OUTPUT_FLAG_DIRECT)
-            flags = AudioSystem::OUTPUT_FLAG_DIRECT;
-        else //route every thing else to ULL path
-            flags = (AudioSystem::output_flags)AUDIO_OUTPUT_FLAG_FAST;
+    char propValue[PROPERTY_VALUE_MAX];
+    bool prop_play_enabled=false, prop_voip_enabled = false;
+
+    if(property_get("voice.playback.conc.disabled", propValue, NULL)) {
+       prop_play_enabled = atoi(propValue) || !strncmp("true", propValue, 4);
+    }
+
+    if(property_get("voice.voip.conc.disabled", propValue, NULL)) {
+       prop_voip_enabled = atoi(propValue) || !strncmp("true", propValue, 4);
+    }
+
+    if (prop_play_enabled) {
+        //check if voice call is active  / running in background
+        if((AudioSystem::MODE_IN_CALL == mPhoneState) ||
+             ((AudioSystem::MODE_IN_CALL == mPrevPhoneState)
+                && (AudioSystem::MODE_IN_COMMUNICATION == mPhoneState)))
+        {
+            if(AUDIO_OUTPUT_FLAG_VOIP_RX  & flags) {
+                if(prop_voip_enabled) {
+                    ALOGD(" IN call mode returing no output .. for VoIP usecase flags: %x ", flags );
+                   // flags = (AudioSystem::output_flags)AUDIO_OUTPUT_FLAG_FAST;
+                   return 0;
+                }
+            }
+            else {
+                ALOGD(" IN call mode adding ULL flags .. flags: %x ", flags );
+                flags = (AudioSystem::output_flags)AUDIO_OUTPUT_FLAG_FAST;
+            }
+        }
+    } else if (prop_voip_enabled) {
+        //check if voice call is active  / running in background
+        //some of VoIP apps(like SIP2SIP call) supports resume of VoIP call when call in progress
+        //return only ULL ouput
+        if((AudioSystem::MODE_IN_CALL == mPhoneState) ||
+             ((AudioSystem::MODE_IN_CALL == mPrevPhoneState)
+                && (AudioSystem::MODE_IN_COMMUNICATION == mPhoneState)))
+        {
+            if(AUDIO_OUTPUT_FLAG_VOIP_RX  & flags) {
+                ALOGD(" IN call mode returing no output .. for VoIP usecase flags: %x ", flags );
+               // flags = (AudioSystem::output_flags)AUDIO_OUTPUT_FLAG_FAST;
+               return 0;
+            }
+        }
     }
 #endif
 
@@ -1329,11 +1421,18 @@
      offloadInfo.has_video);
 
 #ifdef VOICE_CONCURRENCY
-    if(isInCall())
-    {
-        ALOGD("\n  blocking  compress offload on call mode\n");
-        return false;
+    char concpropValue[PROPERTY_VALUE_MAX];
+    if(property_get("voice.playback.conc.disabled", concpropValue, NULL)) {
+         bool propenabled = atoi(concpropValue) || !strncmp("true", concpropValue, 4);
+         if (propenabled) {
+            if(isInCall())
+            {
+                ALOGD("\n  blocking  compress offload on call mode\n");
+                return false;
+            }
+         }
     }
+
 #endif
     // Check if stream type is music, then only allow offload as of now.
     if (offloadInfo.stream_type != AUDIO_STREAM_MUSIC)
@@ -1441,7 +1540,7 @@
 void AudioPolicyManager::setPhoneState(int state)
 
 {
-    ALOGV("setPhoneState() state %d", state);
+    ALOGD("setPhoneState() state %d", state);
     audio_devices_t newDevice = AUDIO_DEVICE_NONE;
     if (state < 0 || state >= AudioSystem::NUM_MODES) {
         ALOGW("setPhoneState() invalid state %d", state);
@@ -1506,6 +1605,117 @@
     if (isStateInCall(oldState) && newDevice == AUDIO_DEVICE_NONE) {
         newDevice = hwOutputDesc->device();
     }
+#ifdef VOICE_CONCURRENCY
+    char propValue[PROPERTY_VALUE_MAX];
+    bool prop_playback_enabled = false, prop_rec_enabled=false, prop_voip_enabled = false;
+
+    if(property_get("voice.playback.conc.disabled", propValue, NULL)) {
+        prop_playback_enabled = atoi(propValue) || !strncmp("true", propValue, 4);
+    }
+
+    if(property_get("voice.record.conc.disabled", propValue, NULL)) {
+        prop_rec_enabled = atoi(propValue) || !strncmp("true", propValue, 4);
+    }
+
+    if(property_get("voice.voip.conc.disabled", propValue, NULL)) {
+        prop_voip_enabled = atoi(propValue) || !strncmp("true", propValue, 4);
+    }
+
+    if((AudioSystem::MODE_IN_CALL != oldState) && (AudioSystem::MODE_IN_CALL == state)) {
+        ALOGD("Entering to call mode oldState :: %d state::%d ",oldState, state);
+
+        if(prop_playback_enabled) {
+            //Call invalidate to reset all opened non ULL audio tracks
+            // Move tracks associated to this strategy from previous output to new output
+            for (int i = AudioSystem::SYSTEM; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
+                ALOGV(" Invalidate on call mode for stream :: %d ", i);
+                //FIXME see fixme on name change
+                mpClientInterface->setStreamOutput((AudioSystem::stream_type)i,
+                                                  0 /* ignored */);
+            }
+        }
+
+        if(prop_rec_enabled) {
+            //Close all active inputs
+            audio_io_handle_t activeInput = getActiveInput();
+            if (activeInput != 0) {
+               AudioInputDescriptor *activeDesc = mInputs.valueFor(activeInput);
+               switch(activeDesc->mInputSource) {
+                   case AUDIO_SOURCE_VOICE_UPLINK:
+                   case AUDIO_SOURCE_VOICE_DOWNLINK:
+                   case AUDIO_SOURCE_VOICE_CALL:
+                       ALOGD("FOUND active input during call active: %d",activeDesc->mInputSource);
+                   break;
+
+                   case  AUDIO_SOURCE_VOICE_COMMUNICATION:
+                        if(prop_voip_enabled) {
+                            ALOGD("CLOSING VoIP input source on call setup :%d ",activeDesc->mInputSource);
+                            stopInput(activeInput);
+                            releaseInput(activeInput);
+                        }
+                   break;
+
+                   default:
+                       ALOGD("CLOSING input on call setup  for inputSource: %d",activeDesc->mInputSource);
+                       stopInput(activeInput);
+                       releaseInput(activeInput);
+                   break;
+               }
+           }
+        } else if(prop_voip_enabled) {
+            audio_io_handle_t activeInput = getActiveInput();
+            if (activeInput != 0) {
+               AudioInputDescriptor *activeDesc = mInputs.valueFor(activeInput);
+                if(AUDIO_SOURCE_VOICE_COMMUNICATION == activeDesc->mInputSource) {
+                    ALOGD("CLOSING VoIP on call setup : %d",activeDesc->mInputSource);
+                    stopInput(activeInput);
+                    releaseInput(activeInput);
+                }
+            }
+        }
+
+        //suspend  PCM (deep-buffer) output & close  compress & direct tracks
+        for (size_t i = 0; i < mOutputs.size(); i++) {
+            AudioOutputDescriptor *outputDesc = mOutputs.valueAt(i);
+            if (((!outputDesc->isDuplicated() &&outputDesc->mProfile->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY))
+                        && prop_playback_enabled) {
+                ALOGD(" calling suspendOutput on call mdoe for primary output");
+                mpClientInterface->suspendOutput(mOutputs.keyAt(i));
+            } //Close compress all sessions
+            else if ((outputDesc->mProfile->mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
+                            &&  prop_playback_enabled) {
+                ALOGD(" calling closeOutput on call mdoe for COMPRESS output");
+                closeOutput(mOutputs.keyAt(i));
+            }
+            else if ((outputDesc->mProfile->mFlags & AUDIO_OUTPUT_FLAG_VOIP_RX)
+                            && prop_voip_enabled) {
+                ALOGD(" calling closeOutput on call mdoe for DIRECT  output");
+                closeOutput(mOutputs.keyAt(i));
+            }
+        }
+   }
+
+   if((AudioSystem::MODE_IN_CALL == oldState) && (AudioSystem::MODE_IN_CALL != state)
+             && prop_playback_enabled) {
+        ALOGD("EXITING from call mode oldState :: %d state::%d \n",oldState, state);
+        //restore PCM (deep-buffer) output after call termination
+        for (size_t i = 0; i < mOutputs.size(); i++) {
+            AudioOutputDescriptor *outputDesc = mOutputs.valueAt(i);
+            if (!outputDesc->isDuplicated() &&outputDesc->mProfile->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) {
+                ALOGD("calling restoreOutput after call mode for primary output");
+                mpClientInterface->restoreOutput(mOutputs.keyAt(i));
+            }
+       }
+       //call invalidate tracks so that any open streams can fall back to deep buffer/compress path from ULL
+       for (int i = AudioSystem::SYSTEM; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
+           ALOGD("Invalidate on call mode for stream :: %d ", i);
+           //FIXME see fixme on name change
+           mpClientInterface->setStreamOutput((AudioSystem::stream_type)i,
+                                                  0 /* ignored */);
+       }
+    }
+    mPrevPhoneState = oldState;
+#endif
 
     int delayMs = 0;
     if (isStateInCall(state)) {
@@ -1552,21 +1762,7 @@
     } else {
         mLimitRingtoneVolume = false;
     }
-
-#ifdef VOICE_CONCURRENCY
-    //Call invalidate to reset all opened non ULL audio tracks
-    if(isInCall())
-    {
-        // Move tracks associated to this strategy from previous output to new output
-        for (int i = AudioSystem::SYSTEM; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
-                ALOGV("\n Invalidate on call mode for stream :: %d  \n", i);
-                //FIXME see fixme on name change
-                mpClientInterface->setStreamOutput((AudioSystem::stream_type)i,
-                                                  0 /* ignored */);
-        }
-    }
-#endif
-
+    ALOGD(" End of setPhoneState ... mPhoneState: %d ",mPhoneState);
 }
 
 extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
diff --git a/policy_hal/AudioPolicyManager.h b/policy_hal/AudioPolicyManager.h
index ca7031d..f2488b2 100644
--- a/policy_hal/AudioPolicyManager.h
+++ b/policy_hal/AudioPolicyManager.h
@@ -106,8 +106,12 @@
         //parameter indicates if HDMI plug in/out detected
         bool mHdmiAudioEvent;
 
+
 private:
         void handleNotificationRoutingForStream(AudioSystem::stream_type stream);
 
+        // Used for voip + voice concurrency usecase
+        int mPrevPhoneState;
+
 };
 };