do not merge bug 3370834 Cherrypick from master

Cherripick from master CL 79833, 79417, 78864, 80332, 87500

Add new audio mode and recording source for audio communications
 other than telelphony.

The audio mode MODE_IN_CALL signals the system the device a phone
 call is currently underway. There was no way for audio video
 chat or VoIP applications to signal a call is underway, but not
 using the telephony resources. This change introduces a new mode
 to address this. Changes in other parts of the system (java
 and native) are required to take this new mode into account.
The generic AudioPolicyManager is updated to not use its phone
 state variable directly, but to use two new convenience methods,
 isInCall() and isStateInCall(int) instead.

Add a recording source used to designate a recording stream for
voice communications such as VoIP.

Update the platform-independent audio policy manager to pass the
 nature of the audio recording source to the audio policy client
 interface through the AudioPolicyClientInterface::setParameters()
 method.

SIP calls should set the audio mode to MODE_IN_COMMUNICATION,
 Audio mode MODE_IN_CALL is reserved for telephony.

SIP: Enable built-in echo canceler if available.
1. Always initialize AudioRecord with VOICE_COMMUNICATION.
2. If echo canceler is available, disable our echo suppressor.

Note that this CL is intentionally not correcting the
 getAudioSourceMax() return value in MediaRecorder.java as the
 new source is hidden here.

Change-Id: Ie68cd03c50553101aa2ad838fe9459b2cf151bc8
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 9fd905f..e881747 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -156,6 +156,7 @@
         MODE_NORMAL = 0,
         MODE_RINGTONE,
         MODE_IN_CALL,
+        MODE_IN_COMMUNICATION,
         NUM_MODES  // not a valid entry, denotes end-of-list
     };
 
@@ -466,7 +467,7 @@
     AudioParameter(const String8& keyValuePairs);
     virtual ~AudioParameter();
 
-    // reserved parameter keys for changeing standard parameters with setParameters() function.
+    // reserved parameter keys for changing standard parameters with setParameters() function.
     // Using these keys is mandatory for AudioFlinger to properly monitor audio output/input
     // configuration changes and act accordingly.
     //  keyRouting: to change audio routing, value is an int in AudioSystem::audio_devices
@@ -474,11 +475,14 @@
     //  keyFormat: to change audio format, value is an int in AudioSystem::audio_format
     //  keyChannels: to change audio channel configuration, value is an int in AudioSystem::audio_channels
     //  keyFrameCount: to change audio output frame count, value is an int
+    //  keyInputSource: to change audio input source, value is an int in audio_source
+    //     (defined in media/mediarecorder.h)
     static const char *keyRouting;
     static const char *keySamplingRate;
     static const char *keyFormat;
     static const char *keyChannels;
     static const char *keyFrameCount;
+    static const char *keyInputSource;
 
     String8 toString();
 
diff --git a/include/media/EffectApi.h b/include/media/EffectApi.h
index 16fb43c..b97c22e 100644
--- a/include/media/EffectApi.h
+++ b/include/media/EffectApi.h
@@ -602,9 +602,9 @@
 
 // Audio mode
 enum audio_mode_e {
-    AUDIO_MODE_NORMAL,      // phone idle
-    AUDIO_MODE_RINGTONE,    // phone ringing
-    AUDIO_MODE_IN_CALL      // phone call connected
+    AUDIO_MODE_NORMAL,      // device idle
+    AUDIO_MODE_RINGTONE,    // device ringing
+    AUDIO_MODE_IN_CALL      // audio call connected (VoIP or telephony)
 };
 
 // Values for "accessMode" field of buffer_config_t:
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index 5ab1640..9a76393 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -44,7 +44,8 @@
     AUDIO_SOURCE_VOICE_CALL = 4,
     AUDIO_SOURCE_CAMCORDER = 5,
     AUDIO_SOURCE_VOICE_RECOGNITION = 6,
-    AUDIO_SOURCE_MAX = AUDIO_SOURCE_VOICE_RECOGNITION,
+    AUDIO_SOURCE_VOICE_COMMUNICATION = 7,
+    AUDIO_SOURCE_MAX = AUDIO_SOURCE_VOICE_COMMUNICATION,
 
     AUDIO_SOURCE_LIST_END  // must be last - used to validate audio source type
 };
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index bbbba74..4459505 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -966,9 +966,14 @@
      */
     public static final int MODE_RINGTONE           = AudioSystem.MODE_RINGTONE;
     /**
-     * In call audio mode. A call is established.
+     * In call audio mode. A telephony call is established.
      */
     public static final int MODE_IN_CALL            = AudioSystem.MODE_IN_CALL;
+    /**
+     * @hide
+     * In communication audio mode. An audio/video chat or VoIP call is established.
+     */
+    public static final int MODE_IN_COMMUNICATION   = AudioSystem.MODE_IN_COMMUNICATION;
 
     /* Routing bits for setRouting/getRouting API */
     /**
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index c48eaad..0eb39db 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -252,7 +252,8 @@
         //--------------
         // audio source
         if ( (audioSource < MediaRecorder.AudioSource.DEFAULT) ||
-             (audioSource > MediaRecorder.getAudioSourceMax()) )  {
+                (audioSource > MediaRecorder.AudioSource.VOICE_COMMUNICATION) )  {
+                //(audioSource > MediaRecorder.getAudioSourceMax()) )  {
             throw (new IllegalArgumentException("Invalid audio source."));
         } else {
             mRecordSource = audioSource;
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 41d2cc5..06e00c5 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -708,7 +708,7 @@
             return;
         }
 
-        if (mode < AudioSystem.MODE_CURRENT || mode > AudioSystem.MODE_IN_CALL) {
+        if (mode < AudioSystem.MODE_CURRENT || mode >= AudioSystem.NUM_MODES) {
             return;
         }
 
@@ -2259,6 +2259,7 @@
                 //      add modify the phone app to take advantage of the new API
                 synchronized(mRingingLock) {
                     if (mIsRinging || (getMode() == AudioSystem.MODE_IN_CALL) ||
+                            (getMode() == AudioSystem.MODE_IN_COMMUNICATION) ||
                             (getMode() == AudioSystem.MODE_RINGTONE) ) {
                         return;
                     }
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index a4818ff..4ddbb35 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -106,7 +106,8 @@
     public static final int MODE_NORMAL             = 0;
     public static final int MODE_RINGTONE           = 1;
     public static final int MODE_IN_CALL            = 2;
-    public static final int NUM_MODES               = 3;
+    public static final int MODE_IN_COMMUNICATION   = 3;
+    public static final int NUM_MODES               = 4;
 
 
     /* Routing bits for setRouting/getRouting API */
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 32c02bc..d9f2302 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -145,6 +145,15 @@
         /** Microphone audio source tuned for voice recognition if available, behaves like
          *  {@link #DEFAULT} otherwise. */
         public static final int VOICE_RECOGNITION = 6;
+
+        /**
+         * @hide
+         * Microphone audio source tuned for voice communications such as VoIP. It
+         * will for instance take advantage of echo cancellation or automatic gain control
+         * if available. It otherwise behaves like {@link #DEFAULT} if no voice processing
+         * is available.
+         */
+        public static final int VOICE_COMMUNICATION = 7;
     }
 
     /**
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 9c2a8ba..1a3fcd6 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -835,6 +835,7 @@
 const char *AudioParameter::keyFormat = "format";
 const char *AudioParameter::keyChannels = "channels";
 const char *AudioParameter::keyFrameCount = "frame_count";
+const char *AudioParameter::keyInputSource = "input_source";
 
 AudioParameter::AudioParameter(const String8& keyValuePairs)
 {
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 5071555..5935bf9 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -5810,7 +5810,8 @@
 const uint32_t AudioFlinger::EffectModule::sModeConvTable[] = {
     AUDIO_MODE_NORMAL,   // AudioSystem::MODE_NORMAL
     AUDIO_MODE_RINGTONE, // AudioSystem::MODE_RINGTONE
-    AUDIO_MODE_IN_CALL   // AudioSystem::MODE_IN_CALL
+    AUDIO_MODE_IN_CALL,  // AudioSystem::MODE_IN_CALL
+    AUDIO_MODE_IN_CALL   // AudioSystem::MODE_IN_COMMUNICATION, same conversion as for MODE_IN_CALL
 };
 
 int AudioFlinger::EffectModule::modeAudioSystemToEffectApi(uint32_t mode)
diff --git a/services/audioflinger/AudioHardwareInterface.cpp b/services/audioflinger/AudioHardwareInterface.cpp
index 9a4a7f9..f58e4c0 100644
--- a/services/audioflinger/AudioHardwareInterface.cpp
+++ b/services/audioflinger/AudioHardwareInterface.cpp
@@ -48,14 +48,15 @@
     "CURRENT",
     "NORMAL",
     "RINGTONE",
-    "IN_CALL"
+    "IN_CALL",
+    "IN_COMMUNICATION"
 };
 
 static const char* routeNone = "NONE";
 
 static const char* displayMode(int mode)
 {
-    if ((mode < -2) || (mode > 2))
+    if ((mode < AudioSystem::MODE_INVALID) || (mode >= AudioSystem::NUM_MODES))
         return routingModeStrings[0];
     return routingModeStrings[mode+3];
 }
diff --git a/services/audioflinger/AudioPolicyManagerBase.cpp b/services/audioflinger/AudioPolicyManagerBase.cpp
index 8d16ab4..0da353a 100644
--- a/services/audioflinger/AudioPolicyManagerBase.cpp
+++ b/services/audioflinger/AudioPolicyManagerBase.cpp
@@ -235,7 +235,7 @@
 
     // if leaving call state, handle special case of active streams
     // pertaining to sonification strategy see handleIncallSonification()
-    if (mPhoneState == AudioSystem::MODE_IN_CALL) {
+    if (isInCall()) {
         LOGV("setPhoneState() in call state management: new state is %d", state);
         for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
             handleIncallSonification(stream, false, true);
@@ -248,16 +248,21 @@
     bool force = false;
 
     // are we entering or starting a call
-    if ((oldState != AudioSystem::MODE_IN_CALL) && (state == AudioSystem::MODE_IN_CALL)) {
+    if (!isStateInCall(oldState) && isStateInCall(state)) {
         LOGV("  Entering call in setPhoneState()");
         // force routing command to audio hardware when starting a call
         // even if no device change is needed
         force = true;
-    } else if ((oldState == AudioSystem::MODE_IN_CALL) && (state != AudioSystem::MODE_IN_CALL)) {
+    } else if (isStateInCall(oldState) && !isStateInCall(state)) {
         LOGV("  Exiting call in setPhoneState()");
         // force routing command to audio hardware when exiting a call
         // even if no device change is needed
         force = true;
+    } else if (isStateInCall(state) && (state != oldState)) {
+        LOGV("  Switching between telephony and VoIP in setPhoneState()");
+        // force routing command to audio hardware when switching between telephony and VoIP
+        // even if no device change is needed
+        force = true;
     }
 
     // check for device and output changes triggered by new phone state
@@ -272,7 +277,7 @@
 
     // force routing command to audio hardware when ending call
     // even if no device change is needed
-    if (oldState == AudioSystem::MODE_IN_CALL && newDevice == 0) {
+    if (isStateInCall(oldState) && newDevice == 0) {
         newDevice = hwOutputDesc->device();
     }
 
@@ -280,7 +285,7 @@
     // immediately and delay the route change to avoid sending the ring tone
     // tail into the earpiece or headset.
     int delayMs = 0;
-    if (state == AudioSystem::MODE_IN_CALL && oldState == AudioSystem::MODE_RINGTONE) {
+    if (isStateInCall(state) && oldState == AudioSystem::MODE_RINGTONE) {
         // delay the device change command by twice the output latency to have some margin
         // and be sure that audio buffers not yet affected by the mute are out when
         // we actually apply the route change
@@ -293,7 +298,7 @@
 
     // if entering in call state, handle special case of active streams
     // pertaining to sonification strategy see handleIncallSonification()
-    if (state == AudioSystem::MODE_IN_CALL) {
+    if (isStateInCall(state)) {
         LOGV("setPhoneState() in call state management: new state is %d", state);
         // unmute the ringing tone after a sufficient delay if it was muted before
         // setting output device above
@@ -564,7 +569,7 @@
     setOutputDevice(output, getNewDevice(output));
 
     // handle special case for sonification while in call
-    if (mPhoneState == AudioSystem::MODE_IN_CALL) {
+    if (isInCall()) {
         handleIncallSonification(stream, true, false);
     }
 
@@ -589,7 +594,7 @@
     routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream);
 
     // handle special case for sonification while in call
-    if (mPhoneState == AudioSystem::MODE_IN_CALL) {
+    if (isInCall()) {
         handleIncallSonification(stream, false, false);
     }
 
@@ -738,10 +743,8 @@
     AudioParameter param = AudioParameter();
     param.addInt(String8(AudioParameter::keyRouting), (int)inputDesc->mDevice);
 
-    // use Voice Recognition mode or not for this input based on input source
-    int vr_enabled = inputDesc->mInputSource == AUDIO_SOURCE_VOICE_RECOGNITION ? 1 : 0;
-    param.addInt(String8("vr_mode"), vr_enabled);
-    LOGV("AudioPolicyManager::startInput(%d), setting vr_mode to %d", inputDesc->mInputSource, vr_enabled);
+    param.addInt(String8(AudioParameter::keyInputSource), (int)inputDesc->mInputSource);
+    LOGV("AudioPolicyManager::startInput() input source = %d", inputDesc->mInputSource);
 
     mpClientInterface->setParameters(input, param.toString());
 
@@ -1494,7 +1497,7 @@
     //      use device for strategy media
     // 4: the strategy DTMF is active on the hardware output:
     //      use device for strategy DTMF
-    if (mPhoneState == AudioSystem::MODE_IN_CALL ||
+    if (isInCall() ||
         outputDesc->isUsedByStrategy(STRATEGY_PHONE)) {
         device = getDeviceForStrategy(STRATEGY_PHONE, fromCache);
     } else if (outputDesc->isUsedByStrategy(STRATEGY_SONIFICATION)) {
@@ -1549,7 +1552,7 @@
 
     switch (strategy) {
     case STRATEGY_DTMF:
-        if (mPhoneState != AudioSystem::MODE_IN_CALL) {
+        if (!isInCall()) {
             // when off call, DTMF strategy follows the same rules as MEDIA strategy
             device = getDeviceForStrategy(STRATEGY_MEDIA, false);
             break;
@@ -1562,7 +1565,7 @@
         // of priority
         switch (mForceUse[AudioSystem::FOR_COMMUNICATION]) {
         case AudioSystem::FORCE_BT_SCO:
-            if (mPhoneState != AudioSystem::MODE_IN_CALL || strategy != STRATEGY_DTMF) {
+            if (!isInCall() || strategy != STRATEGY_DTMF) {
                 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
                 if (device) break;
             }
@@ -1580,7 +1583,7 @@
             if (device) break;
 #ifdef WITH_A2DP
             // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
-            if (mPhoneState != AudioSystem::MODE_IN_CALL) {
+            if (!isInCall()) {
                 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP;
                 if (device) break;
                 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
@@ -1594,14 +1597,14 @@
             break;
 
         case AudioSystem::FORCE_SPEAKER:
-            if (mPhoneState != AudioSystem::MODE_IN_CALL || strategy != STRATEGY_DTMF) {
+            if (!isInCall() || strategy != STRATEGY_DTMF) {
                 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
                 if (device) break;
             }
 #ifdef WITH_A2DP
             // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to
             // A2DP speaker when forcing to speaker output
-            if (mPhoneState != AudioSystem::MODE_IN_CALL) {
+            if (!isInCall()) {
                 device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
                 if (device) break;
             }
@@ -1618,7 +1621,7 @@
 
         // If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by
         // handleIncallSonification().
-        if (mPhoneState == AudioSystem::MODE_IN_CALL) {
+        if (isInCall()) {
             device = getDeviceForStrategy(STRATEGY_PHONE, false);
             break;
         }
@@ -1739,6 +1742,7 @@
     case AUDIO_SOURCE_DEFAULT:
     case AUDIO_SOURCE_MIC:
     case AUDIO_SOURCE_VOICE_RECOGNITION:
+    case AUDIO_SOURCE_VOICE_COMMUNICATION:
         if (mForceUse[AudioSystem::FOR_RECORD] == AudioSystem::FORCE_BT_SCO &&
             mAvailableInputDevices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
             device = AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET;
@@ -1960,6 +1964,16 @@
     }
 }
 
+bool AudioPolicyManagerBase::isInCall()
+{
+    return isStateInCall(mPhoneState);
+}
+
+bool AudioPolicyManagerBase::isStateInCall(int state) {
+    return ((state == AudioSystem::MODE_IN_CALL) ||
+            (state == AudioSystem::MODE_IN_COMMUNICATION));
+}
+
 bool AudioPolicyManagerBase::needsDirectOuput(AudioSystem::stream_type stream,
                                     uint32_t samplingRate,
                                     uint32_t format,
diff --git a/telephony/java/com/android/internal/telephony/CallManager.java b/telephony/java/com/android/internal/telephony/CallManager.java
index 0335ca2..b89058f 100644
--- a/telephony/java/com/android/internal/telephony/CallManager.java
+++ b/telephony/java/com/android/internal/telephony/CallManager.java
@@ -380,12 +380,17 @@
                 break;
             case OFFHOOK:
                 Phone fgPhone = getFgPhone();
-                // Enable IN_CALL mode while foreground call is in DIALING,
-                // ALERTING, ACTIVE and DISCONNECTING state and not from sipPhone
+                // While foreground call is in DIALING,
+                // ALERTING, ACTIVE and DISCONNECTING state
                 if (getActiveFgCallState() != Call.State.IDLE
-                        && getActiveFgCallState() != Call.State.DISCONNECTED
-                        && !(fgPhone instanceof SipPhone)) {
-                    mode = AudioManager.MODE_IN_CALL;
+                        && getActiveFgCallState() != Call.State.DISCONNECTED) {
+                    if (fgPhone instanceof SipPhone) {
+                        // enable IN_COMMUNICATION audio mode for sipPhone
+                        mode = AudioManager.MODE_IN_COMMUNICATION;
+                    } else {
+                        // enable IN_CALL audio mode for telephony
+                        mode = AudioManager.MODE_IN_CALL;
+                    }
                 }
                 break;
         }
diff --git a/voip/jni/rtp/AudioGroup.cpp b/voip/jni/rtp/AudioGroup.cpp
index 60abf2a..2cbd023 100644
--- a/voip/jni/rtp/AudioGroup.cpp
+++ b/voip/jni/rtp/AudioGroup.cpp
@@ -483,7 +483,7 @@
         ON_HOLD = 0,
         MUTED = 1,
         NORMAL = 2,
-        EC_ENABLED = 3,
+        ECHO_SUPPRESSION = 3,
         LAST_MODE = 3,
     };
 
@@ -619,6 +619,10 @@
     if (mode < 0 || mode > LAST_MODE) {
         return false;
     }
+    if (mode == ECHO_SUPPRESSION && AudioSystem::getParameters(
+        0, String8("ec_supported")) == "ec_supported=yes") {
+        mode = NORMAL;
+    }
     if (mMode == mode) {
         return true;
     }
@@ -775,8 +779,8 @@
     AudioTrack track;
     AudioRecord record;
     if (track.set(AudioSystem::VOICE_CALL, sampleRate, AudioSystem::PCM_16_BIT,
-        AudioSystem::CHANNEL_OUT_MONO, output) != NO_ERROR ||
-        record.set(AUDIO_SOURCE_MIC, sampleRate, AudioSystem::PCM_16_BIT,
+        AudioSystem::CHANNEL_OUT_MONO, output) != NO_ERROR || record.set(
+        AUDIO_SOURCE_VOICE_COMMUNICATION, sampleRate, AudioSystem::PCM_16_BIT,
         AudioSystem::CHANNEL_IN_MONO, input) != NO_ERROR) {
         LOGE("cannot initialize audio device");
         return false;