Add one-stop-shop for built-in AEC toggling in APM

This does not change what AEC functionality is available.
However, a client that only uses this interface - and not the submodule
pointer accessors - gets simpler code, and is guaranteed not to run any
two AECs in tandem.

The submodule interface EchoControlMobile is being deprecated in
https://webrtc-review.googlesource.com/c/src/+/89392

Bug: webrtc:9535
Change-Id: Id9326074e566be6d8768010fc421c457beff402c
Reviewed-on: https://webrtc-review.googlesource.com/89386
Commit-Queue: Sam Zackrisson <saza@webrtc.org>
Reviewed-by: Per Ã…hgren <peah@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24066}
diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc
index 7e5955a..e229b45 100644
--- a/modules/audio_processing/audio_processing_impl.cc
+++ b/modules/audio_processing/audio_processing_impl.cc
@@ -385,8 +385,10 @@
     rtc::CritScope cs_capture(&crit_capture_);
 
     // Mark Echo Controller enabled if a factory is injected.
-    capture_nonlocked_.echo_controller_enabled =
-        static_cast<bool>(echo_control_factory_);
+    if (echo_control_factory_) {
+      config_.echo_cancellation.enabled = true;
+      capture_nonlocked_.echo_controller_enabled = true;
+    }
 
     public_submodules_->echo_cancellation.reset(
         new EchoCancellationImpl(&crit_render_, &crit_capture_));
@@ -491,6 +493,15 @@
 }
 
 int AudioProcessingImpl::InitializeLocked() {
+  // Ensure at most one built-in AEC is active, by arbitrarily preferring AEC2.
+  if (public_submodules_->echo_cancellation->is_enabled()) {
+    echo_control_mobile()->Enable(false);
+    config_.echo_cancellation.enabled = true;
+    config_.echo_cancellation.mobile_mode = false;
+  } else if (public_submodules_->echo_control_mobile->is_enabled()) {
+    config_.echo_cancellation.enabled = true;
+    config_.echo_cancellation.mobile_mode = true;
+  }
   UpdateActiveSubmoduleStates();
 
   const int render_audiobuffer_num_output_frames =
@@ -666,6 +677,13 @@
   rtc::CritScope cs_render(&crit_render_);
   rtc::CritScope cs_capture(&crit_capture_);
 
+  capture_nonlocked_.echo_controller_enabled =
+      config_.echo_cancellation.enabled && private_submodules_->echo_controller;
+  echo_cancellation()->Enable(config_.echo_cancellation.enabled &&
+                              !config_.echo_cancellation.mobile_mode);
+  echo_control_mobile()->Enable(config_.echo_cancellation.enabled &&
+                                config_.echo_cancellation.mobile_mode);
+
   InitializeLowCutFilter();
 
   RTC_LOG(LS_INFO) << "Highpass filter activated: "
@@ -1169,8 +1187,8 @@
   HandleCaptureRuntimeSettings();
 
   // Ensure that not both the AEC and AECM are active at the same time.
-  // TODO(peah): Simplify once the public API Enable functions for these
-  // are moved to APM.
+  // TODO(bugs.webrtc.org/9535): Simplify once the public API Enable functions
+  // for these are moved to APM.
   RTC_DCHECK(!(public_submodules_->echo_cancellation->is_enabled() &&
                public_submodules_->echo_control_mobile->is_enabled()));
 
@@ -1197,7 +1215,7 @@
                                 levels.peak, 1, RmsLevel::kMinLevelDb, 64);
   }
 
-  if (private_submodules_->echo_controller) {
+  if (capture_nonlocked_.echo_controller_enabled) {
     // Detect and flag any change in the analog gain.
     int analog_mic_level = gain_control()->stream_analog_level();
     capture_.echo_path_gain_change =
@@ -1221,7 +1239,7 @@
     capture_buffer->SplitIntoFrequencyBands();
   }
 
-  if (private_submodules_->echo_controller) {
+  if (capture_nonlocked_.echo_controller_enabled) {
     // Force down-mixing of the number of channels after the detection of
     // capture signal saturation.
     // TODO(peah): Look into ensuring that this kind of tampering with the
@@ -1231,7 +1249,7 @@
 
   // TODO(peah): Move the AEC3 low-cut filter to this place.
   if (private_submodules_->low_cut_filter &&
-      !private_submodules_->echo_controller) {
+      !capture_nonlocked_.echo_controller_enabled) {
     private_submodules_->low_cut_filter->Process(capture_buffer);
   }
   RETURN_ON_ERR(
@@ -1241,11 +1259,11 @@
   // Ensure that the stream delay was set before the call to the
   // AEC ProcessCaptureAudio function.
   if (public_submodules_->echo_cancellation->is_enabled() &&
-      !private_submodules_->echo_controller && !was_stream_delay_set()) {
+      !was_stream_delay_set()) {
     return AudioProcessing::kStreamParameterNotSetError;
   }
 
-  if (private_submodules_->echo_controller) {
+  if (capture_nonlocked_.echo_controller_enabled) {
     data_dumper_->DumpRaw("stream_delay", stream_delay_ms());
 
     if (was_stream_delay_set()) {
@@ -1285,8 +1303,7 @@
     return AudioProcessing::kStreamParameterNotSetError;
   }
 
-  if (!(private_submodules_->echo_controller ||
-        public_submodules_->echo_cancellation->is_enabled())) {
+  if (public_submodules_->echo_control_mobile->is_enabled()) {
     RETURN_ON_ERR(public_submodules_->echo_control_mobile->ProcessCaptureAudio(
         capture_buffer, stream_delay_ms()));
   }
@@ -1504,7 +1521,7 @@
   }
 
   // TODO(peah): Perform the queueing ínside QueueRenderAudiuo().
-  if (private_submodules_->echo_controller) {
+  if (capture_nonlocked_.echo_controller_enabled) {
     private_submodules_->echo_controller->AnalyzeRender(render_buffer);
   }
 
@@ -1627,7 +1644,7 @@
     const {
   AudioProcessingStatistics stats;
   EchoCancellation::Metrics metrics;
-  if (private_submodules_->echo_controller) {
+  if (capture_nonlocked_.echo_controller_enabled) {
     rtc::CritScope cs_capture(&crit_capture_);
     auto ec_metrics = private_submodules_->echo_controller->GetMetrics();
     float erl = static_cast<float>(ec_metrics.echo_return_loss);
@@ -1663,7 +1680,7 @@
   AudioProcessingStats stats;
   if (has_remote_tracks) {
     EchoCancellation::Metrics metrics;
-    if (private_submodules_->echo_controller) {
+    if (capture_nonlocked_.echo_controller_enabled) {
       rtc::CritScope cs_capture(&crit_capture_);
       auto ec_metrics = private_submodules_->echo_controller->GetMetrics();
       stats.echo_return_loss = ec_metrics.echo_return_loss;
@@ -1853,8 +1870,8 @@
   static const int kMinDiffDelayMs = 60;
 
   if (echo_cancellation()->is_enabled()) {
-    // Activate delay_jumps_ counters if we know echo_cancellation is running.
-    // If a stream has echo we know that the echo_cancellation is in process.
+    // Activate delay_jumps_ counters if we know AEC2 is running.
+    // If a stream has echo we know that echo cancellation is in process.
     if (capture_.stream_delay_jumps == -1 &&
         echo_cancellation()->stream_has_echo()) {
       capture_.stream_delay_jumps = 0;