Open backdoor in VoiceEngineImpl to get at the actual voe::Channel objects from an ID.
This will allow Audio[Send|Receive]Stream to bypass the VoE interfaces in many cases and talk directly to the channel.

BUG=webrtc:4690

Review URL: https://codereview.webrtc.org/1459083007

Cr-Commit-Position: refs/heads/master@{#10788}
diff --git a/webrtc/audio/audio_receive_stream.cc b/webrtc/audio/audio_receive_stream.cc
index 82e8ddf..dd3f3c4 100644
--- a/webrtc/audio/audio_receive_stream.cc
+++ b/webrtc/audio/audio_receive_stream.cc
@@ -18,12 +18,14 @@
 #include "webrtc/base/logging.h"
 #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
 #include "webrtc/system_wrappers/include/tick_util.h"
+#include "webrtc/voice_engine/channel_proxy.h"
 #include "webrtc/voice_engine/include/voe_base.h"
 #include "webrtc/voice_engine/include/voe_codec.h"
 #include "webrtc/voice_engine/include/voe_neteq_stats.h"
 #include "webrtc/voice_engine/include/voe_rtp_rtcp.h"
 #include "webrtc/voice_engine/include/voe_video_sync.h"
 #include "webrtc/voice_engine/include/voe_volume_control.h"
+#include "webrtc/voice_engine/voice_engine_impl.h"
 
 namespace webrtc {
 std::string AudioReceiveStream::Config::Rtp::ToString() const {
@@ -74,24 +76,26 @@
   RTC_DCHECK(audio_state_.get());
   RTC_DCHECK(rtp_header_parser_);
 
+  VoiceEngineImpl* voe_impl = static_cast<VoiceEngineImpl*>(voice_engine());
+  channel_proxy_ = voe_impl->GetChannelProxy(config_.voe_channel_id);
+  channel_proxy_->SetLocalSSRC(config.rtp.local_ssrc);
+
   const int channel_id = config.voe_channel_id;
   ScopedVoEInterface<VoERTP_RTCP> rtp(voice_engine());
-  int error = rtp->SetLocalSSRC(channel_id, config.rtp.local_ssrc);
-  RTC_DCHECK_EQ(0, error);
   for (const auto& extension : config.rtp.extensions) {
     // One-byte-extension local identifiers are in the range 1-14 inclusive.
     RTC_DCHECK_GE(extension.id, 1);
     RTC_DCHECK_LE(extension.id, 14);
     if (extension.name == RtpExtension::kAudioLevel) {
-      error = rtp->SetReceiveAudioLevelIndicationStatus(channel_id, true,
-                                                        extension.id);
+      int error = rtp->SetReceiveAudioLevelIndicationStatus(channel_id, true,
+                                                            extension.id);
       RTC_DCHECK_EQ(0, error);
       bool registered = rtp_header_parser_->RegisterRtpHeaderExtension(
           kRtpExtensionAudioLevel, extension.id);
       RTC_DCHECK(registered);
     } else if (extension.name == RtpExtension::kAbsSendTime) {
-      error = rtp->SetReceiveAbsoluteSenderTimeStatus(channel_id, true,
-                                                      extension.id);
+      int error = rtp->SetReceiveAbsoluteSenderTimeStatus(channel_id, true,
+                                                          extension.id);
       RTC_DCHECK_EQ(0, error);
       bool registered = rtp_header_parser_->RegisterRtpHeaderExtension(
           kRtpExtensionAbsoluteSendTime, extension.id);
diff --git a/webrtc/audio/audio_receive_stream.h b/webrtc/audio/audio_receive_stream.h
index e7a2952..08e65cd 100644
--- a/webrtc/audio/audio_receive_stream.h
+++ b/webrtc/audio/audio_receive_stream.h
@@ -17,11 +17,13 @@
 #include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
 
 namespace webrtc {
-
 class RemoteBitrateEstimator;
 
-namespace internal {
+namespace voe {
+class ChannelProxy;
+}  // namespace voe
 
+namespace internal {
 class AudioReceiveStream final : public webrtc::AudioReceiveStream {
  public:
   AudioReceiveStream(RemoteBitrateEstimator* remote_bitrate_estimator,
@@ -51,6 +53,7 @@
   const webrtc::AudioReceiveStream::Config config_;
   rtc::scoped_refptr<webrtc::AudioState> audio_state_;
   rtc::scoped_ptr<RtpHeaderParser> rtp_header_parser_;
+  rtc::scoped_ptr<voe::ChannelProxy> channel_proxy_;
 
   RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AudioReceiveStream);
 };
diff --git a/webrtc/audio/audio_receive_stream_unittest.cc b/webrtc/audio/audio_receive_stream_unittest.cc
index 5efd5b0..aac7c0f 100644
--- a/webrtc/audio/audio_receive_stream_unittest.cc
+++ b/webrtc/audio/audio_receive_stream_unittest.cc
@@ -14,6 +14,7 @@
 #include "webrtc/audio/conversion.h"
 #include "webrtc/modules/remote_bitrate_estimator/include/mock/mock_remote_bitrate_estimator.h"
 #include "webrtc/modules/rtp_rtcp/source/byte_io.h"
+#include "webrtc/test/mock_voe_channel_proxy.h"
 #include "webrtc/test/mock_voice_engine.h"
 
 namespace webrtc {
@@ -53,6 +54,8 @@
 
 struct ConfigHelper {
   ConfigHelper() {
+    using testing::Invoke;
+
     EXPECT_CALL(voice_engine_,
         RegisterVoiceEngineObserver(_)).WillOnce(Return(0));
     EXPECT_CALL(voice_engine_,
@@ -61,8 +64,13 @@
     config.voice_engine = &voice_engine_;
     audio_state_ = AudioState::Create(config);
 
-    EXPECT_CALL(voice_engine_, SetLocalSSRC(kChannelId, kLocalSsrc))
-        .WillOnce(Return(0));
+    EXPECT_CALL(voice_engine_, ChannelProxyFactory(kChannelId))
+        .WillOnce(Invoke([this](int channel_id) {
+          EXPECT_FALSE(channel_proxy_);
+          channel_proxy_ = new testing::StrictMock<MockVoEChannelProxy>();
+          EXPECT_CALL(*channel_proxy_, SetLocalSSRC(kLocalSsrc)).Times(1);
+          return channel_proxy_;
+        }));
     EXPECT_CALL(voice_engine_,
         SetReceiveAbsoluteSenderTimeStatus(kChannelId, true, kAbsSendTimeId))
             .WillOnce(Return(0));
@@ -76,7 +84,7 @@
         RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeId));
     stream_config_.rtp.extensions.push_back(
         RtpExtension(RtpExtension::kAudioLevel, kAudioLevelId));
-}
+  }
 
   MockRemoteBitrateEstimator* remote_bitrate_estimator() {
     return &remote_bitrate_estimator_;
@@ -89,6 +97,7 @@
     using testing::DoAll;
     using testing::SetArgPointee;
     using testing::SetArgReferee;
+
     EXPECT_CALL(voice_engine_, GetRTCPStatistics(kChannelId, _))
         .WillOnce(DoAll(SetArgReferee<1>(kCallStats), Return(0)));
     EXPECT_CALL(voice_engine_, GetRecCodec(kChannelId, _))
@@ -110,6 +119,7 @@
   testing::StrictMock<MockVoiceEngine> voice_engine_;
   rtc::scoped_refptr<AudioState> audio_state_;
   AudioReceiveStream::Config stream_config_;
+  testing::StrictMock<MockVoEChannelProxy>* channel_proxy_ = nullptr;
 };
 
 void BuildAbsoluteSendTimeExtension(uint8_t* buffer,
diff --git a/webrtc/audio/audio_send_stream.cc b/webrtc/audio/audio_send_stream.cc
index a7b98c7..04d3a25 100644
--- a/webrtc/audio/audio_send_stream.cc
+++ b/webrtc/audio/audio_send_stream.cc
@@ -17,10 +17,12 @@
 #include "webrtc/audio/scoped_voe_interface.h"
 #include "webrtc/base/checks.h"
 #include "webrtc/base/logging.h"
+#include "webrtc/voice_engine/channel_proxy.h"
 #include "webrtc/voice_engine/include/voe_audio_processing.h"
 #include "webrtc/voice_engine/include/voe_codec.h"
 #include "webrtc/voice_engine/include/voe_rtp_rtcp.h"
 #include "webrtc/voice_engine/include/voe_volume_control.h"
+#include "webrtc/voice_engine/voice_engine_impl.h"
 
 namespace webrtc {
 std::string AudioSendStream::Config::Rtp::ToString() const {
@@ -51,7 +53,6 @@
 }
 
 namespace internal {
-
 AudioSendStream::AudioSendStream(
     const webrtc::AudioSendStream::Config& config,
     const rtc::scoped_refptr<webrtc::AudioState>& audio_state)
@@ -60,25 +61,25 @@
   RTC_DCHECK_NE(config_.voe_channel_id, -1);
   RTC_DCHECK(audio_state_.get());
 
+  VoiceEngineImpl* voe_impl = static_cast<VoiceEngineImpl*>(voice_engine());
+  channel_proxy_ = voe_impl->GetChannelProxy(config_.voe_channel_id);
+  channel_proxy_->SetRTCPStatus(true);
+  channel_proxy_->SetLocalSSRC(config.rtp.ssrc);
+  channel_proxy_->SetRTCP_CNAME(config.rtp.c_name);
+
   const int channel_id = config.voe_channel_id;
   ScopedVoEInterface<VoERTP_RTCP> rtp(voice_engine());
-  int error = rtp->SetRTCPStatus(channel_id, true);
-  RTC_DCHECK_EQ(0, error);
-  error = rtp->SetLocalSSRC(channel_id, config.rtp.ssrc);
-  RTC_DCHECK_EQ(0, error);
-  error = rtp->SetRTCP_CNAME(channel_id, config.rtp.c_name.c_str());
-  RTC_DCHECK_EQ(0, error);
   for (const auto& extension : config.rtp.extensions) {
     // One-byte-extension local identifiers are in the range 1-14 inclusive.
     RTC_DCHECK_GE(extension.id, 1);
     RTC_DCHECK_LE(extension.id, 14);
     if (extension.name == RtpExtension::kAbsSendTime) {
-      error = rtp->SetSendAbsoluteSenderTimeStatus(channel_id, true,
-                                                   extension.id);
+      int error = rtp->SetSendAbsoluteSenderTimeStatus(channel_id, true,
+                                                       extension.id);
       RTC_DCHECK_EQ(0, error);
     } else if (extension.name == RtpExtension::kAudioLevel) {
-      error = rtp->SetSendAudioLevelIndicationStatus(channel_id, true,
-                                                     extension.id);
+      int error = rtp->SetSendAudioLevelIndicationStatus(channel_id, true,
+                                                         extension.id);
       RTC_DCHECK_EQ(0, error);
     } else {
       RTC_NOTREACHED() << "Registering unsupported RTP extension.";
diff --git a/webrtc/audio/audio_send_stream.h b/webrtc/audio/audio_send_stream.h
index a4eb89d..b670efe 100644
--- a/webrtc/audio/audio_send_stream.h
+++ b/webrtc/audio/audio_send_stream.h
@@ -14,13 +14,16 @@
 #include "webrtc/audio_send_stream.h"
 #include "webrtc/audio_state.h"
 #include "webrtc/base/thread_checker.h"
+#include "webrtc/base/scoped_ptr.h"
 
 namespace webrtc {
-
 class VoiceEngine;
 
-namespace internal {
+namespace voe {
+class ChannelProxy;
+}  // namespace voe
 
+namespace internal {
 class AudioSendStream final : public webrtc::AudioSendStream {
  public:
   AudioSendStream(const webrtc::AudioSendStream::Config& config,
@@ -44,6 +47,7 @@
   rtc::ThreadChecker thread_checker_;
   const webrtc::AudioSendStream::Config config_;
   rtc::scoped_refptr<webrtc::AudioState> audio_state_;
+  rtc::scoped_ptr<voe::ChannelProxy> channel_proxy_;
 
   RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AudioSendStream);
 };
diff --git a/webrtc/audio/audio_send_stream_unittest.cc b/webrtc/audio/audio_send_stream_unittest.cc
index 27d4029..bea8a82 100644
--- a/webrtc/audio/audio_send_stream_unittest.cc
+++ b/webrtc/audio/audio_send_stream_unittest.cc
@@ -13,6 +13,7 @@
 #include "webrtc/audio/audio_send_stream.h"
 #include "webrtc/audio/audio_state.h"
 #include "webrtc/audio/conversion.h"
+#include "webrtc/test/mock_voe_channel_proxy.h"
 #include "webrtc/test/mock_voice_engine.h"
 
 namespace webrtc {
@@ -39,6 +40,7 @@
 
 struct ConfigHelper {
   ConfigHelper() : stream_config_(nullptr) {
+    using testing::Invoke;
     using testing::StrEq;
 
     EXPECT_CALL(voice_engine_,
@@ -49,12 +51,15 @@
     config.voice_engine = &voice_engine_;
     audio_state_ = AudioState::Create(config);
 
-    EXPECT_CALL(voice_engine_, SetRTCPStatus(kChannelId, true))
-        .WillOnce(Return(0));
-    EXPECT_CALL(voice_engine_, SetLocalSSRC(kChannelId, kSsrc))
-        .WillOnce(Return(0));
-    EXPECT_CALL(voice_engine_, SetRTCP_CNAME(kChannelId, StrEq(kCName)))
-        .WillOnce(Return(0));
+    EXPECT_CALL(voice_engine_, ChannelProxyFactory(kChannelId))
+        .WillOnce(Invoke([this](int channel_id) {
+          EXPECT_FALSE(channel_proxy_);
+          channel_proxy_ = new testing::StrictMock<MockVoEChannelProxy>();
+          EXPECT_CALL(*channel_proxy_, SetRTCPStatus(true)).Times(1);
+          EXPECT_CALL(*channel_proxy_, SetLocalSSRC(kSsrc)).Times(1);
+          EXPECT_CALL(*channel_proxy_, SetRTCP_CNAME(StrEq(kCName))).Times(1);
+          return channel_proxy_;
+        }));
     EXPECT_CALL(voice_engine_,
         SetSendAbsoluteSenderTimeStatus(kChannelId, true, kAbsSendTimeId))
             .WillOnce(Return(0));
@@ -109,6 +114,7 @@
   testing::StrictMock<MockVoiceEngine> voice_engine_;
   rtc::scoped_refptr<AudioState> audio_state_;
   AudioSendStream::Config stream_config_;
+  testing::StrictMock<MockVoEChannelProxy>* channel_proxy_ = nullptr;
 };
 }  // namespace
 
diff --git a/webrtc/test/mock_voe_channel_proxy.h b/webrtc/test/mock_voe_channel_proxy.h
new file mode 100644
index 0000000..d42e29b
--- /dev/null
+++ b/webrtc/test/mock_voe_channel_proxy.h
@@ -0,0 +1,30 @@
+/*
+ *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_TEST_MOCK_VOE_CHANNEL_PROXY_H_
+#define WEBRTC_TEST_MOCK_VOE_CHANNEL_PROXY_H_
+
+#include <string>
+#include "testing/gmock/include/gmock/gmock.h"
+#include "webrtc/voice_engine/channel_proxy.h"
+
+namespace webrtc {
+namespace test {
+
+class MockVoEChannelProxy : public voe::ChannelProxy {
+ public:
+  MOCK_METHOD1(SetRTCPStatus, void(bool enable));
+  MOCK_METHOD1(SetLocalSSRC, void(uint32_t ssrc));
+  MOCK_METHOD1(SetRTCP_CNAME, void(const std::string& c_name));
+};
+}  // namespace test
+}  // namespace webrtc
+
+#endif  // WEBRTC_TEST_MOCK_VOE_CHANNEL_PROXY_H_
diff --git a/webrtc/test/mock_voice_engine.h b/webrtc/test/mock_voice_engine.h
index dead226..28a75f8 100644
--- a/webrtc/test/mock_voice_engine.h
+++ b/webrtc/test/mock_voice_engine.h
@@ -12,6 +12,7 @@
 #define WEBRTC_AUDIO_MOCK_VOICE_ENGINE_H_
 
 #include "testing/gmock/include/gmock/gmock.h"
+#include "webrtc/test/mock_voe_channel_proxy.h"
 #include "webrtc/voice_engine/voice_engine_impl.h"
 
 namespace webrtc {
@@ -25,12 +26,26 @@
     // Increase ref count so this object isn't automatically deleted whenever
     // interfaces are Release():d.
     ++_ref_count;
+    // We add this default behavior to make the mock easier to use in tests. It
+    // will create a NiceMock of a voe::ChannelProxy.
+    ON_CALL(*this, ChannelProxyFactory(testing::_))
+        .WillByDefault(
+            testing::Invoke([](int channel_id) {
+              return new testing::NiceMock<MockVoEChannelProxy>();
+            }));
   }
   ~MockVoiceEngine() override {
     // Decrease ref count before base class d-tor is called; otherwise it will
     // trigger an assertion.
     --_ref_count;
   }
+  // Allows injecting a ChannelProxy factory.
+  MOCK_METHOD1(ChannelProxyFactory, voe::ChannelProxy*(int channel_id));
+
+  // VoiceEngineImpl
+  rtc::scoped_ptr<voe::ChannelProxy> GetChannelProxy(int channel_id) override {
+    return rtc::scoped_ptr<voe::ChannelProxy>(ChannelProxyFactory(channel_id));
+  }
 
   // VoEAudioProcessing
   MOCK_METHOD2(SetNsStatus, int(bool enable, NsModes mode));
diff --git a/webrtc/test/webrtc_test_common.gyp b/webrtc/test/webrtc_test_common.gyp
index 83f38ea..8716c9b 100644
--- a/webrtc/test/webrtc_test_common.gyp
+++ b/webrtc/test/webrtc_test_common.gyp
@@ -37,6 +37,7 @@
         'layer_filtering_transport.cc',
         'layer_filtering_transport.h',
         'mock_transport.h',
+        'mock_voe_channel_proxy.h',
         'mock_voice_engine.h',
         'null_transport.cc',
         'null_transport.h',
diff --git a/webrtc/voice_engine/BUILD.gn b/webrtc/voice_engine/BUILD.gn
index efe4781..7a30a7b 100644
--- a/webrtc/voice_engine/BUILD.gn
+++ b/webrtc/voice_engine/BUILD.gn
@@ -14,6 +14,8 @@
     "channel.h",
     "channel_manager.cc",
     "channel_manager.h",
+    "channel_proxy.cc",
+    "channel_proxy.h",
     "dtmf_inband.cc",
     "dtmf_inband.h",
     "dtmf_inband_queue.cc",
diff --git a/webrtc/voice_engine/channel_proxy.cc b/webrtc/voice_engine/channel_proxy.cc
new file mode 100644
index 0000000..f53db87
--- /dev/null
+++ b/webrtc/voice_engine/channel_proxy.cc
@@ -0,0 +1,44 @@
+/*
+ *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/voice_engine/channel_proxy.h"
+
+#include "webrtc/base/checks.h"
+#include "webrtc/voice_engine/channel.h"
+
+namespace webrtc {
+namespace voe {
+ChannelProxy::ChannelProxy() : channel_owner_(nullptr) {}
+
+ChannelProxy::ChannelProxy(const ChannelOwner& channel_owner) :
+    channel_owner_(channel_owner) {
+  RTC_CHECK(channel_owner_.channel());
+}
+
+void ChannelProxy::SetRTCPStatus(bool enable) {
+  RTC_DCHECK(channel_owner_.channel());
+  channel_owner_.channel()->SetRTCPStatus(enable);
+}
+
+void ChannelProxy::SetLocalSSRC(uint32_t ssrc) {
+  RTC_DCHECK(channel_owner_.channel());
+  int error = channel_owner_.channel()->SetLocalSSRC(ssrc);
+  RTC_DCHECK_EQ(0, error);
+}
+
+void ChannelProxy::SetRTCP_CNAME(const std::string& c_name) {
+  // Note: VoERTP_RTCP::SetRTCP_CNAME() accepts a char[256] array.
+  std::string c_name_limited = c_name.substr(0, 255);
+  RTC_DCHECK(channel_owner_.channel());
+  int error = channel_owner_.channel()->SetRTCP_CNAME(c_name_limited.c_str());
+  RTC_DCHECK_EQ(0, error);
+}
+}  // namespace voe
+}  // namespace webrtc
diff --git a/webrtc/voice_engine/channel_proxy.h b/webrtc/voice_engine/channel_proxy.h
new file mode 100644
index 0000000..5a7ead2
--- /dev/null
+++ b/webrtc/voice_engine/channel_proxy.h
@@ -0,0 +1,44 @@
+/*
+ *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_VOICE_ENGINE_CHANNEL_PROXY_H_
+#define WEBRTC_VOICE_ENGINE_CHANNEL_PROXY_H_
+
+#include "webrtc/voice_engine/channel_manager.h"
+
+#include <string>
+
+namespace webrtc {
+namespace voe {
+
+// This class provides the "view" of a voe::Channel that we need to implement
+// webrtc::AudioSendStream and webrtc::AudioReceiveStream. It serves two
+// purposes:
+//  1. Allow mocking just the interfaces used, instead of the entire
+//     voe::Channel class.
+//  2. Provide a refined interface for the stream classes, including assumptions
+//     on return values and input adaptation.
+class ChannelProxy {
+ public:
+  ChannelProxy();
+  explicit ChannelProxy(const ChannelOwner& channel_owner);
+  virtual ~ChannelProxy() {}
+
+  virtual void SetRTCPStatus(bool enable);
+  virtual void SetLocalSSRC(uint32_t ssrc);
+  virtual void SetRTCP_CNAME(const std::string& c_name);
+
+ private:
+  ChannelOwner channel_owner_;
+};
+}  // namespace voe
+}  // namespace webrtc
+
+#endif  // WEBRTC_VOICE_ENGINE_CHANNEL_PROXY_H_
diff --git a/webrtc/voice_engine/voe_base_impl.cc b/webrtc/voice_engine/voe_base_impl.cc
index 8ea3f63..677e9b1 100644
--- a/webrtc/voice_engine/voe_base_impl.cc
+++ b/webrtc/voice_engine/voe_base_impl.cc
@@ -47,7 +47,7 @@
   delete &callbackCritSect_;
 }
 
-void VoEBaseImpl::OnErrorIsReported(ErrorCode error) {
+void VoEBaseImpl::OnErrorIsReported(const ErrorCode error) {
   CriticalSectionScoped cs(&callbackCritSect_);
   int errCode = 0;
   if (error == AudioDeviceObserver::kRecordingError) {
@@ -63,7 +63,7 @@
   }
 }
 
-void VoEBaseImpl::OnWarningIsReported(WarningCode warning) {
+void VoEBaseImpl::OnWarningIsReported(const WarningCode warning) {
   CriticalSectionScoped cs(&callbackCritSect_);
   int warningCode = 0;
   if (warning == AudioDeviceObserver::kRecordingWarning) {
@@ -79,21 +79,28 @@
   }
 }
 
-int32_t VoEBaseImpl::RecordedDataIsAvailable(
-    const void* audioSamples, size_t nSamples, size_t nBytesPerSample,
-    uint8_t nChannels, uint32_t samplesPerSec, uint32_t totalDelayMS,
-    int32_t clockDrift, uint32_t micLevel, bool keyPressed,
-    uint32_t& newMicLevel) {
+int32_t VoEBaseImpl::RecordedDataIsAvailable(const void* audioSamples,
+                                             const size_t nSamples,
+                                             const size_t nBytesPerSample,
+                                             const uint8_t nChannels,
+                                             const uint32_t samplesPerSec,
+                                             const uint32_t totalDelayMS,
+                                             const int32_t clockDrift,
+                                             const uint32_t currentMicLevel,
+                                             const bool keyPressed,
+                                             uint32_t& newMicLevel) {
   newMicLevel = static_cast<uint32_t>(ProcessRecordedDataWithAPM(
       nullptr, 0, audioSamples, samplesPerSec, nChannels, nSamples,
-      totalDelayMS, clockDrift, micLevel, keyPressed));
+      totalDelayMS, clockDrift, currentMicLevel, keyPressed));
   return 0;
 }
 
-int32_t VoEBaseImpl::NeedMorePlayData(size_t nSamples,
-                                      size_t nBytesPerSample,
-                                      uint8_t nChannels, uint32_t samplesPerSec,
-                                      void* audioSamples, size_t& nSamplesOut,
+int32_t VoEBaseImpl::NeedMorePlayData(const size_t nSamples,
+                                      const size_t nBytesPerSample,
+                                      const uint8_t nChannels,
+                                      const uint32_t samplesPerSec,
+                                      void* audioSamples,
+                                      size_t& nSamplesOut,
                                       int64_t* elapsed_time_ms,
                                       int64_t* ntp_time_ms) {
   GetPlayoutData(static_cast<int>(samplesPerSec), static_cast<int>(nChannels),
diff --git a/webrtc/voice_engine/voe_base_impl.h b/webrtc/voice_engine/voe_base_impl.h
index 5cd0acd..e6c8944 100644
--- a/webrtc/voice_engine/voe_base_impl.h
+++ b/webrtc/voice_engine/voe_base_impl.h
@@ -54,37 +54,57 @@
   int AssociateSendChannel(int channel, int accociate_send_channel) override;
 
   // AudioTransport
-  int32_t RecordedDataIsAvailable(const void* audioSamples, size_t nSamples,
-                                  size_t nBytesPerSample, uint8_t nChannels,
-                                  uint32_t samplesPerSec, uint32_t totalDelayMS,
-                                  int32_t clockDrift, uint32_t micLevel,
-                                  bool keyPressed,
+  int32_t RecordedDataIsAvailable(const void* audioSamples,
+                                  const size_t nSamples,
+                                  const size_t nBytesPerSample,
+                                  const uint8_t nChannels,
+                                  const uint32_t samplesPerSec,
+                                  const uint32_t totalDelayMS,
+                                  const int32_t clockDrift,
+                                  const uint32_t currentMicLevel,
+                                  const bool keyPressed,
                                   uint32_t& newMicLevel) override;
-  int32_t NeedMorePlayData(size_t nSamples, size_t nBytesPerSample,
-                           uint8_t nChannels, uint32_t samplesPerSec,
-                           void* audioSamples, size_t& nSamplesOut,
+  int32_t NeedMorePlayData(const size_t nSamples,
+                           const size_t nBytesPerSample,
+                           const uint8_t nChannels,
+                           const uint32_t samplesPerSec,
+                           void* audioSamples,
+                           size_t& nSamplesOut,
                            int64_t* elapsed_time_ms,
                            int64_t* ntp_time_ms) override;
-  int OnDataAvailable(const int voe_channels[], int number_of_voe_channels,
-                      const int16_t* audio_data, int sample_rate,
-                      int number_of_channels, size_t number_of_frames,
-                      int audio_delay_milliseconds, int volume,
-                      bool key_pressed, bool need_audio_processing) override;
-  void OnData(int voe_channel, const void* audio_data, int bits_per_sample,
-              int sample_rate, int number_of_channels,
+  int OnDataAvailable(const int voe_channels[],
+                      int number_of_voe_channels,
+                      const int16_t* audio_data,
+                      int sample_rate,
+                      int number_of_channels,
+                      size_t number_of_frames,
+                      int audio_delay_milliseconds,
+                      int current_volume,
+                      bool key_pressed,
+                      bool need_audio_processing) override;
+  void OnData(int voe_channel,
+              const void* audio_data,
+              int bits_per_sample,
+              int sample_rate,
+              int number_of_channels,
               size_t number_of_frames) override;
-  void PushCaptureData(int voe_channel, const void* audio_data,
-                       int bits_per_sample, int sample_rate,
+  void PushCaptureData(int voe_channel,
+                       const void* audio_data,
+                       int bits_per_sample,
+                       int sample_rate,
                        int number_of_channels,
                        size_t number_of_frames) override;
-  void PullRenderData(int bits_per_sample, int sample_rate,
-                      int number_of_channels, size_t number_of_frames,
-                      void* audio_data, int64_t* elapsed_time_ms,
+  void PullRenderData(int bits_per_sample,
+                      int sample_rate,
+                      int number_of_channels,
+                      size_t number_of_frames,
+                      void* audio_data,
+                      int64_t* elapsed_time_ms,
                       int64_t* ntp_time_ms) override;
 
   // AudioDeviceObserver
-  void OnErrorIsReported(ErrorCode error) override;
-  void OnWarningIsReported(WarningCode warning) override;
+  void OnErrorIsReported(const ErrorCode error) override;
+  void OnWarningIsReported(const WarningCode warning) override;
 
  protected:
   VoEBaseImpl(voe::SharedData* shared);
diff --git a/webrtc/voice_engine/voice_engine.gyp b/webrtc/voice_engine/voice_engine.gyp
index 570d680..c9b0d85 100644
--- a/webrtc/voice_engine/voice_engine.gyp
+++ b/webrtc/voice_engine/voice_engine.gyp
@@ -49,6 +49,8 @@
         'channel.h',
         'channel_manager.cc',
         'channel_manager.h',
+        'channel_proxy.cc',
+        'channel_proxy.h',
         'dtmf_inband.cc',
         'dtmf_inband.h',
         'dtmf_inband_queue.cc',
diff --git a/webrtc/voice_engine/voice_engine_impl.cc b/webrtc/voice_engine/voice_engine_impl.cc
index 814d619..d9c5744 100644
--- a/webrtc/voice_engine/voice_engine_impl.cc
+++ b/webrtc/voice_engine/voice_engine_impl.cc
@@ -15,8 +15,11 @@
 #include "webrtc/modules/utility/include/jvm_android.h"
 #endif
 
+#include "webrtc/base/checks.h"
 #include "webrtc/modules/audio_coding/main/include/audio_coding_module.h"
+#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
 #include "webrtc/system_wrappers/include/trace.h"
+#include "webrtc/voice_engine/channel_proxy.h"
 #include "webrtc/voice_engine/voice_engine_impl.h"
 
 namespace webrtc {
@@ -77,6 +80,15 @@
   return new_ref;
 }
 
+rtc::scoped_ptr<voe::ChannelProxy> VoiceEngineImpl::GetChannelProxy(
+    int channel_id) {
+  RTC_DCHECK(channel_id >= 0);
+  CriticalSectionScoped cs(crit_sec());
+  RTC_DCHECK(statistics().Initialized());
+  return rtc::scoped_ptr<voe::ChannelProxy>(
+      new voe::ChannelProxy(channel_manager().GetChannel(channel_id)));
+}
+
 VoiceEngine* VoiceEngine::Create() {
   Config* config = new Config();
   return GetVoiceEngine(config, true);
diff --git a/webrtc/voice_engine/voice_engine_impl.h b/webrtc/voice_engine/voice_engine_impl.h
index c3b2e5c..f98f881 100644
--- a/webrtc/voice_engine/voice_engine_impl.h
+++ b/webrtc/voice_engine/voice_engine_impl.h
@@ -11,6 +11,7 @@
 #ifndef WEBRTC_VOICE_ENGINE_VOICE_ENGINE_IMPL_H
 #define WEBRTC_VOICE_ENGINE_VOICE_ENGINE_IMPL_H
 
+#include "webrtc/base/scoped_ptr.h"
 #include "webrtc/engine_configurations.h"
 #include "webrtc/system_wrappers/include/atomic32.h"
 #include "webrtc/voice_engine/voe_base_impl.h"
@@ -48,6 +49,9 @@
 #endif
 
 namespace webrtc {
+namespace voe {
+class ChannelProxy;
+}  // namespace voe
 
 class VoiceEngineImpl : public voe::SharedData,  // Must be the first base class
                         public VoiceEngine,
@@ -128,6 +132,10 @@
   // This implements the Release() method for all the inherited interfaces.
   int Release() override;
 
+  // Backdoor to access a voe::Channel object without a channel ID. This is only
+  // to be used while refactoring the VoE API!
+  virtual rtc::scoped_ptr<voe::ChannelProxy> GetChannelProxy(int channel_id);
+
  // This is *protected* so that FakeVoiceEngine can inherit from the class and
  // manipulate the reference count. See: fake_voice_engine.h.
  protected: