Delays changing to COMMUNICATION mode until streaming starts.
Restores stored audio mode when all streaming stops.

TBR=glaznev
BUG=NONE
TEST=AppRTCDemo

Review URL: https://webrtc-codereview.appspot.com/46869005

Cr-Commit-Position: refs/heads/master@{#8970}
diff --git a/webrtc/modules/audio_device/android/audio_device_template.h b/webrtc/modules/audio_device/android/audio_device_template.h
index c1a7e19..fa37eb2 100644
--- a/webrtc/modules/audio_device/android/audio_device_template.h
+++ b/webrtc/modules/audio_device/android/audio_device_template.h
@@ -118,6 +118,7 @@
   }
 
   int32_t InitPlayout() override {
+    audio_manager_.SetCommunicationMode(true);
     return output_.InitPlayout();
   }
 
@@ -131,6 +132,7 @@
   }
 
   int32_t InitRecording() override {
+    audio_manager_.SetCommunicationMode(true);
     return input_.InitRecording();
   }
 
@@ -143,7 +145,13 @@
   }
 
   int32_t StopPlayout() override {
-    return output_.StopPlayout();
+    int32_t err = output_.StopPlayout();
+    if (!Recording()) {
+      // Restore initial audio mode since all audio streaming is disabled.
+      // The default mode was stored in Init().
+      audio_manager_.SetCommunicationMode(false);
+    }
+    return err;
   }
 
   bool Playing() const override {
@@ -155,7 +163,13 @@
   }
 
   int32_t StopRecording() override {
-    return input_.StopRecording();
+    int32_t err = input_.StopRecording();
+    if (!Playing()) {
+      // Restore initial audio mode since all audio streaming is disabled.
+      // The default mode was is stored in Init().
+      audio_manager_.SetCommunicationMode(false);
+    }
+    return err;
   }
 
   bool Recording() const override {
diff --git a/webrtc/modules/audio_device/android/audio_manager.cc b/webrtc/modules/audio_device/android/audio_manager.cc
index a4f54bc..717d164 100644
--- a/webrtc/modules/audio_device/android/audio_manager.cc
+++ b/webrtc/modules/audio_device/android/audio_manager.cc
@@ -121,6 +121,18 @@
   return true;
 }
 
+void AudioManager::SetCommunicationMode(bool enable) {
+  ALOGD("SetCommunicationMode(%d)%s", enable, GetThreadInfo().c_str());
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(initialized_);
+  AttachThreadScoped ats(g_jvm);
+  JNIEnv* jni = ats.env();
+  jmethodID setcommID = GetMethodID(
+      jni, g_audio_manager_class, "setCommunicationMode", "(Z)V");
+  jni->CallVoidMethod(j_audio_manager_, setcommID, enable);
+  CHECK_EXCEPTION(jni);
+}
+
 void JNICALL AudioManager::CacheAudioParameters(JNIEnv* env, jobject obj,
     jint sample_rate, jint channels, jlong nativeAudioManager) {
   webrtc::AudioManager* this_object =
diff --git a/webrtc/modules/audio_device/android/audio_manager.h b/webrtc/modules/audio_device/android/audio_manager.h
index 5d2c0563..3ab29b7 100644
--- a/webrtc/modules/audio_device/android/audio_manager.h
+++ b/webrtc/modules/audio_device/android/audio_manager.h
@@ -81,14 +81,15 @@
   AudioManager();
   ~AudioManager();
 
-  // Initializes the audio manager (changes mode to MODE_IN_COMMUNICATION,
-  // request audio focus etc.).
-  // It is possible to use this class without calling Init() if the calling
-  // application prefers to set up the audio environment on its own instead.
+  // Initializes the audio manager and stores the current audio mode.
   bool Init();
   // Revert any setting done by Init().
   bool Close();
 
+  // Sets audio mode to AudioManager.MODE_IN_COMMUNICATION if |enable| is true.
+  // Restores audio mode that was stored in Init() if |enable| is false.
+  void SetCommunicationMode(bool enable);
+
   // Native audio parameters stored during construction.
   AudioParameters GetPlayoutAudioParameters() const;
   AudioParameters GetRecordAudioParameters() const;
diff --git a/webrtc/modules/audio_device/android/java/src/org/webrtc/voiceengine/WebRtcAudioManager.java b/webrtc/modules/audio_device/android/java/src/org/webrtc/voiceengine/WebRtcAudioManager.java
index 4472a61..3a0d3a1 100644
--- a/webrtc/modules/audio_device/android/java/src/org/webrtc/voiceengine/WebRtcAudioManager.java
+++ b/webrtc/modules/audio_device/android/java/src/org/webrtc/voiceengine/WebRtcAudioManager.java
@@ -37,6 +37,14 @@
   // TODO(henrika): add stereo support for playout.
   private static final int CHANNELS = 1;
 
+  // List of possible audio modes.
+  private static final String[] AUDIO_MODES = new String[] {
+      "MODE_NORMAL",
+      "MODE_RINGTONE",
+      "MODE_IN_CALL",
+      "MODE_IN_COMMUNICATION",
+    };
+
   private final long nativeAudioManager;
   private final Context context;
   private final AudioManager audioManager;
@@ -68,13 +76,11 @@
       return true;
     }
 
-    // Store current audio state so we can restore it when close() is called.
+    // Store current audio state so we can restore it when close() or
+    // setCommunicationMode(false) is called.
     savedAudioMode = audioManager.getMode();
     savedIsSpeakerPhoneOn = audioManager.isSpeakerphoneOn();
 
-    // Switch to COMMUNICATION mode for best possible VoIP performance.
-    audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
-
     if (DEBUG) {
       Logd("savedAudioMode: " + savedAudioMode);
       Logd("savedIsSpeakerPhoneOn: " + savedIsSpeakerPhoneOn);
@@ -95,6 +101,24 @@
     audioManager.setMode(savedAudioMode);
   }
 
+  private void setCommunicationMode(boolean enable) {
+    Logd("setCommunicationMode(" + enable + ")"
+        + WebRtcAudioUtils.getThreadInfo());
+    assertTrue(initialized);
+    if (enable) {
+      // Avoid switching mode if MODE_IN_COMMUNICATION is already in use.
+      if (audioManager.getMode() == AudioManager.MODE_IN_COMMUNICATION) {
+        return;
+      }
+      // Switch to COMMUNICATION mode for best possible VoIP performance.
+      audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
+    } else {
+      // Restore audio mode that was stored in init().
+      audioManager.setMode(savedAudioMode);
+    }
+    Logd("changing audio mode to: " + AUDIO_MODES[audioManager.getMode()]);
+  }
+
   private void storeAudioParameters() {
     // Only mono is supported currently (in both directions).
     // TODO(henrika): add support for stereo playout.