Propagate field trials into AgcManagerDirect

Bug: webrtc:369904700
Change-Id: I8389627f46494f825bcdcb59022ddfa992f74639
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/372381
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Reviewed-by: Sam Zackrisson <saza@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#43722}
diff --git a/modules/audio_processing/agc/BUILD.gn b/modules/audio_processing/agc/BUILD.gn
index f5bb272..754b807 100644
--- a/modules/audio_processing/agc/BUILD.gn
+++ b/modules/audio_processing/agc/BUILD.gn
@@ -25,7 +25,9 @@
     "..:audio_buffer",
     "..:audio_frame_view",
     "../../../api:array_view",
+    "../../../api:field_trials_view",
     "../../../api/audio:audio_processing",
+    "../../../api/environment",
     "../../../common_audio",
     "../../../common_audio:common_audio_c",
     "../../../rtc_base:checks",
@@ -106,13 +108,15 @@
       ":level_estimation",
       "..:mocks",
       "../../../api:array_view",
+      "../../../api:field_trials",
+      "../../../api/environment",
+      "../../../api/environment:environment_factory",
       "../../../rtc_base:checks",
       "../../../rtc_base:random",
       "../../../rtc_base:safe_conversions",
       "../../../rtc_base:safe_minmax",
       "../../../rtc_base:stringutils",
       "../../../system_wrappers:metrics",
-      "../../../test:field_trial",
       "../../../test:fileutils",
       "../../../test:test_support",
       "//testing/gtest",
diff --git a/modules/audio_processing/agc/agc_manager_direct.cc b/modules/audio_processing/agc/agc_manager_direct.cc
index 763dd9a..0f2469d 100644
--- a/modules/audio_processing/agc/agc_manager_direct.cc
+++ b/modules/audio_processing/agc/agc_manager_direct.cc
@@ -14,6 +14,8 @@
 #include <cmath>
 
 #include "api/array_view.h"
+#include "api/environment/environment.h"
+#include "api/field_trials_view.h"
 #include "common_audio/include/audio_util.h"
 #include "modules/audio_processing/agc/gain_control.h"
 #include "modules/audio_processing/agc2/gain_map_internal.h"
@@ -22,7 +24,6 @@
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/numerics/safe_minmax.h"
-#include "system_wrappers/include/field_trial.h"
 #include "system_wrappers/include/metrics.h"
 
 namespace webrtc {
@@ -69,14 +70,13 @@
 // string. Returns an unspecified value if the field trial is not specified, if
 // disabled or if it cannot be parsed. Example:
 // 'WebRTC-Audio-2ndAgcMinMicLevelExperiment/Enabled-80' => returns 80.
-std::optional<int> GetMinMicLevelOverride() {
+std::optional<int> GetMinMicLevelOverride(const FieldTrialsView& field_trials) {
   constexpr char kMinMicLevelFieldTrial[] =
       "WebRTC-Audio-2ndAgcMinMicLevelExperiment";
-  if (!webrtc::field_trial::IsEnabled(kMinMicLevelFieldTrial)) {
+  if (!field_trials.IsEnabled(kMinMicLevelFieldTrial)) {
     return std::nullopt;
   }
-  const auto field_trial_string =
-      webrtc::field_trial::FindFullName(kMinMicLevelFieldTrial);
+  const auto field_trial_string = field_trials.Lookup(kMinMicLevelFieldTrial);
   int min_mic_level = -1;
   sscanf(field_trial_string.c_str(), "Enabled-%d", &min_mic_level);
   if (min_mic_level >= 0 && min_mic_level <= 255) {
@@ -447,19 +447,21 @@
 std::atomic<int> AgcManagerDirect::instance_counter_(0);
 
 AgcManagerDirect::AgcManagerDirect(
+    const Environment& env,
     const AudioProcessing::Config::GainController1::AnalogGainController&
         analog_config,
     Agc* agc)
-    : AgcManagerDirect(/*num_capture_channels=*/1, analog_config) {
+    : AgcManagerDirect(env, /*num_capture_channels=*/1, analog_config) {
   RTC_DCHECK(channel_agcs_[0]);
   RTC_DCHECK(agc);
   channel_agcs_[0]->set_agc(agc);
 }
 
-AgcManagerDirect::AgcManagerDirect(int num_capture_channels,
+AgcManagerDirect::AgcManagerDirect(const Environment& env,
+                                   int num_capture_channels,
                                    const AnalogAgcConfig& analog_config)
     : analog_controller_enabled_(analog_config.enabled),
-      min_mic_level_override_(GetMinMicLevelOverride()),
+      min_mic_level_override_(GetMinMicLevelOverride(env.field_trials())),
       data_dumper_(new ApmDataDumper(instance_counter_.fetch_add(1) + 1)),
       num_capture_channels_(num_capture_channels),
       disable_digital_adaptive_(!analog_config.enable_digital_adaptive),
diff --git a/modules/audio_processing/agc/agc_manager_direct.h b/modules/audio_processing/agc/agc_manager_direct.h
index db2d27b..78dfa87 100644
--- a/modules/audio_processing/agc/agc_manager_direct.h
+++ b/modules/audio_processing/agc/agc_manager_direct.h
@@ -17,6 +17,7 @@
 
 #include "api/array_view.h"
 #include "api/audio/audio_processing.h"
+#include "api/environment/environment.h"
 #include "modules/audio_processing/agc/agc.h"
 #include "modules/audio_processing/agc2/clipping_predictor.h"
 #include "modules/audio_processing/audio_buffer.h"
@@ -42,6 +43,7 @@
   // passed to `AnalyzePreProcess()` and `Process()`. Clamps
   // `analog_config.startup_min_level` in the [12, 255] range.
   AgcManagerDirect(
+      const Environment& env,
       int num_capture_channels,
       const AudioProcessing::Config::GainController1::AnalogGainController&
           analog_config);
@@ -142,6 +144,7 @@
   // Ctor that creates a single channel AGC and by injecting `agc`.
   // `agc` will be owned by this class; hence, do not delete it.
   AgcManagerDirect(
+      const Environment& env,
       const AudioProcessing::Config::GainController1::AnalogGainController&
           analog_config,
       Agc* agc);
diff --git a/modules/audio_processing/agc/agc_manager_direct_unittest.cc b/modules/audio_processing/agc/agc_manager_direct_unittest.cc
index 3b6ae72..d5b87bd 100644
--- a/modules/audio_processing/agc/agc_manager_direct_unittest.cc
+++ b/modules/audio_processing/agc/agc_manager_direct_unittest.cc
@@ -15,12 +15,14 @@
 #include <tuple>
 #include <vector>
 
+#include "api/environment/environment.h"
+#include "api/environment/environment_factory.h"
+#include "api/field_trials.h"
 #include "modules/audio_processing/agc/gain_control.h"
 #include "modules/audio_processing/agc/mock_agc.h"
 #include "modules/audio_processing/include/mock_audio_processing.h"
 #include "rtc_base/numerics/safe_minmax.h"
 #include "rtc_base/strings/string_builder.h"
-#include "test/field_trial.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
 #include "test/testsupport/file_utils.h"
@@ -78,24 +80,32 @@
   MOCK_METHOD(bool, stream_is_saturated, (), (const, override));
 };
 
-// TODO(bugs.webrtc.org/12874): Remove and use designated initializers once
-// fixed.
+// Construction parameters that tests may explicitely specify.
+struct AgcManagerDirectTestParams {
+  std::string field_trials;
+  int clipped_level_min = kClippedMin;
+  bool enable_digital_adaptive = false;
+  int clipped_level_step = kClippedLevelStep;
+  float clipped_ratio_threshold = kClippedRatioThreshold;
+  int clipped_wait_frames = kClippedWaitFrames;
+  AnalogAgcConfig::ClippingPredictor clipping_predictor;
+};
+
 std::unique_ptr<AgcManagerDirect> CreateAgcManagerDirect(
-    int startup_min_volume,
-    int clipped_level_step,
-    float clipped_ratio_threshold,
-    int clipped_wait_frames,
-    const ClippingPredictorConfig& clipping_predictor_config =
-        kDefaultAnalogConfig.clipping_predictor) {
-  AnalogAgcConfig config;
-  config.startup_min_volume = startup_min_volume;
-  config.clipped_level_min = kClippedMin;
-  config.enable_digital_adaptive = false;
-  config.clipped_level_step = clipped_level_step;
-  config.clipped_ratio_threshold = clipped_ratio_threshold;
-  config.clipped_wait_frames = clipped_wait_frames;
-  config.clipping_predictor = clipping_predictor_config;
-  return std::make_unique<AgcManagerDirect>(/*num_capture_channels=*/1, config);
+    AgcManagerDirectTestParams p = {}) {
+  auto manager = std::make_unique<AgcManagerDirect>(
+      CreateEnvironment(FieldTrials::CreateNoGlobal(p.field_trials)),
+      kNumChannels,
+      AnalogAgcConfig{.startup_min_volume = kInitialInputVolume,
+                      .clipped_level_min = p.clipped_level_min,
+                      .enable_digital_adaptive = p.enable_digital_adaptive,
+                      .clipped_level_step = p.clipped_level_step,
+                      .clipped_ratio_threshold = p.clipped_ratio_threshold,
+                      .clipped_wait_frames = p.clipped_wait_frames,
+                      .clipping_predictor = p.clipping_predictor});
+  manager->Initialize();
+  manager->set_stream_analog_level(kInitialInputVolume);
+  return manager;
 }
 
 // Deprecated.
@@ -329,7 +339,7 @@
 class AgcManagerDirectTestHelper {
  public:
   // Ctor. Initializes `audio_buffer` with zeros.
-  AgcManagerDirectTestHelper()
+  explicit AgcManagerDirectTestHelper(const Environment& env)
       : audio_buffer(kSampleRateHz,
                      kNumChannels,
                      kSampleRateHz,
@@ -337,7 +347,7 @@
                      kSampleRateHz,
                      kNumChannels),
         mock_agc(new ::testing::NiceMock<MockAgc>()),
-        manager(GetAnalogAgcTestConfig(), mock_agc) {
+        manager(env, GetAnalogAgcTestConfig(), mock_agc) {
     manager.Initialize();
     manager.SetupDigitalGainControl(mock_gain_control);
     WriteAudioBufferSamples(/*samples_value=*/0.0f, /*clipped_ratio=*/0.0f,
@@ -438,8 +448,8 @@
     : public ::testing::TestWithParam<std::tuple<std::optional<int>, bool>> {
  protected:
   AgcManagerDirectParametrizedTest()
-      : field_trials_(
-            GetAgcMinMicLevelExperimentFieldTrial(std::get<0>(GetParam()))) {}
+      : env_(CreateEnvironment(FieldTrials::CreateNoGlobal(
+            GetAgcMinMicLevelExperimentFieldTrial(std::get<0>(GetParam()))))) {}
 
   bool IsMinMicLevelOverridden() const {
     return std::get<0>(GetParam()).has_value();
@@ -453,8 +463,7 @@
     return IsRmsErrorOverridden() ? std::optional<float>(value) : std::nullopt;
   }
 
- private:
-  test::ScopedFieldTrials field_trials_;
+  const Environment env_;
 };
 
 INSTANTIATE_TEST_SUITE_P(
@@ -469,10 +478,10 @@
 // differs.
 TEST_P(AgcManagerDirectParametrizedTest,
        DisabledAnalogAgcDoesNotAdaptDownwards) {
-  AgcManagerDirect manager_no_analog_agc(kNumChannels,
+  AgcManagerDirect manager_no_analog_agc(env_, kNumChannels,
                                          GetDisabledAnalogAgcConfig());
   manager_no_analog_agc.Initialize();
-  AgcManagerDirect manager_with_analog_agc(kNumChannels,
+  AgcManagerDirect manager_with_analog_agc(env_, kNumChannels,
                                            GetAnalogAgcTestConfig());
   manager_with_analog_agc.Initialize();
 
@@ -523,10 +532,10 @@
 // frames to APM config. The test passes but internally the gain update timing
 // differs.
 TEST_P(AgcManagerDirectParametrizedTest, DisabledAnalogAgcDoesNotAdaptUpwards) {
-  AgcManagerDirect manager_no_analog_agc(kNumChannels,
+  AgcManagerDirect manager_no_analog_agc(env_, kNumChannels,
                                          GetDisabledAnalogAgcConfig());
   manager_no_analog_agc.Initialize();
-  AgcManagerDirect manager_with_analog_agc(kNumChannels,
+  AgcManagerDirect manager_with_analog_agc(env_, kNumChannels,
                                            GetAnalogAgcTestConfig());
   manager_with_analog_agc.Initialize();
 
@@ -552,7 +561,7 @@
 
 TEST_P(AgcManagerDirectParametrizedTest,
        StartupMinVolumeConfigurationIsRespected) {
-  AgcManagerDirectTestHelper helper;
+  AgcManagerDirectTestHelper helper(env_);
   helper.CallAgcSequence(kInitialInputVolume,
                          GetOverrideOrEmpty(kHighSpeechProbability),
                          GetOverrideOrEmpty(kSpeechLevelDbfs));
@@ -563,7 +572,7 @@
   const auto speech_probability_override =
       GetOverrideOrEmpty(kHighSpeechProbability);
 
-  AgcManagerDirectTestHelper helper;
+  AgcManagerDirectTestHelper helper(env_);
   helper.CallAgcSequence(kInitialInputVolume, speech_probability_override,
                          GetOverrideOrEmpty(kSpeechLevelDbfs));
 
@@ -626,7 +635,7 @@
   const auto speech_probability_override =
       GetOverrideOrEmpty(kHighSpeechProbability);
 
-  AgcManagerDirectTestHelper helper;
+  AgcManagerDirectTestHelper helper(env_);
   helper.CallAgcSequence(kInitialInputVolume, speech_probability_override,
                          GetOverrideOrEmpty(kSpeechLevelDbfs));
 
@@ -708,7 +717,7 @@
   const auto speech_probability_override =
       GetOverrideOrEmpty(kHighSpeechProbability);
 
-  AgcManagerDirectTestHelper helper;
+  AgcManagerDirectTestHelper helper(env_);
   helper.CallAgcSequence(kInitialInputVolume, speech_probability_override,
                          GetOverrideOrEmpty(kSpeechLevelDbfs));
 
@@ -780,7 +789,7 @@
   const auto speech_probability_override =
       GetOverrideOrEmpty(kHighSpeechProbability);
 
-  AgcManagerDirectTestHelper helper;
+  AgcManagerDirectTestHelper helper(env_);
   helper.CallAgcSequence(kInitialInputVolume, speech_probability_override,
                          GetOverrideOrEmpty(kSpeechLevelDbfs));
 
@@ -825,7 +834,7 @@
   const auto speech_probability_override =
       GetOverrideOrEmpty(kHighSpeechProbability);
 
-  AgcManagerDirectTestHelper helper;
+  AgcManagerDirectTestHelper helper(env_);
   helper.CallAgcSequence(kInitialInputVolume, speech_probability_override,
                          GetOverrideOrEmpty(kSpeechLevelDbfs));
 
@@ -862,7 +871,7 @@
   const auto speech_probability_override =
       GetOverrideOrEmpty(kHighSpeechProbability);
 
-  AgcManagerDirectTestHelper helper;
+  AgcManagerDirectTestHelper helper(env_);
   helper.CallAgcSequence(kInitialInputVolume, speech_probability_override,
                          GetOverrideOrEmpty(kSpeechLevelDbfs));
 
@@ -895,7 +904,7 @@
 }
 
 TEST_P(AgcManagerDirectParametrizedTest, NoActionWhileMuted) {
-  AgcManagerDirectTestHelper helper;
+  AgcManagerDirectTestHelper helper(env_);
   helper.CallAgcSequence(kInitialInputVolume,
                          GetOverrideOrEmpty(kHighSpeechProbability),
                          GetOverrideOrEmpty(kSpeechLevelDbfs));
@@ -913,7 +922,7 @@
 }
 
 TEST_P(AgcManagerDirectParametrizedTest, UnmutingChecksVolumeWithoutRaising) {
-  AgcManagerDirectTestHelper helper;
+  AgcManagerDirectTestHelper helper(env_);
   helper.CallAgcSequence(kInitialInputVolume,
                          GetOverrideOrEmpty(kHighSpeechProbability),
                          GetOverrideOrEmpty(kSpeechLevelDbfs));
@@ -934,7 +943,7 @@
 }
 
 TEST_P(AgcManagerDirectParametrizedTest, UnmutingRaisesTooLowVolume) {
-  AgcManagerDirectTestHelper helper;
+  AgcManagerDirectTestHelper helper(env_);
   helper.CallAgcSequence(kInitialInputVolume,
                          GetOverrideOrEmpty(kHighSpeechProbability),
                          GetOverrideOrEmpty(kSpeechLevelDbfs));
@@ -958,7 +967,7 @@
   const auto speech_probability_override =
       GetOverrideOrEmpty(kHighSpeechProbability);
 
-  AgcManagerDirectTestHelper helper;
+  AgcManagerDirectTestHelper helper(env_);
   helper.CallAgcSequence(kInitialInputVolume, speech_probability_override,
                          GetOverrideOrEmpty(kSpeechLevelDbfs));
 
@@ -1000,7 +1009,7 @@
   const auto speech_probability_override =
       GetOverrideOrEmpty(kHighSpeechProbability);
 
-  AgcManagerDirectTestHelper helper;
+  AgcManagerDirectTestHelper helper(env_);
   helper.CallAgcSequence(kInitialInputVolume, speech_probability_override,
                          GetOverrideOrEmpty(kSpeechLevelDbfs));
 
@@ -1048,7 +1057,7 @@
   const auto speech_probability_override =
       GetOverrideOrEmpty(kHighSpeechProbability);
 
-  AgcManagerDirectTestHelper helper;
+  AgcManagerDirectTestHelper helper(env_);
   helper.CallAgcSequence(kInitialInputVolume, speech_probability_override,
                          GetOverrideOrEmpty(kSpeechLevelDbfs));
 
@@ -1094,7 +1103,7 @@
   const auto speech_probability_override =
       GetOverrideOrEmpty(kHighSpeechProbability);
 
-  AgcManagerDirectTestHelper helper;
+  AgcManagerDirectTestHelper helper(env_);
   helper.CallAgcSequence(kInitialInputVolume, speech_probability_override,
                          GetOverrideOrEmpty(kSpeechLevelDbfs));
 
@@ -1110,7 +1119,7 @@
 }
 
 TEST_P(AgcManagerDirectParametrizedTest, NoClippingHasNoImpact) {
-  AgcManagerDirectTestHelper helper;
+  AgcManagerDirectTestHelper helper(env_);
   helper.CallAgcSequence(kInitialInputVolume,
                          GetOverrideOrEmpty(kHighSpeechProbability),
                          GetOverrideOrEmpty(kSpeechLevelDbfs));
@@ -1120,7 +1129,7 @@
 }
 
 TEST_P(AgcManagerDirectParametrizedTest, ClippingUnderThresholdHasNoImpact) {
-  AgcManagerDirectTestHelper helper;
+  AgcManagerDirectTestHelper helper(env_);
   helper.CallAgcSequence(kInitialInputVolume,
                          GetOverrideOrEmpty(kHighSpeechProbability),
                          GetOverrideOrEmpty(kSpeechLevelDbfs));
@@ -1130,7 +1139,7 @@
 }
 
 TEST_P(AgcManagerDirectParametrizedTest, ClippingLowersVolume) {
-  AgcManagerDirectTestHelper helper;
+  AgcManagerDirectTestHelper helper(env_);
   helper.CallAgcSequence(/*applied_input_volume=*/255,
                          GetOverrideOrEmpty(kHighSpeechProbability),
                          GetOverrideOrEmpty(kSpeechLevelDbfs));
@@ -1141,7 +1150,7 @@
 }
 
 TEST_P(AgcManagerDirectParametrizedTest, WaitingPeriodBetweenClippingChecks) {
-  AgcManagerDirectTestHelper helper;
+  AgcManagerDirectTestHelper helper(env_);
   helper.CallAgcSequence(/*applied_input_volume=*/255,
                          GetOverrideOrEmpty(kHighSpeechProbability),
                          GetOverrideOrEmpty(kSpeechLevelDbfs));
@@ -1161,7 +1170,7 @@
 }
 
 TEST_P(AgcManagerDirectParametrizedTest, ClippingLoweringIsLimited) {
-  AgcManagerDirectTestHelper helper;
+  AgcManagerDirectTestHelper helper(env_);
   helper.CallAgcSequence(/*applied_input_volume=*/180,
                          GetOverrideOrEmpty(kHighSpeechProbability),
                          GetOverrideOrEmpty(kSpeechLevelDbfs));
@@ -1181,7 +1190,7 @@
   const auto speech_probability_override =
       GetOverrideOrEmpty(kHighSpeechProbability);
 
-  AgcManagerDirectTestHelper helper;
+  AgcManagerDirectTestHelper helper(env_);
   helper.CallAgcSequence(/*applied_input_volume=*/255,
                          speech_probability_override,
                          GetOverrideOrEmpty(kSpeechLevelDbfs));
@@ -1202,7 +1211,7 @@
   const auto speech_probability_override =
       GetOverrideOrEmpty(kHighSpeechProbability);
 
-  AgcManagerDirectTestHelper helper;
+  AgcManagerDirectTestHelper helper(env_);
   helper.CallAgcSequence(/*applied_input_volume=*/200,
                          speech_probability_override,
                          GetOverrideOrEmpty(kSpeechLevelDbfs));
@@ -1227,7 +1236,7 @@
   const auto speech_probability_override =
       GetOverrideOrEmpty(kHighSpeechProbability);
 
-  AgcManagerDirectTestHelper helper;
+  AgcManagerDirectTestHelper helper(env_);
   helper.CallAgcSequence(/*applied_input_volume=*/210,
                          speech_probability_override,
                          GetOverrideOrEmpty(kSpeechLevelDbfs));
@@ -1324,7 +1333,7 @@
   const auto speech_probability_override =
       GetOverrideOrEmpty(kHighSpeechProbability);
 
-  AgcManagerDirectTestHelper helper;
+  AgcManagerDirectTestHelper helper(env_);
   helper.CallAgcSequence(/*applied_input_volume=*/225,
                          speech_probability_override,
                          GetOverrideOrEmpty(kSpeechLevelDbfs));
@@ -1364,7 +1373,7 @@
 }
 
 TEST_P(AgcManagerDirectParametrizedTest, ClippingDoesNotPullLowVolumeBackUp) {
-  AgcManagerDirectTestHelper helper;
+  AgcManagerDirectTestHelper helper(env_);
   helper.CallAgcSequence(/*applied_input_volume=*/80,
                          GetOverrideOrEmpty(kHighSpeechProbability),
                          GetOverrideOrEmpty(kSpeechLevelDbfs));
@@ -1376,7 +1385,7 @@
 }
 
 TEST_P(AgcManagerDirectParametrizedTest, TakesNoActionOnZeroMicVolume) {
-  AgcManagerDirectTestHelper helper;
+  AgcManagerDirectTestHelper helper(env_);
   helper.CallAgcSequence(kInitialInputVolume,
                          GetOverrideOrEmpty(kHighSpeechProbability),
                          GetOverrideOrEmpty(kSpeechLevelDbfs));
@@ -1391,7 +1400,7 @@
 }
 
 TEST_P(AgcManagerDirectParametrizedTest, ClippingDetectionLowersVolume) {
-  AgcManagerDirectTestHelper helper;
+  AgcManagerDirectTestHelper helper(env_);
   helper.CallAgcSequence(/*applied_input_volume=*/255,
                          GetOverrideOrEmpty(kHighSpeechProbability),
                          GetOverrideOrEmpty(kSpeechLevelDbfs));
@@ -1405,7 +1414,7 @@
 
 TEST_P(AgcManagerDirectParametrizedTest,
        DisabledClippingPredictorDoesNotLowerVolume) {
-  AgcManagerDirectTestHelper helper;
+  AgcManagerDirectTestHelper helper(env_);
   helper.CallAgcSequence(/*applied_input_volume=*/255,
                          GetOverrideOrEmpty(kHighSpeechProbability),
                          GetOverrideOrEmpty(kSpeechLevelDbfs));
@@ -1432,25 +1441,21 @@
 
   AnalogAgcConfig config;
   config.enable_digital_adaptive = false;
-  auto manager = std::make_unique<AgcManagerDirect>(kNumChannels, config);
+  auto manager = std::make_unique<AgcManagerDirect>(env_, kNumChannels, config);
   manager->Initialize();
   manager->SetupDigitalGainControl(mock_gain_control);
 }
 
 TEST(AgcManagerDirectTest, AgcMinMicLevelExperimentDefault) {
-  std::unique_ptr<AgcManagerDirect> manager =
-      CreateAgcManagerDirect(kInitialInputVolume, kClippedLevelStep,
-                             kClippedRatioThreshold, kClippedWaitFrames);
+  std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect();
   EXPECT_EQ(manager->channel_agcs_[0]->min_mic_level(), kMinMicLevel);
 }
 
 TEST(AgcManagerDirectTest, AgcMinMicLevelExperimentDisabled) {
   for (const std::string& field_trial_suffix : {"", "_20220210"}) {
-    test::ScopedFieldTrials field_trial(
-        GetAgcMinMicLevelExperimentFieldTrial("Disabled" + field_trial_suffix));
-    std::unique_ptr<AgcManagerDirect> manager =
-        CreateAgcManagerDirect(kInitialInputVolume, kClippedLevelStep,
-                               kClippedRatioThreshold, kClippedWaitFrames);
+    std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect(
+        {.field_trials = GetAgcMinMicLevelExperimentFieldTrial(
+             "Disabled" + field_trial_suffix)});
     EXPECT_EQ(manager->channel_agcs_[0]->min_mic_level(), kMinMicLevel);
   }
 }
@@ -1458,22 +1463,16 @@
 // Checks that a field-trial parameter outside of the valid range [0,255] is
 // ignored.
 TEST(AgcManagerDirectTest, AgcMinMicLevelExperimentOutOfRangeAbove) {
-  test::ScopedFieldTrials field_trial(
-      GetAgcMinMicLevelExperimentFieldTrial("Enabled-256"));
-  std::unique_ptr<AgcManagerDirect> manager =
-      CreateAgcManagerDirect(kInitialInputVolume, kClippedLevelStep,
-                             kClippedRatioThreshold, kClippedWaitFrames);
+  std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect(
+      {.field_trials = GetAgcMinMicLevelExperimentFieldTrial("Enabled-256")});
   EXPECT_EQ(manager->channel_agcs_[0]->min_mic_level(), kMinMicLevel);
 }
 
 // Checks that a field-trial parameter outside of the valid range [0,255] is
 // ignored.
 TEST(AgcManagerDirectTest, AgcMinMicLevelExperimentOutOfRangeBelow) {
-  test::ScopedFieldTrials field_trial(
-      GetAgcMinMicLevelExperimentFieldTrial("Enabled--1"));
-  std::unique_ptr<AgcManagerDirect> manager =
-      CreateAgcManagerDirect(kInitialInputVolume, kClippedLevelStep,
-                             kClippedRatioThreshold, kClippedWaitFrames);
+  std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect(
+      {.field_trials = GetAgcMinMicLevelExperimentFieldTrial("Enabled--1")});
   EXPECT_EQ(manager->channel_agcs_[0]->min_mic_level(), kMinMicLevel);
 }
 
@@ -1484,12 +1483,11 @@
   constexpr int kMinMicLevelOverride = 50;
   for (const std::string& field_trial_suffix : {"", "_20220210"}) {
     SCOPED_TRACE(field_trial_suffix);
-    test::ScopedFieldTrials field_trial(
-        GetAgcMinMicLevelExperimentFieldTrialEnabled(kMinMicLevelOverride,
-                                                     field_trial_suffix));
-    std::unique_ptr<AgcManagerDirect> manager =
-        CreateAgcManagerDirect(kInitialInputVolume, kClippedLevelStep,
-                               kClippedRatioThreshold, kClippedWaitFrames);
+
+    std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect(
+        {.field_trials = GetAgcMinMicLevelExperimentFieldTrialEnabled(
+             kMinMicLevelOverride, field_trial_suffix)});
+
     EXPECT_EQ(manager->channel_agcs_[0]->min_mic_level(), kMinMicLevelOverride);
   }
 }
@@ -1502,21 +1500,11 @@
 
   // Create and initialize two AGCs by specifying and leaving unspecified the
   // relevant field trial.
-  const auto factory = []() {
-    std::unique_ptr<AgcManagerDirect> manager =
-        CreateAgcManagerDirect(kInitialInputVolume, kClippedLevelStep,
-                               kClippedRatioThreshold, kClippedWaitFrames);
-    manager->Initialize();
-    manager->set_stream_analog_level(kInitialInputVolume);
-    return manager;
-  };
-  std::unique_ptr<AgcManagerDirect> manager = factory();
-  std::unique_ptr<AgcManagerDirect> manager_with_override;
-  {
-    test::ScopedFieldTrials field_trial(
-        GetAgcMinMicLevelExperimentFieldTrialEnabled(kMinMicLevelOverride));
-    manager_with_override = factory();
-  }
+  std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect();
+  std::unique_ptr<AgcManagerDirect> manager_with_override =
+      CreateAgcManagerDirect(
+          {.field_trials = GetAgcMinMicLevelExperimentFieldTrialEnabled(
+               kMinMicLevelOverride)});
 
   // Create a test input signal which containts 80% of clipped samples.
   AudioBuffer audio_buffer(kSampleRateHz, 1, kSampleRateHz, 1, kSampleRateHz,
@@ -1559,21 +1547,11 @@
 
   // Create and initialize two AGCs by specifying and leaving unspecified the
   // relevant field trial.
-  const auto factory = []() {
-    std::unique_ptr<AgcManagerDirect> manager =
-        CreateAgcManagerDirect(kInitialInputVolume, kClippedLevelStep,
-                               kClippedRatioThreshold, kClippedWaitFrames);
-    manager->Initialize();
-    manager->set_stream_analog_level(kInitialInputVolume);
-    return manager;
-  };
-  std::unique_ptr<AgcManagerDirect> manager = factory();
-  std::unique_ptr<AgcManagerDirect> manager_with_override;
-  {
-    test::ScopedFieldTrials field_trial(
-        GetAgcMinMicLevelExperimentFieldTrialEnabled(kMinMicLevelOverride));
-    manager_with_override = factory();
-  }
+  std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect();
+  std::unique_ptr<AgcManagerDirect> manager_with_override =
+      CreateAgcManagerDirect(
+          {.field_trials = GetAgcMinMicLevelExperimentFieldTrialEnabled(
+               kMinMicLevelOverride)});
 
   // Create a test input signal which containts 80% of clipped samples.
   AudioBuffer audio_buffer(kSampleRateHz, 1, kSampleRateHz, 1, kSampleRateHz,
@@ -1614,32 +1592,25 @@
      AgcMinMicLevelExperimentCompareMicLevelWithClipping) {
   // Create and initialize two AGCs by specifying and leaving unspecified the
   // relevant field trial.
-  const auto factory = []() {
-    // Use a large clipped level step to more quickly decrease the analog gain
-    // with clipping.
-    AnalogAgcConfig config = kDefaultAnalogConfig;
-    config.startup_min_volume = kInitialInputVolume;
-    config.enable_digital_adaptive = false;
-    config.clipped_level_step = 64;
-    config.clipped_ratio_threshold = kClippedRatioThreshold;
-    config.clipped_wait_frames = kClippedWaitFrames;
-    auto controller =
-        std::make_unique<AgcManagerDirect>(/*num_capture_channels=*/1, config);
-    controller->Initialize();
-    controller->set_stream_analog_level(kInitialInputVolume);
-    return controller;
-  };
-  std::unique_ptr<AgcManagerDirect> manager = factory();
-  std::unique_ptr<AgcManagerDirect> manager_with_override;
-  {
-    constexpr int kMinMicLevelOverride = 20;
-    static_assert(
-        kDefaultAnalogConfig.clipped_level_min >= kMinMicLevelOverride,
-        "Use a lower override value.");
-    test::ScopedFieldTrials field_trial(
-        GetAgcMinMicLevelExperimentFieldTrialEnabled(kMinMicLevelOverride));
-    manager_with_override = factory();
-  }
+  // Use a large clipped level step to more quickly decrease the analog gain
+  // with clipping.
+  std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect({
+      .clipped_level_min = kDefaultAnalogConfig.clipped_level_min,
+      .enable_digital_adaptive = false,
+      .clipped_level_step = 64,
+  });
+
+  constexpr int kMinMicLevelOverride = 20;
+  static_assert(kDefaultAnalogConfig.clipped_level_min >= kMinMicLevelOverride,
+                "Use a lower override value.");
+  std::unique_ptr<AgcManagerDirect> manager_with_override =
+      CreateAgcManagerDirect({
+          .field_trials = GetAgcMinMicLevelExperimentFieldTrialEnabled(
+              kMinMicLevelOverride),
+          .clipped_level_min = kDefaultAnalogConfig.clipped_level_min,
+          .enable_digital_adaptive = false,
+          .clipped_level_step = 64,
+      });
 
   // Create a test input signal which containts 80% of clipped samples.
   AudioBuffer audio_buffer(kSampleRateHz, 1, kSampleRateHz, 1, kSampleRateHz,
@@ -1681,32 +1652,23 @@
      AgcMinMicLevelExperimentCompareMicLevelWithClippingWithRmsErrorOverride) {
   // Create and initialize two AGCs by specifying and leaving unspecified the
   // relevant field trial.
-  const auto factory = []() {
-    // Use a large clipped level step to more quickly decrease the analog gain
-    // with clipping.
-    AnalogAgcConfig config = kDefaultAnalogConfig;
-    config.startup_min_volume = kInitialInputVolume;
-    config.enable_digital_adaptive = false;
-    config.clipped_level_step = 64;
-    config.clipped_ratio_threshold = kClippedRatioThreshold;
-    config.clipped_wait_frames = kClippedWaitFrames;
-    auto controller =
-        std::make_unique<AgcManagerDirect>(/*num_capture_channels=*/1, config);
-    controller->Initialize();
-    controller->set_stream_analog_level(kInitialInputVolume);
-    return controller;
-  };
-  std::unique_ptr<AgcManagerDirect> manager = factory();
-  std::unique_ptr<AgcManagerDirect> manager_with_override;
-  {
-    constexpr int kMinMicLevelOverride = 20;
-    static_assert(
-        kDefaultAnalogConfig.clipped_level_min >= kMinMicLevelOverride,
-        "Use a lower override value.");
-    test::ScopedFieldTrials field_trial(
-        GetAgcMinMicLevelExperimentFieldTrialEnabled(kMinMicLevelOverride));
-    manager_with_override = factory();
-  }
+  std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect({
+      .clipped_level_min = kDefaultAnalogConfig.clipped_level_min,
+      .enable_digital_adaptive = false,
+      .clipped_level_step = 64,
+  });
+
+  constexpr int kMinMicLevelOverride = 20;
+  static_assert(kDefaultAnalogConfig.clipped_level_min >= kMinMicLevelOverride,
+                "Use a lower override value.");
+  std::unique_ptr<AgcManagerDirect> manager_with_override =
+      CreateAgcManagerDirect({
+          .field_trials = GetAgcMinMicLevelExperimentFieldTrialEnabled(
+              kMinMicLevelOverride),
+          .clipped_level_min = kDefaultAnalogConfig.clipped_level_min,
+          .enable_digital_adaptive = false,
+          .clipped_level_step = 64,
+      });
 
   // Create a test input signal which containts 80% of clipped samples.
   AudioBuffer audio_buffer(kSampleRateHz, 1, kSampleRateHz, 1, kSampleRateHz,
@@ -1746,19 +1708,15 @@
     GTEST_SKIP() << "Skipped. RMS error override does not affect the test.";
   }
 
-  std::unique_ptr<AgcManagerDirect> manager =
-      CreateAgcManagerDirect(kInitialInputVolume, kClippedLevelStep,
-                             kClippedRatioThreshold, kClippedWaitFrames);
-  manager->Initialize();
+  std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect();
   EXPECT_EQ(manager->clipped_level_step_, kClippedLevelStep);
   EXPECT_EQ(manager->clipped_ratio_threshold_, kClippedRatioThreshold);
   EXPECT_EQ(manager->clipped_wait_frames_, kClippedWaitFrames);
+
   std::unique_ptr<AgcManagerDirect> manager_custom =
-      CreateAgcManagerDirect(kInitialInputVolume,
-                             /*clipped_level_step=*/10,
-                             /*clipped_ratio_threshold=*/0.2f,
-                             /*clipped_wait_frames=*/50);
-  manager_custom->Initialize();
+      CreateAgcManagerDirect({.clipped_level_step = 10,
+                              .clipped_ratio_threshold = 0.2f,
+                              .clipped_wait_frames = 50});
   EXPECT_EQ(manager_custom->clipped_level_step_, 10);
   EXPECT_EQ(manager_custom->clipped_ratio_threshold_, 0.2f);
   EXPECT_EQ(manager_custom->clipped_wait_frames_, 50);
@@ -1770,14 +1728,9 @@
     GTEST_SKIP() << "Skipped. RMS error override does not affect the test.";
   }
 
-  // TODO(bugs.webrtc.org/12874): Use designated initializers once fixed.
-  ClippingPredictorConfig config;
-  config.enabled = false;
+  std::unique_ptr<AgcManagerDirect> manager =
+      CreateAgcManagerDirect({.clipping_predictor = {.enabled = false}});
 
-  std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect(
-      kInitialInputVolume, kClippedLevelStep, kClippedRatioThreshold,
-      kClippedWaitFrames, config);
-  manager->Initialize();
   EXPECT_FALSE(manager->clipping_predictor_enabled());
   EXPECT_FALSE(manager->use_clipping_predictor_step());
 }
@@ -1797,15 +1750,9 @@
     GTEST_SKIP() << "Skipped. RMS error override does not affect the test.";
   }
 
-  // TODO(bugs.webrtc.org/12874): Use designated initializers once fixed.
-  ClippingPredictorConfig config;
-  config.enabled = true;
-  config.use_predicted_step = true;
-
   std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect(
-      kInitialInputVolume, kClippedLevelStep, kClippedRatioThreshold,
-      kClippedWaitFrames, config);
-  manager->Initialize();
+      {.clipping_predictor = {.enabled = true, .use_predicted_step = true}});
+
   EXPECT_TRUE(manager->clipping_predictor_enabled());
   EXPECT_TRUE(manager->use_clipping_predictor_step());
 }
@@ -1817,7 +1764,7 @@
 
   AnalogAgcConfig config = GetAnalogAgcTestConfig();
   config.clipping_predictor.enabled = false;
-  AgcManagerDirect manager(config, new ::testing::NiceMock<MockAgc>());
+  AgcManagerDirect manager(env_, config, new ::testing::NiceMock<MockAgc>());
   manager.Initialize();
   manager.set_stream_analog_level(/*level=*/255);
   EXPECT_FALSE(manager.clipping_predictor_enabled());
@@ -1843,10 +1790,10 @@
   config_with_prediction.clipping_predictor.use_predicted_step = true;
   AnalogAgcConfig config_without_prediction = GetAnalogAgcTestConfig();
   config_without_prediction.clipping_predictor.enabled = false;
-  AgcManagerDirect manager_with_prediction(config_with_prediction,
+  AgcManagerDirect manager_with_prediction(env_, config_with_prediction,
                                            new ::testing::NiceMock<MockAgc>());
   AgcManagerDirect manager_without_prediction(
-      config_without_prediction, new ::testing::NiceMock<MockAgc>());
+      env_, config_without_prediction, new ::testing::NiceMock<MockAgc>());
 
   manager_with_prediction.Initialize();
   manager_without_prediction.Initialize();
@@ -1951,10 +1898,10 @@
   config_with_prediction.clipping_predictor.use_predicted_step = false;
   AnalogAgcConfig config_without_prediction = GetAnalogAgcTestConfig();
   config_without_prediction.clipping_predictor.enabled = false;
-  AgcManagerDirect manager_with_prediction(config_with_prediction,
+  AgcManagerDirect manager_with_prediction(env_, config_with_prediction,
                                            new ::testing::NiceMock<MockAgc>());
   AgcManagerDirect manager_without_prediction(
-      config_without_prediction, new ::testing::NiceMock<MockAgc>());
+      env_, config_without_prediction, new ::testing::NiceMock<MockAgc>());
 
   constexpr int kInitialLevel = 255;
   constexpr float kClippingPeakRatio = 1.0f;
@@ -2038,8 +1985,8 @@
 // Checks that passing an empty speech level and probability overrides to
 // `Process()` has the same effect as passing no overrides.
 TEST_P(AgcManagerDirectParametrizedTest, EmptyRmsErrorOverrideHasNoEffect) {
-  AgcManagerDirect manager_1(kNumChannels, GetAnalogAgcTestConfig());
-  AgcManagerDirect manager_2(kNumChannels, GetAnalogAgcTestConfig());
+  AgcManagerDirect manager_1(env_, kNumChannels, GetAnalogAgcTestConfig());
+  AgcManagerDirect manager_2(env_, kNumChannels, GetAnalogAgcTestConfig());
   manager_1.Initialize();
   manager_2.Initialize();
 
@@ -2080,8 +2027,8 @@
 // Checks that passing a non-empty speech level and probability overrides to
 // `Process()` has an effect.
 TEST_P(AgcManagerDirectParametrizedTest, NonEmptyRmsErrorOverrideHasEffect) {
-  AgcManagerDirect manager_1(kNumChannels, GetAnalogAgcTestConfig());
-  AgcManagerDirect manager_2(kNumChannels, GetAnalogAgcTestConfig());
+  AgcManagerDirect manager_1(env_, kNumChannels, GetAnalogAgcTestConfig());
+  AgcManagerDirect manager_2(env_, kNumChannels, GetAnalogAgcTestConfig());
   manager_1.Initialize();
   manager_2.Initialize();
 
@@ -2125,7 +2072,7 @@
 
   constexpr AnalogAgcConfig kConfig{.enabled = true,
                                     .clipping_predictor{.enabled = true}};
-  AgcManagerDirect manager(num_channels, kConfig);
+  AgcManagerDirect manager(CreateEnvironment(), num_channels, kConfig);
   manager.Initialize();
   AudioBuffer buffer(sample_rate_hz, num_channels, sample_rate_hz, num_channels,
                      sample_rate_hz, num_channels);
diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc
index fe72b39..45b1c82 100644
--- a/modules/audio_processing/audio_processing_impl.cc
+++ b/modules/audio_processing/audio_processing_impl.cc
@@ -2017,8 +2017,9 @@
     if (re_creation) {
       stream_analog_level = submodules_.agc_manager->recommended_analog_level();
     }
-    submodules_.agc_manager.reset(new AgcManagerDirect(
-        num_proc_channels(), config_.gain_controller1.analog_gain_controller));
+    submodules_.agc_manager = std::make_unique<AgcManagerDirect>(
+        env_, num_proc_channels(),
+        config_.gain_controller1.analog_gain_controller);
     if (re_creation) {
       submodules_.agc_manager->set_stream_analog_level(stream_analog_level);
     }