Implement ANA statistics.

This CL also makes it possible to enable/prevent ANA controllers from making adaptations using field trials.

BUG=webrtc:8127

Review-Url: https://codereview.webrtc.org/3007983002
Cr-Original-Commit-Position: refs/heads/master@{#19761}
Cr-Mirrored-From: https://chromium.googlesource.com/external/webrtc
Cr-Mirrored-Commit: 17289097f08280b377c4ca550e8d75e46ffcede3
diff --git a/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.cc b/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.cc
index 5eff4b3..e2786ca 100644
--- a/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.cc
+++ b/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.cc
@@ -14,6 +14,7 @@
 
 #include "webrtc/rtc_base/logging.h"
 #include "webrtc/rtc_base/timeutils.h"
+#include "webrtc/system_wrappers/include/field_trial.h"
 
 namespace webrtc {
 
@@ -40,7 +41,17 @@
                                    kEventLogMinBitrateChangeBps,
                                    kEventLogMinBitrateChangeFraction,
                                    kEventLogMinPacketLossChangeFraction)
-              : nullptr) {
+              : nullptr),
+      enable_bitrate_adaptation_(
+          webrtc::field_trial::IsEnabled("WebRTC-Audio-BitrateAdaptation")),
+      enable_dtx_adaptation_(
+          webrtc::field_trial::IsEnabled("WebRTC-Audio-DtxAdaptation")),
+      enable_fec_adaptation_(
+          webrtc::field_trial::IsEnabled("WebRTC-Audio-FecAdaptation")),
+      enable_channel_adaptation_(
+          webrtc::field_trial::IsEnabled("WebRTC-Audio-ChannelAdaptation")),
+      enable_frame_length_adaptation_(webrtc::field_trial::IsEnabled(
+          "WebRTC-Audio-FrameLengthAdaptation")) {
   RTC_DCHECK(controller_manager_);
 }
 
@@ -118,6 +129,55 @@
        controller_manager_->GetSortedControllers(last_metrics_))
     controller->MakeDecision(&config);
 
+  // Update ANA stats.
+  auto increment_opt = [](rtc::Optional<uint32_t>& a) {
+    a = rtc::Optional<uint32_t>(a.value_or(0) + 1);
+  };
+  if (prev_config_) {
+    if (config.bitrate_bps != prev_config_->bitrate_bps) {
+      increment_opt(stats_.bitrate_action_counter);
+    }
+    if (config.enable_dtx != prev_config_->enable_dtx) {
+      increment_opt(stats_.dtx_action_counter);
+    }
+    if (config.enable_fec != prev_config_->enable_fec) {
+      increment_opt(stats_.fec_action_counter);
+    }
+    if (config.frame_length_ms && prev_config_->frame_length_ms) {
+      if (*config.frame_length_ms > *prev_config_->frame_length_ms) {
+        increment_opt(stats_.frame_length_increase_counter);
+      } else if (*config.frame_length_ms < *prev_config_->frame_length_ms) {
+        increment_opt(stats_.frame_length_decrease_counter);
+      }
+    }
+    if (config.num_channels != prev_config_->num_channels) {
+      increment_opt(stats_.channel_action_counter);
+    }
+    if (config.uplink_packet_loss_fraction) {
+      stats_.uplink_packet_loss_fraction =
+          rtc::Optional<float>(*config.uplink_packet_loss_fraction);
+    }
+  }
+  prev_config_ = rtc::Optional<AudioEncoderRuntimeConfig>(config);
+
+  // Prevent certain controllers from taking action (determined by field trials)
+  if (!enable_bitrate_adaptation_ && config.bitrate_bps) {
+    config.bitrate_bps.reset();
+  }
+  if (!enable_dtx_adaptation_ && config.enable_dtx) {
+    config.enable_dtx.reset();
+  }
+  if (!enable_fec_adaptation_ && config.enable_fec) {
+    config.enable_fec.reset();
+    config.uplink_packet_loss_fraction.reset();
+  }
+  if (!enable_frame_length_adaptation_ && config.frame_length_ms) {
+    config.frame_length_ms.reset();
+  }
+  if (!enable_channel_adaptation_ && config.num_channels) {
+    config.num_channels.reset();
+  }
+
   if (debug_dump_writer_)
     debug_dump_writer_->DumpEncoderRuntimeConfig(config, rtc::TimeMillis());
 
@@ -136,9 +196,7 @@
 }
 
 ANAStats AudioNetworkAdaptorImpl::GetStats() const {
-  // TODO(ivoc): Actually implement the stat.
-  // Tracking bug: https://crbug.com/webrtc/8127
-  return ANAStats();
+  return stats_;
 }
 
 void AudioNetworkAdaptorImpl::DumpNetworkMetrics() {
diff --git a/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h b/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h
index bd2a250..8e76db2 100644
--- a/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h
+++ b/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h
@@ -75,6 +75,16 @@
 
   Controller::NetworkMetrics last_metrics_;
 
+  rtc::Optional<AudioEncoderRuntimeConfig> prev_config_;
+
+  ANAStats stats_;
+
+  const bool enable_bitrate_adaptation_;
+  const bool enable_dtx_adaptation_;
+  const bool enable_fec_adaptation_;
+  const bool enable_channel_adaptation_;
+  const bool enable_frame_length_adaptation_;
+
   RTC_DISALLOW_COPY_AND_ASSIGN(AudioNetworkAdaptorImpl);
 };
 
diff --git a/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl_unittest.cc b/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl_unittest.cc
index 5695a38..a0dc12c 100644
--- a/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl_unittest.cc
+++ b/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl_unittest.cc
@@ -17,6 +17,7 @@
 #include "webrtc/modules/audio_coding/audio_network_adaptor/mock/mock_controller_manager.h"
 #include "webrtc/modules/audio_coding/audio_network_adaptor/mock/mock_debug_dump_writer.h"
 #include "webrtc/rtc_base/fakeclock.h"
+#include "webrtc/test/field_trial.h"
 #include "webrtc/test/gtest.h"
 
 namespace webrtc {
@@ -178,6 +179,9 @@
 
 TEST(AudioNetworkAdaptorImplTest,
      DumpEncoderRuntimeConfigIsCalledOnGetEncoderRuntimeConfig) {
+  test::ScopedFieldTrials override_field_trials(
+      "WebRTC-Audio-BitrateAdaptation/Enabled/WebRTC-Audio-FecAdaptation/"
+      "Enabled/");
   rtc::ScopedFakeClock fake_clock;
   fake_clock.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kClockInitialTimeMs));
   auto states = CreateAudioNetworkAdaptor();
@@ -255,6 +259,9 @@
 }
 
 TEST(AudioNetworkAdaptorImplTest, LogRuntimeConfigOnGetEncoderRuntimeConfig) {
+  test::ScopedFieldTrials override_field_trials(
+      "WebRTC-Audio-BitrateAdaptation/Enabled/WebRTC-Audio-FecAdaptation/"
+      "Enabled/");
   auto states = CreateAudioNetworkAdaptor();
 
   AudioEncoderRuntimeConfig config;
@@ -276,9 +283,17 @@
   // Simulate some adaptation, otherwise the stats will not show anything.
   AudioEncoderRuntimeConfig config1, config2;
   config1.bitrate_bps = rtc::Optional<int>(32000);
+  config1.num_channels = rtc::Optional<size_t>(2);
   config1.enable_fec = rtc::Optional<bool>(true);
+  config1.enable_dtx = rtc::Optional<bool>(true);
+  config1.frame_length_ms = rtc::Optional<int>(120);
+  config1.uplink_packet_loss_fraction = rtc::Optional<float>(0.1f);
   config2.bitrate_bps = rtc::Optional<int>(16000);
+  config2.num_channels = rtc::Optional<size_t>(1);
   config2.enable_fec = rtc::Optional<bool>(false);
+  config2.enable_dtx = rtc::Optional<bool>(false);
+  config2.frame_length_ms = rtc::Optional<int>(60);
+  config1.uplink_packet_loss_fraction = rtc::Optional<float>(0.1f);
 
   EXPECT_CALL(*states.mock_controllers[0], MakeDecision(_))
       .WillOnce(SetArgPointee<0>(config1));
@@ -286,24 +301,19 @@
   EXPECT_CALL(*states.mock_controllers[0], MakeDecision(_))
       .WillOnce(SetArgPointee<0>(config2));
   states.audio_network_adaptor->GetEncoderRuntimeConfig();
+  EXPECT_CALL(*states.mock_controllers[0], MakeDecision(_))
+      .WillOnce(SetArgPointee<0>(config1));
+  states.audio_network_adaptor->GetEncoderRuntimeConfig();
 
   auto ana_stats = states.audio_network_adaptor->GetStats();
 
-  // Check that the default stats are returned, as these have not been
-  // implemented yet). Tracking bug: https://crbug.com/8127
-  auto default_stats = ANAStats();
-  EXPECT_EQ(ana_stats.bitrate_action_counter,
-            default_stats.bitrate_action_counter);
-  EXPECT_EQ(ana_stats.channel_action_counter,
-            default_stats.channel_action_counter);
-  EXPECT_EQ(ana_stats.dtx_action_counter, default_stats.dtx_action_counter);
-  EXPECT_EQ(ana_stats.fec_action_counter, default_stats.fec_action_counter);
-  EXPECT_EQ(ana_stats.frame_length_increase_counter,
-            default_stats.frame_length_increase_counter);
-  EXPECT_EQ(ana_stats.frame_length_decrease_counter,
-            default_stats.frame_length_decrease_counter);
-  EXPECT_EQ(ana_stats.uplink_packet_loss_fraction,
-            default_stats.uplink_packet_loss_fraction);
+  EXPECT_EQ(ana_stats.bitrate_action_counter, 2);
+  EXPECT_EQ(ana_stats.channel_action_counter, 2);
+  EXPECT_EQ(ana_stats.dtx_action_counter, 2);
+  EXPECT_EQ(ana_stats.fec_action_counter, 2);
+  EXPECT_EQ(ana_stats.frame_length_increase_counter, 1);
+  EXPECT_EQ(ana_stats.frame_length_decrease_counter, 1);
+  EXPECT_EQ(ana_stats.uplink_packet_loss_fraction, 0.1f);
 }
 
 }  // namespace webrtc