diff --git a/sdk/android/native_unittests/audio_device/audio_device_unittest.cc b/sdk/android/native_unittests/audio_device/audio_device_unittest.cc index 4181094e68..5e46052b90 100644 --- a/sdk/android/native_unittests/audio_device/audio_device_unittest.cc +++ b/sdk/android/native_unittests/audio_device/audio_device_unittest.cc @@ -1135,6 +1135,36 @@ TEST_F(AudioDeviceTest, DISABLED_MeasureLoopbackLatency) { latency_audio_stream->PrintResults(); } +TEST(JavaAudioDeviceTest, TestRunningTwoAdmsSimultaneously) { + JNIEnv* jni = AttachCurrentThreadIfNeeded(); + ScopedJavaLocalRef context = + Java_ApplicationContextProvider_getApplicationContextForTest(jni); + + // Create and start the first ADM. + rtc::scoped_refptr adm_1 = + CreateJavaAudioDeviceModule(jni, context.obj()); + EXPECT_EQ(0, adm_1->Init()); + EXPECT_EQ(0, adm_1->InitRecording()); + EXPECT_EQ(0, adm_1->StartRecording()); + + // Create and start a second ADM. Expect this to fail due to the microphone + // already being in use. + rtc::scoped_refptr adm_2 = + CreateJavaAudioDeviceModule(jni, context.obj()); + int32_t err = adm_2->Init(); + err |= adm_2->InitRecording(); + err |= adm_2->StartRecording(); + EXPECT_NE(0, err); + + // Stop and terminate second adm. + adm_2->StopRecording(); + adm_2->Terminate(); + + // Stop first ADM. + EXPECT_EQ(0, adm_1->StopRecording()); + EXPECT_EQ(0, adm_1->Terminate()); +} + } // namespace jni } // namespace webrtc diff --git a/sdk/android/src/jni/audio_device/audio_device_module.cc b/sdk/android/src/jni/audio_device/audio_device_module.cc index 6127ebe316..c44ac91751 100644 --- a/sdk/android/src/jni/audio_device/audio_device_module.cc +++ b/sdk/android/src/jni/audio_device/audio_device_module.cc @@ -241,11 +241,15 @@ class AndroidAudioDeviceModule : public AudioDeviceModule { if (Playing()) { return 0; } - audio_device_buffer_->StartPlayout(); int32_t result = output_->StartPlayout(); RTC_LOG(INFO) << "output: " << result; RTC_HISTOGRAM_BOOLEAN("WebRTC.Audio.StartPlayoutSuccess", static_cast(result == 0)); + if (result == 0) { + // Only start playing the audio device buffer if starting the audio + // output succeeded. + audio_device_buffer_->StartPlayout(); + } return result; } @@ -276,11 +280,15 @@ class AndroidAudioDeviceModule : public AudioDeviceModule { if (Recording()) { return 0; } - audio_device_buffer_->StartRecording(); int32_t result = input_->StartRecording(); RTC_LOG(INFO) << "output: " << result; RTC_HISTOGRAM_BOOLEAN("WebRTC.Audio.StartRecordingSuccess", static_cast(result == 0)); + if (result == 0) { + // Only start recording the audio device buffer if starting the audio + // input succeeded. + audio_device_buffer_->StartRecording(); + } return result; } diff --git a/sdk/android/src/jni/audio_device/audio_record_jni.cc b/sdk/android/src/jni/audio_device/audio_record_jni.cc index 50da3f7688..390cec0e9e 100644 --- a/sdk/android/src/jni/audio_device/audio_record_jni.cc +++ b/sdk/android/src/jni/audio_device/audio_record_jni.cc @@ -102,7 +102,10 @@ int32_t AudioRecordJni::Terminate() { int32_t AudioRecordJni::InitRecording() { RTC_LOG(INFO) << "InitRecording"; RTC_DCHECK(thread_checker_.CalledOnValidThread()); - RTC_DCHECK(!initialized_); + if (initialized_) { + // Already initialized. + return 0; + } RTC_DCHECK(!recording_); ScopedHistogramTimer timer("WebRTC.Audio.InitRecordingDurationMs"); @@ -131,7 +134,10 @@ bool AudioRecordJni::RecordingIsInitialized() const { int32_t AudioRecordJni::StartRecording() { RTC_LOG(INFO) << "StartRecording"; RTC_DCHECK(thread_checker_.CalledOnValidThread()); - RTC_DCHECK(!recording_); + if (recording_) { + // Already recording. + return 0; + } if (!initialized_) { RTC_DLOG(LS_WARNING) << "Recording can not start since InitRecording must succeed first"; diff --git a/sdk/android/src/jni/audio_device/audio_track_jni.cc b/sdk/android/src/jni/audio_device/audio_track_jni.cc index da3cedd4a6..f48673f048 100644 --- a/sdk/android/src/jni/audio_device/audio_track_jni.cc +++ b/sdk/android/src/jni/audio_device/audio_track_jni.cc @@ -76,7 +76,10 @@ int32_t AudioTrackJni::Terminate() { int32_t AudioTrackJni::InitPlayout() { RTC_LOG(INFO) << "InitPlayout"; RTC_DCHECK(thread_checker_.CalledOnValidThread()); - RTC_DCHECK(!initialized_); + if (initialized_) { + // Already initialized. + return 0; + } RTC_DCHECK(!playing_); if (!Java_WebRtcAudioTrack_initPlayout( env_, j_audio_track_, audio_parameters_.sample_rate(), @@ -95,7 +98,10 @@ bool AudioTrackJni::PlayoutIsInitialized() const { int32_t AudioTrackJni::StartPlayout() { RTC_LOG(INFO) << "StartPlayout"; RTC_DCHECK(thread_checker_.CalledOnValidThread()); - RTC_DCHECK(!playing_); + if (playing_) { + // Already playing. + return 0; + } if (!initialized_) { RTC_DLOG(LS_WARNING) << "Playout can not start since InitPlayout must succeed first";