Add new ANA stats to the old GetStats() to count the number of actions taken by each controller.

This CL only wires up the new stats but does not set the values yet. This will be added in a follow-up CL.

BUG=webrtc:8127

Review-Url: https://codereview.webrtc.org/3011623002
Cr-Original-Commit-Position: refs/heads/master@{#19751}
Cr-Mirrored-From: https://chromium.googlesource.com/external/webrtc
Cr-Mirrored-Commit: e1198e068bdcb01dcb8799d6871018092711714e
diff --git a/api/audio_codecs/audio_encoder.cc b/api/audio_codecs/audio_encoder.cc
index 3ee371f..d5be26c 100644
--- a/api/audio_codecs/audio_encoder.cc
+++ b/api/audio_codecs/audio_encoder.cc
@@ -15,6 +15,10 @@
 
 namespace webrtc {
 
+ANAStats::ANAStats() = default;
+ANAStats::~ANAStats() = default;
+ANAStats::ANAStats(const ANAStats&) = default;
+
 AudioEncoder::EncodedInfo::EncodedInfo() = default;
 AudioEncoder::EncodedInfo::EncodedInfo(const EncodedInfo&) = default;
 AudioEncoder::EncodedInfo::EncodedInfo(EncodedInfo&&) = default;
@@ -95,4 +99,8 @@
 void AudioEncoder::SetReceiverFrameLengthRange(int min_frame_length_ms,
                                                int max_frame_length_ms) {}
 
+ANAStats AudioEncoder::GetANAStats() const {
+  return ANAStats();
+}
+
 }  // namespace webrtc
diff --git a/api/audio_codecs/audio_encoder.h b/api/audio_codecs/audio_encoder.h
index 7406d7d..a77894b 100644
--- a/api/audio_codecs/audio_encoder.h
+++ b/api/audio_codecs/audio_encoder.h
@@ -27,6 +27,33 @@
 class Clock;
 class RtcEventLog;
 
+// Statistics related to Audio Network Adaptation.
+struct ANAStats {
+  ANAStats();
+  ANAStats(const ANAStats&);
+  ~ANAStats();
+  // Number of actions taken by the ANA bitrate controller since the start of
+  // the call. If this value is not set, it indicates that the bitrate
+  // controller is disabled.
+  rtc::Optional<uint32_t> bitrate_action_counter;
+  // Number of actions taken by the ANA channel controller since the start of
+  // the call. If this value is not set, it indicates that the channel
+  // controller is disabled.
+  rtc::Optional<uint32_t> channel_action_counter;
+  // Number of actions taken by the ANA DTX controller since the start of the
+  // call. If this value is not set, it indicates that the DTX controller is
+  // disabled.
+  rtc::Optional<uint32_t> dtx_action_counter;
+  // Number of actions taken by the ANA FEC controller since the start of the
+  // call. If this value is not set, it indicates that the FEC controller is
+  // disabled.
+  rtc::Optional<uint32_t> fec_action_counter;
+  // Number of actions taken by the ANA frame length controller since the start
+  // of the call. If this value is not set, it indicates that the frame length
+  // controller is disabled.
+  rtc::Optional<uint32_t> frame_length_action_counter;
+};
+
 // This is the interface class for encoders in AudioCoding module. Each codec
 // type must have an implementation of this class.
 class AudioEncoder {
@@ -203,6 +230,9 @@
   virtual void SetReceiverFrameLengthRange(int min_frame_length_ms,
                                            int max_frame_length_ms);
 
+  // Get statistics related to audio network adaptation.
+  virtual ANAStats GetANAStats() const;
+
  protected:
   // Subclasses implement this to perform the actual encoding. Called by
   // Encode().
diff --git a/api/statstypes.cc b/api/statstypes.cc
index 714d36b..67bf49e 100644
--- a/api/statstypes.cc
+++ b/api/statstypes.cc
@@ -586,6 +586,16 @@
       return "googResidualEchoLikelihood";
     case kStatsValueNameResidualEchoLikelihoodRecentMax:
       return "googResidualEchoLikelihoodRecentMax";
+    case kStatsValueNameAnaBitrateActionCounter:
+      return "googAnaBitrateActionCounter";
+    case kStatsValueNameAnaChannelActionCounter:
+      return "googAnaChannelActionCounter";
+    case kStatsValueNameAnaDtxActionCounter:
+      return "googAnaDtxActionCounter";
+    case kStatsValueNameAnaFecActionCounter:
+      return "googAnaFecActionCounter";
+    case kStatsValueNameAnaFrameLengthActionCounter:
+      return "googAnaFrameLengthActionCounter";
     case kStatsValueNameRetransmitBitrate:
       return "googRetransmitBitrate";
     case kStatsValueNameRtt:
diff --git a/api/statstypes.h b/api/statstypes.h
index 42e3601..219995e 100644
--- a/api/statstypes.h
+++ b/api/statstypes.h
@@ -208,6 +208,11 @@
     kStatsValueNameRenderDelayMs,
     kStatsValueNameResidualEchoLikelihood,
     kStatsValueNameResidualEchoLikelihoodRecentMax,
+    kStatsValueNameAnaBitrateActionCounter,
+    kStatsValueNameAnaChannelActionCounter,
+    kStatsValueNameAnaDtxActionCounter,
+    kStatsValueNameAnaFecActionCounter,
+    kStatsValueNameAnaFrameLengthActionCounter,
     kStatsValueNameRetransmitBitrate,
     kStatsValueNameRtt,
     kStatsValueNameSecondaryDecodedRate,
diff --git a/audio/audio_send_stream.cc b/audio/audio_send_stream.cc
index 5bf6f2b..cb73e84 100644
--- a/audio/audio_send_stream.cc
+++ b/audio/audio_send_stream.cc
@@ -333,6 +333,7 @@
   internal::AudioState* audio_state =
       static_cast<internal::AudioState*>(audio_state_.get());
   stats.typing_noise_detected = audio_state->typing_noise_detected();
+  stats.ana_statistics = channel_proxy_->GetANAStatistics();
 
   return stats;
 }
diff --git a/audio/audio_send_stream_unittest.cc b/audio/audio_send_stream_unittest.cc
index 1308657..4c29f6a 100644
--- a/audio/audio_send_stream_unittest.cc
+++ b/audio/audio_send_stream_unittest.cc
@@ -301,6 +301,8 @@
         .WillRepeatedly(Return(kCallStats));
     EXPECT_CALL(*channel_proxy_, GetRemoteRTCPReportBlocks())
         .WillRepeatedly(Return(report_blocks));
+    EXPECT_CALL(*channel_proxy_, GetANAStatistics())
+        .WillRepeatedly(Return(ANAStats()));
     EXPECT_CALL(voice_engine_, transmit_mixer())
         .WillRepeatedly(Return(&transmit_mixer_));
 
diff --git a/call/audio_send_stream.h b/call/audio_send_stream.h
index 4f7f8c0..ac962c5 100644
--- a/call/audio_send_stream.h
+++ b/call/audio_send_stream.h
@@ -15,6 +15,7 @@
 #include <string>
 #include <vector>
 
+#include "webrtc/api/audio_codecs/audio_encoder.h"
 #include "webrtc/api/audio_codecs/audio_encoder_factory.h"
 #include "webrtc/api/audio_codecs/audio_format.h"
 #include "webrtc/api/call/transport.h"
@@ -61,6 +62,7 @@
     float residual_echo_likelihood = -1.0f;
     float residual_echo_likelihood_recent_max = -1.0f;
     bool typing_noise_detected = false;
+    ANAStats ana_statistics;
   };
 
   struct Config {
diff --git a/media/base/mediachannel.h b/media/base/mediachannel.h
index cea85e6..7e7b815 100644
--- a/media/base/mediachannel.h
+++ b/media/base/mediachannel.h
@@ -15,6 +15,7 @@
 #include <string>
 #include <vector>
 
+#include "webrtc/api/audio_codecs/audio_encoder.h"
 #include "webrtc/api/optional.h"
 #include "webrtc/api/rtpparameters.h"
 #include "webrtc/api/rtpreceiverinterface.h"
@@ -641,6 +642,7 @@
   float residual_echo_likelihood;
   float residual_echo_likelihood_recent_max;
   bool typing_noise_detected;
+  webrtc::ANAStats ana_statistics;
 };
 
 struct VoiceReceiverInfo : public MediaReceiverInfo {
diff --git a/media/engine/webrtcvoiceengine.cc b/media/engine/webrtcvoiceengine.cc
index 8c45e95..d202106 100644
--- a/media/engine/webrtcvoiceengine.cc
+++ b/media/engine/webrtcvoiceengine.cc
@@ -2260,6 +2260,7 @@
     sinfo.residual_echo_likelihood_recent_max =
         stats.residual_echo_likelihood_recent_max;
     sinfo.typing_noise_detected = (send_ ? stats.typing_noise_detected : false);
+    sinfo.ana_statistics = stats.ana_statistics;
     info->senders.push_back(sinfo);
   }
 
diff --git a/media/engine/webrtcvoiceengine_unittest.cc b/media/engine/webrtcvoiceengine_unittest.cc
index 5ccd7d6..67fde12 100644
--- a/media/engine/webrtcvoiceengine_unittest.cc
+++ b/media/engine/webrtcvoiceengine_unittest.cc
@@ -546,6 +546,12 @@
     stats.echo_return_loss_enhancement = 1234;
     stats.residual_echo_likelihood = 0.432f;
     stats.residual_echo_likelihood_recent_max = 0.6f;
+    stats.ana_statistics.bitrate_action_counter = rtc::Optional<uint32_t>(321);
+    stats.ana_statistics.channel_action_counter = rtc::Optional<uint32_t>(432);
+    stats.ana_statistics.dtx_action_counter = rtc::Optional<uint32_t>(543);
+    stats.ana_statistics.fec_action_counter = rtc::Optional<uint32_t>(654);
+    stats.ana_statistics.frame_length_action_counter =
+        rtc::Optional<uint32_t>(765);
     stats.typing_noise_detected = true;
     return stats;
   }
@@ -577,6 +583,16 @@
     EXPECT_EQ(info.residual_echo_likelihood, stats.residual_echo_likelihood);
     EXPECT_EQ(info.residual_echo_likelihood_recent_max,
               stats.residual_echo_likelihood_recent_max);
+    EXPECT_EQ(info.ana_statistics.bitrate_action_counter,
+              stats.ana_statistics.bitrate_action_counter);
+    EXPECT_EQ(info.ana_statistics.channel_action_counter,
+              stats.ana_statistics.channel_action_counter);
+    EXPECT_EQ(info.ana_statistics.dtx_action_counter,
+              stats.ana_statistics.dtx_action_counter);
+    EXPECT_EQ(info.ana_statistics.fec_action_counter,
+              stats.ana_statistics.fec_action_counter);
+    EXPECT_EQ(info.ana_statistics.frame_length_action_counter,
+              stats.ana_statistics.frame_length_action_counter);
     EXPECT_EQ(info.typing_noise_detected,
               stats.typing_noise_detected && is_sending);
   }
diff --git a/modules/audio_coding/BUILD.gn b/modules/audio_coding/BUILD.gn
index 32d5336..898723b 100644
--- a/modules/audio_coding/BUILD.gn
+++ b/modules/audio_coding/BUILD.gn
@@ -913,6 +913,7 @@
   deps = [
     "../..:webrtc_common",
     "../../api:optional",
+    "../../api/audio_codecs:audio_codecs_api",
     "../../common_audio",
     "../../logging:rtc_event_log_api",
     "../../rtc_base:protobuf_utils",
diff --git a/modules/audio_coding/acm2/audio_coding_module.cc b/modules/audio_coding/acm2/audio_coding_module.cc
index f7607c6..0244882 100644
--- a/modules/audio_coding/acm2/audio_coding_module.cc
+++ b/modules/audio_coding/acm2/audio_coding_module.cc
@@ -204,6 +204,8 @@
 
   void GetDecodingCallStatistics(AudioDecodingCallStats* stats) const override;
 
+  ANAStats GetANAStats() const override;
+
  private:
   struct InputData {
     uint32_t input_timestamp;
@@ -1273,6 +1275,14 @@
   receiver_.GetDecodingCallStatistics(call_stats);
 }
 
+ANAStats AudioCodingModuleImpl::GetANAStats() const {
+  rtc::CritScope lock(&acm_crit_sect_);
+  if (encoder_stack_)
+    return encoder_stack_->GetANAStats();
+  // If no encoder is set, return default stats.
+  return ANAStats();
+}
+
 }  // namespace
 
 AudioCodingModule::Config::Config()
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 7645c4a..5eff4b3 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
@@ -135,6 +135,12 @@
   debug_dump_writer_.reset(nullptr);
 }
 
+ANAStats AudioNetworkAdaptorImpl::GetStats() const {
+  // TODO(ivoc): Actually implement the stat.
+  // Tracking bug: https://crbug.com/webrtc/8127
+  return ANAStats();
+}
+
 void AudioNetworkAdaptorImpl::DumpNetworkMetrics() {
   if (debug_dump_writer_)
     debug_dump_writer_->DumpNetworkMetrics(last_metrics_, rtc::TimeMillis());
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 7d7a2cb..bd2a250 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
@@ -58,6 +58,8 @@
 
   void StopDebugDump() override;
 
+  ANAStats GetStats() const override;
+
  private:
   void DumpNetworkMetrics();
 
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 1914939..c29b1e8 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
@@ -270,4 +270,36 @@
   states.audio_network_adaptor->GetEncoderRuntimeConfig();
 }
 
+TEST(AudioNetworkAdaptorImplTest, TestANAStats) {
+  auto states = CreateAudioNetworkAdaptor();
+
+  // Simulate some adaptation, otherwise the stats will not show anything.
+  AudioEncoderRuntimeConfig config1, config2;
+  config1.bitrate_bps = rtc::Optional<int>(32000);
+  config1.enable_fec = rtc::Optional<bool>(true);
+  config2.bitrate_bps = rtc::Optional<int>(16000);
+  config2.enable_fec = rtc::Optional<bool>(false);
+
+  EXPECT_CALL(*states.mock_controllers[0], MakeDecision(_))
+      .WillOnce(SetArgPointee<0>(config1));
+  states.audio_network_adaptor->GetEncoderRuntimeConfig();
+  EXPECT_CALL(*states.mock_controllers[0], MakeDecision(_))
+      .WillOnce(SetArgPointee<0>(config2));
+  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_action_counter,
+            default_stats.frame_length_action_counter);
+}
+
 }  // namespace webrtc
diff --git a/modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h b/modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h
index fa742e6..0097d70 100644
--- a/modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h
+++ b/modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h
@@ -11,6 +11,7 @@
 #ifndef WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_INCLUDE_AUDIO_NETWORK_ADAPTOR_H_
 #define WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_INCLUDE_AUDIO_NETWORK_ADAPTOR_H_
 
+#include "webrtc/api/audio_codecs/audio_encoder.h"
 #include "webrtc/api/optional.h"
 
 namespace webrtc {
@@ -38,7 +39,6 @@
 // encoder based on network metrics.
 class AudioNetworkAdaptor {
  public:
-
   virtual ~AudioNetworkAdaptor() = default;
 
   virtual void SetUplinkBandwidth(int uplink_bandwidth_bps) = 0;
@@ -60,6 +60,8 @@
   virtual void StartDebugDump(FILE* file_handle) = 0;
 
   virtual void StopDebugDump() = 0;
+
+  virtual ANAStats GetStats() const = 0;
 };
 
 }  // namespace webrtc
diff --git a/modules/audio_coding/audio_network_adaptor/mock/mock_audio_network_adaptor.h b/modules/audio_coding/audio_network_adaptor/mock/mock_audio_network_adaptor.h
index 4b9a477..f58a482 100644
--- a/modules/audio_coding/audio_network_adaptor/mock/mock_audio_network_adaptor.h
+++ b/modules/audio_coding/audio_network_adaptor/mock/mock_audio_network_adaptor.h
@@ -40,6 +40,8 @@
   MOCK_METHOD1(StartDebugDump, void(FILE* file_handle));
 
   MOCK_METHOD0(StopDebugDump, void());
+
+  MOCK_CONST_METHOD0(GetStats, ANAStats());
 };
 
 }  // namespace webrtc
diff --git a/modules/audio_coding/codecs/opus/audio_encoder_opus.cc b/modules/audio_coding/codecs/opus/audio_encoder_opus.cc
index cd47bf4..3b4473a 100644
--- a/modules/audio_coding/codecs/opus/audio_encoder_opus.cc
+++ b/modules/audio_coding/codecs/opus/audio_encoder_opus.cc
@@ -773,4 +773,11 @@
   }
 }
 
+ANAStats AudioEncoderOpus::GetANAStats() const {
+  if (audio_network_adaptor_) {
+    return audio_network_adaptor_->GetStats();
+  }
+  return ANAStats();
+}
+
 }  // namespace webrtc
diff --git a/modules/audio_coding/codecs/opus/audio_encoder_opus.h b/modules/audio_coding/codecs/opus/audio_encoder_opus.h
index 588f268..f966dbe 100644
--- a/modules/audio_coding/codecs/opus/audio_encoder_opus.h
+++ b/modules/audio_coding/codecs/opus/audio_encoder_opus.h
@@ -116,6 +116,7 @@
   void OnReceivedOverhead(size_t overhead_bytes_per_packet) override;
   void SetReceiverFrameLengthRange(int min_frame_length_ms,
                                    int max_frame_length_ms) override;
+  ANAStats GetANAStats() const override;
   rtc::ArrayView<const int> supported_frame_lengths_ms() const {
     return config_.supported_frame_lengths_ms;
   }
diff --git a/modules/audio_coding/include/audio_coding_module.h b/modules/audio_coding/include/audio_coding_module.h
index 4ceade2..eb59404 100644
--- a/modules/audio_coding/include/audio_coding_module.h
+++ b/modules/audio_coding/include/audio_coding_module.h
@@ -823,6 +823,8 @@
 
   virtual void GetDecodingCallStatistics(
       AudioDecodingCallStats* call_stats) const = 0;
+
+  virtual ANAStats GetANAStats() const = 0;
 };
 
 }  // namespace webrtc
diff --git a/pc/statscollector.cc b/pc/statscollector.cc
index 08cf464..b964283 100644
--- a/pc/statscollector.cc
+++ b/pc/statscollector.cc
@@ -224,6 +224,26 @@
     }
   }
   report->AddString(StatsReport::kStatsValueNameMediaType, "audio");
+  if (info.ana_statistics.bitrate_action_counter) {
+    report->AddInt(StatsReport::kStatsValueNameAnaBitrateActionCounter,
+                   *info.ana_statistics.bitrate_action_counter);
+  }
+  if (info.ana_statistics.channel_action_counter) {
+    report->AddInt(StatsReport::kStatsValueNameAnaChannelActionCounter,
+                   *info.ana_statistics.channel_action_counter);
+  }
+  if (info.ana_statistics.dtx_action_counter) {
+    report->AddInt(StatsReport::kStatsValueNameAnaDtxActionCounter,
+                   *info.ana_statistics.dtx_action_counter);
+  }
+  if (info.ana_statistics.fec_action_counter) {
+    report->AddInt(StatsReport::kStatsValueNameAnaFecActionCounter,
+                   *info.ana_statistics.fec_action_counter);
+  }
+  if (info.ana_statistics.frame_length_action_counter) {
+    report->AddInt(StatsReport::kStatsValueNameAnaFrameLengthActionCounter,
+                   *info.ana_statistics.frame_length_action_counter);
+  }
 }
 
 void ExtractStats(const cricket::VideoReceiverInfo& info, StatsReport* report) {
diff --git a/pc/statscollector_unittest.cc b/pc/statscollector_unittest.cc
index 56d4fca..5734676 100644
--- a/pc/statscollector_unittest.cc
+++ b/pc/statscollector_unittest.cc
@@ -430,6 +430,37 @@
       report, StatsReport::kStatsValueNameTypingNoiseState, &value_in_report));
   std::string typing_detected = sinfo.typing_noise_detected ? "true" : "false";
   EXPECT_EQ(typing_detected, value_in_report);
+  EXPECT_TRUE(GetValue(report,
+                       StatsReport::kStatsValueNameAnaBitrateActionCounter,
+                       &value_in_report));
+  ASSERT_TRUE(sinfo.ana_statistics.bitrate_action_counter);
+  EXPECT_EQ(
+      rtc::ToString<uint32_t>(*sinfo.ana_statistics.bitrate_action_counter),
+      value_in_report);
+  EXPECT_TRUE(GetValue(report,
+                       StatsReport::kStatsValueNameAnaChannelActionCounter,
+                       &value_in_report));
+  ASSERT_TRUE(sinfo.ana_statistics.channel_action_counter);
+  EXPECT_EQ(
+      rtc::ToString<uint32_t>(*sinfo.ana_statistics.channel_action_counter),
+      value_in_report);
+  EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameAnaDtxActionCounter,
+                       &value_in_report));
+  ASSERT_TRUE(sinfo.ana_statistics.dtx_action_counter);
+  EXPECT_EQ(rtc::ToString<uint32_t>(*sinfo.ana_statistics.dtx_action_counter),
+            value_in_report);
+  EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameAnaFecActionCounter,
+                       &value_in_report));
+  ASSERT_TRUE(sinfo.ana_statistics.fec_action_counter);
+  EXPECT_EQ(rtc::ToString<uint32_t>(*sinfo.ana_statistics.fec_action_counter),
+            value_in_report);
+  EXPECT_TRUE(GetValue(report,
+                       StatsReport::kStatsValueNameAnaFrameLengthActionCounter,
+                       &value_in_report));
+  ASSERT_TRUE(sinfo.ana_statistics.frame_length_action_counter);
+  EXPECT_EQ(rtc::ToString<uint32_t>(
+                *sinfo.ana_statistics.frame_length_action_counter),
+            value_in_report);
 }
 
 // Helper methods to avoid duplication of code.
@@ -450,6 +481,16 @@
   voice_sender_info->echo_delay_std_ms = 111;
   voice_sender_info->aec_quality_min = 112.0f;
   voice_sender_info->typing_noise_detected = false;
+  voice_sender_info->ana_statistics.bitrate_action_counter =
+      rtc::Optional<uint32_t>(113);
+  voice_sender_info->ana_statistics.channel_action_counter =
+      rtc::Optional<uint32_t>(114);
+  voice_sender_info->ana_statistics.dtx_action_counter =
+      rtc::Optional<uint32_t>(115);
+  voice_sender_info->ana_statistics.fec_action_counter =
+      rtc::Optional<uint32_t>(116);
+  voice_sender_info->ana_statistics.frame_length_action_counter =
+      rtc::Optional<uint32_t>(117);
 }
 
 void UpdateVoiceSenderInfoFromAudioTrack(
@@ -1988,6 +2029,7 @@
   stats.AddLocalAudioTrack(audio_track_, kSsrcOfTrack);
 
   cricket::VoiceSenderInfo voice_sender_info;
+  InitVoiceSenderInfo(&voice_sender_info);
   voice_sender_info.add_ssrc(kSsrcOfTrack);
 
   cricket::VoiceMediaInfo stats_read;
diff --git a/test/mock_voe_channel_proxy.h b/test/mock_voe_channel_proxy.h
index 6aa6085..b151aa8 100644
--- a/test/mock_voe_channel_proxy.h
+++ b/test/mock_voe_channel_proxy.h
@@ -52,6 +52,7 @@
   MOCK_CONST_METHOD0(GetRemoteRTCPReportBlocks, std::vector<ReportBlock>());
   MOCK_CONST_METHOD0(GetNetworkStatistics, NetworkStatistics());
   MOCK_CONST_METHOD0(GetDecodingCallStatistics, AudioDecodingCallStats());
+  MOCK_CONST_METHOD0(GetANAStatistics, ANAStats());
   MOCK_CONST_METHOD0(GetSpeechOutputLevel, int());
   MOCK_CONST_METHOD0(GetSpeechOutputLevelFullRange, int());
   MOCK_CONST_METHOD0(GetTotalOutputEnergy, double());
diff --git a/voice_engine/channel.cc b/voice_engine/channel.cc
index 1a56e81..0e83989 100644
--- a/voice_engine/channel.cc
+++ b/voice_engine/channel.cc
@@ -2856,6 +2856,10 @@
   audio_coding_->GetDecodingCallStatistics(stats);
 }
 
+ANAStats Channel::GetANAStatistics() const {
+  return audio_coding_->GetANAStats();
+}
+
 uint32_t Channel::GetDelayEstimate() const {
   rtc::CritScope lock(&video_sync_lock_);
   return audio_coding_->FilteredCurrentDelayMs() + playout_delay_ms_;
diff --git a/voice_engine/channel.h b/voice_engine/channel.h
index 0d71a41..89c2b43 100644
--- a/voice_engine/channel.h
+++ b/voice_engine/channel.h
@@ -268,6 +268,7 @@
   // Stats.
   int GetNetworkStatistics(NetworkStatistics& stats);
   void GetDecodingCallStatistics(AudioDecodingCallStats* stats) const;
+  ANAStats GetANAStatistics() const;
 
   // Audio+Video Sync.
   uint32_t GetDelayEstimate() const;
diff --git a/voice_engine/channel_proxy.cc b/voice_engine/channel_proxy.cc
index cdd4b66..5f4f98a 100644
--- a/voice_engine/channel_proxy.cc
+++ b/voice_engine/channel_proxy.cc
@@ -144,6 +144,11 @@
   return stats;
 }
 
+ANAStats ChannelProxy::GetANAStatistics() const {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  return channel()->GetANAStatistics();
+}
+
 int ChannelProxy::GetSpeechOutputLevel() const {
   RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
   return channel()->GetSpeechOutputLevel();
diff --git a/voice_engine/channel_proxy.h b/voice_engine/channel_proxy.h
index 5aa2839..826117b 100644
--- a/voice_engine/channel_proxy.h
+++ b/voice_engine/channel_proxy.h
@@ -81,6 +81,7 @@
   virtual std::vector<ReportBlock> GetRemoteRTCPReportBlocks() const;
   virtual NetworkStatistics GetNetworkStatistics() const;
   virtual AudioDecodingCallStats GetDecodingCallStatistics() const;
+  virtual ANAStats GetANAStatistics() const;
   virtual int GetSpeechOutputLevel() const;
   virtual int GetSpeechOutputLevelFullRange() const;
   // See description of "totalAudioEnergy" in the WebRTC stats spec: