UMA log for audio_device Init and Start(Playout|Recording). Make Init return a more specific error code, if possible.

BUG=webrtc:5761
R=asapersson@webrtc.org, henrika@webrtc.org

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

Cr-Commit-Position: refs/heads/master@{#13361}
diff --git a/webrtc/modules/audio_device/BUILD.gn b/webrtc/modules/audio_device/BUILD.gn
index 92061a2..35a99ea 100644
--- a/webrtc/modules/audio_device/BUILD.gn
+++ b/webrtc/modules/audio_device/BUILD.gn
@@ -27,6 +27,7 @@
 source_set("audio_device") {
   deps = [
     "../..:webrtc_common",
+    "../../base:rtc_base",
     "../../base:rtc_base_approved",
     "../../common_audio",
     "../../system_wrappers",
diff --git a/webrtc/modules/audio_device/android/audio_device_template.h b/webrtc/modules/audio_device/android/audio_device_template.h
index fa7b15e..46d97f6 100644
--- a/webrtc/modules/audio_device/android/audio_device_template.h
+++ b/webrtc/modules/audio_device/android/audio_device_template.h
@@ -53,23 +53,24 @@
     return 0;
   }
 
-  int32_t Init() override {
+  InitStatus Init() override {
     LOG(INFO) << __FUNCTION__;
     RTC_DCHECK(thread_checker_.CalledOnValidThread());
     RTC_DCHECK(!initialized_);
-    if (!audio_manager_->Init())
-      return -1;
+    if (!audio_manager_->Init()) {
+      return InitStatus::OTHER_ERROR;
+    }
     if (output_.Init() != 0) {
       audio_manager_->Close();
-      return -1;
+      return InitStatus::PLAYOUT_ERROR;
     }
     if (input_.Init() != 0) {
       output_.Terminate();
       audio_manager_->Close();
-      return -1;
+      return InitStatus::RECORDING_ERROR;
     }
     initialized_ = true;
-    return 0;
+    return InitStatus::OK;
   }
 
   int32_t Terminate() override {
diff --git a/webrtc/modules/audio_device/audio_device.gypi b/webrtc/modules/audio_device/audio_device.gypi
index a7c5789..0ef1da1 100644
--- a/webrtc/modules/audio_device/audio_device.gypi
+++ b/webrtc/modules/audio_device/audio_device.gypi
@@ -89,6 +89,9 @@
             'audio_device_impl.cc',
             'audio_device_impl.h',
           ],
+          'dependencies': [
+            '<(webrtc_root)/system_wrappers/system_wrappers.gyp:metrics_default',
+          ],
           'conditions': [
             ['OS=="android"', {
               'sources': [
diff --git a/webrtc/modules/audio_device/audio_device_generic.h b/webrtc/modules/audio_device/audio_device_generic.h
index c76ea52..326d933 100644
--- a/webrtc/modules/audio_device/audio_device_generic.h
+++ b/webrtc/modules/audio_device/audio_device_generic.h
@@ -18,12 +18,22 @@
 
 class AudioDeviceGeneric {
  public:
+  // For use with UMA logging. Must be kept in sync with histograms.xml in
+  // Chrome, located at
+  // https://cs.chromium.org/chromium/src/tools/metrics/histograms/histograms.xml
+  enum class InitStatus {
+    OK = 0,
+    PLAYOUT_ERROR = 1,
+    RECORDING_ERROR = 2,
+    OTHER_ERROR = 3,
+    NUM_STATUSES = 4
+  };
   // Retrieve the currently utilized audio layer
   virtual int32_t ActiveAudioLayer(
       AudioDeviceModule::AudioLayer& audioLayer) const = 0;
 
   // Main initializaton and termination
-  virtual int32_t Init() = 0;
+  virtual InitStatus Init() = 0;
   virtual int32_t Terminate() = 0;
   virtual bool Initialized() const = 0;
 
diff --git a/webrtc/modules/audio_device/audio_device_impl.cc b/webrtc/modules/audio_device/audio_device_impl.cc
index b2a33ef..7c8840a 100644
--- a/webrtc/modules/audio_device/audio_device_impl.cc
+++ b/webrtc/modules/audio_device/audio_device_impl.cc
@@ -8,12 +8,15 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include "webrtc/base/checks.h"
 #include "webrtc/base/logging.h"
 #include "webrtc/base/refcount.h"
 #include "webrtc/base/timeutils.h"
 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
 #include "webrtc/modules/audio_device/audio_device_config.h"
+#include "webrtc/modules/audio_device/audio_device_generic.h"
 #include "webrtc/modules/audio_device/audio_device_impl.h"
+#include "webrtc/system_wrappers/include/metrics.h"
 
 #include <assert.h>
 #include <string.h>
@@ -266,7 +269,7 @@
 
     // create *Linux PulseAudio* implementation
     AudioDeviceLinuxPulse* pulseDevice = new AudioDeviceLinuxPulse(Id());
-    if (pulseDevice->Init() != -1) {
+    if (pulseDevice->Init() == AudioDeviceGeneric::InitStatus::OK) {
       ptrAudioDevice = pulseDevice;
       LOG(INFO) << "Linux PulseAudio APIs will be utilized";
     } else {
@@ -481,11 +484,14 @@
   LOG(INFO) << __FUNCTION__;
   if (_initialized)
     return 0;
+  RTC_CHECK(_ptrAudioDevice);
 
-  if (!_ptrAudioDevice)
-    return -1;
-
-  if (_ptrAudioDevice->Init() == -1) {
+  AudioDeviceGeneric::InitStatus status = _ptrAudioDevice->Init();
+  RTC_HISTOGRAM_ENUMERATION(
+      "WebRTC.Audio.InitializationResult", static_cast<int>(status),
+      static_cast<int>(AudioDeviceGeneric::InitStatus::NUM_STATUSES));
+  if (status != AudioDeviceGeneric::InitStatus::OK) {
+    LOG(LS_ERROR) << "Audio device initialization failed.";
     return -1;
   }
 
@@ -1434,7 +1440,11 @@
   LOG(INFO) << __FUNCTION__;
   CHECK_INITIALIZED();
   _audioDeviceBuffer.InitPlayout();
-  return (_ptrAudioDevice->InitPlayout());
+  int32_t result = _ptrAudioDevice->InitPlayout();
+  LOG(INFO) << "output: " << result;
+  RTC_HISTOGRAM_BOOLEAN("WebRTC.Audio.InitPlayoutSuccess",
+                        static_cast<int>(result == 0));
+  return result;
 }
 
 // ----------------------------------------------------------------------------
@@ -1445,7 +1455,11 @@
   LOG(INFO) << __FUNCTION__;
   CHECK_INITIALIZED();
   _audioDeviceBuffer.InitRecording();
-  return (_ptrAudioDevice->InitRecording());
+  int32_t result = _ptrAudioDevice->InitRecording();
+  LOG(INFO) << "output: " << result;
+  RTC_HISTOGRAM_BOOLEAN("WebRTC.Audio.InitRecordingSuccess",
+                        static_cast<int>(result == 0));
+  return result;
 }
 
 // ----------------------------------------------------------------------------
@@ -1475,7 +1489,11 @@
 int32_t AudioDeviceModuleImpl::StartPlayout() {
   LOG(INFO) << __FUNCTION__;
   CHECK_INITIALIZED();
-  return (_ptrAudioDevice->StartPlayout());
+  int32_t result = _ptrAudioDevice->StartPlayout();
+  LOG(INFO) << "output: " << result;
+  RTC_HISTOGRAM_BOOLEAN("WebRTC.Audio.StartPlayoutSuccess",
+                        static_cast<int>(result == 0));
+  return result;
 }
 
 // ----------------------------------------------------------------------------
@@ -1485,7 +1503,11 @@
 int32_t AudioDeviceModuleImpl::StopPlayout() {
   LOG(INFO) << __FUNCTION__;
   CHECK_INITIALIZED();
-  return (_ptrAudioDevice->StopPlayout());
+  int32_t result = _ptrAudioDevice->StopPlayout();
+  LOG(INFO) << "output: " << result;
+  RTC_HISTOGRAM_BOOLEAN("WebRTC.Audio.StopPlayoutSuccess",
+                        static_cast<int>(result == 0));
+  return result;
 }
 
 // ----------------------------------------------------------------------------
@@ -1505,7 +1527,11 @@
 int32_t AudioDeviceModuleImpl::StartRecording() {
   LOG(INFO) << __FUNCTION__;
   CHECK_INITIALIZED();
-  return (_ptrAudioDevice->StartRecording());
+  int32_t result = _ptrAudioDevice->StartRecording();
+  LOG(INFO) << "output: " << result;
+  RTC_HISTOGRAM_BOOLEAN("WebRTC.Audio.StartRecordingSuccess",
+                        static_cast<int>(result == 0));
+  return result;
 }
 // ----------------------------------------------------------------------------
 //  StopRecording
@@ -1514,7 +1540,11 @@
 int32_t AudioDeviceModuleImpl::StopRecording() {
   LOG(INFO) << __FUNCTION__;
   CHECK_INITIALIZED();
-  return (_ptrAudioDevice->StopRecording());
+  int32_t result = _ptrAudioDevice->StopRecording();
+  LOG(INFO) << "output: " << result;
+  RTC_HISTOGRAM_BOOLEAN("WebRTC.Audio.StopRecordingSuccess",
+                        static_cast<int>(result == 0));
+  return result;
 }
 
 // ----------------------------------------------------------------------------
diff --git a/webrtc/modules/audio_device/dummy/audio_device_dummy.cc b/webrtc/modules/audio_device/dummy/audio_device_dummy.cc
index 92199f6..4961937 100644
--- a/webrtc/modules/audio_device/dummy/audio_device_dummy.cc
+++ b/webrtc/modules/audio_device/dummy/audio_device_dummy.cc
@@ -17,7 +17,9 @@
   return -1;
 }
 
-int32_t AudioDeviceDummy::Init() { return 0; }
+AudioDeviceGeneric::InitStatus AudioDeviceDummy::Init() {
+  return InitStatus::OK;
+}
 
 int32_t AudioDeviceDummy::Terminate() { return 0; }
 
diff --git a/webrtc/modules/audio_device/dummy/audio_device_dummy.h b/webrtc/modules/audio_device/dummy/audio_device_dummy.h
index 75c599e..72a0eb1 100644
--- a/webrtc/modules/audio_device/dummy/audio_device_dummy.h
+++ b/webrtc/modules/audio_device/dummy/audio_device_dummy.h
@@ -27,7 +27,7 @@
       AudioDeviceModule::AudioLayer& audioLayer) const override;
 
   // Main initializaton and termination
-  int32_t Init() override;
+  InitStatus Init() override;
   int32_t Terminate() override;
   bool Initialized() const override;
 
diff --git a/webrtc/modules/audio_device/dummy/file_audio_device.cc b/webrtc/modules/audio_device/dummy/file_audio_device.cc
index 35e77a9..4ecc94f 100644
--- a/webrtc/modules/audio_device/dummy/file_audio_device.cc
+++ b/webrtc/modules/audio_device/dummy/file_audio_device.cc
@@ -55,7 +55,9 @@
   return -1;
 }
 
-int32_t FileAudioDevice::Init() { return 0; }
+AudioDeviceGeneric::InitStatus FileAudioDevice::Init() {
+  return InitStatus::OK;
+}
 
 int32_t FileAudioDevice::Terminate() { return 0; }
 
diff --git a/webrtc/modules/audio_device/dummy/file_audio_device.h b/webrtc/modules/audio_device/dummy/file_audio_device.h
index be6fa3d..ae4737c 100644
--- a/webrtc/modules/audio_device/dummy/file_audio_device.h
+++ b/webrtc/modules/audio_device/dummy/file_audio_device.h
@@ -48,7 +48,7 @@
       AudioDeviceModule::AudioLayer& audioLayer) const override;
 
   // Main initializaton and termination
-  int32_t Init() override;
+  InitStatus Init() override;
   int32_t Terminate() override;
   bool Initialized() const override;
 
diff --git a/webrtc/modules/audio_device/ios/audio_device_ios.h b/webrtc/modules/audio_device/ios/audio_device_ios.h
index e6b72d6..efe2558 100644
--- a/webrtc/modules/audio_device/ios/audio_device_ios.h
+++ b/webrtc/modules/audio_device/ios/audio_device_ios.h
@@ -49,7 +49,7 @@
 
   void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) override;
 
-  int32_t Init() override;
+  InitStatus Init() override;
   int32_t Terminate() override;
   bool Initialized() const override { return initialized_; }
 
diff --git a/webrtc/modules/audio_device/ios/audio_device_ios.mm b/webrtc/modules/audio_device/ios/audio_device_ios.mm
index 0a8da0f..3a745a4b 100644
--- a/webrtc/modules/audio_device/ios/audio_device_ios.mm
+++ b/webrtc/modules/audio_device/ios/audio_device_ios.mm
@@ -121,11 +121,11 @@
   audio_device_buffer_ = audioBuffer;
 }
 
-int32_t AudioDeviceIOS::Init() {
+AudioDeviceGeneric::InitStatus AudioDeviceIOS::Init() {
   LOGI() << "Init";
   RTC_DCHECK(thread_checker_.CalledOnValidThread());
   if (initialized_) {
-    return 0;
+    return InitStatus::OK;
   }
 #if !defined(NDEBUG)
   LogDeviceInfo();
@@ -146,7 +146,7 @@
   // to guarantee mono on the "input side" of the audio unit.
   UpdateAudioDeviceBuffer();
   initialized_ = true;
-  return 0;
+  return InitStatus::OK;
 }
 
 int32_t AudioDeviceIOS::Terminate() {
diff --git a/webrtc/modules/audio_device/linux/audio_device_alsa_linux.cc b/webrtc/modules/audio_device/linux/audio_device_alsa_linux.cc
index bdbccde..f7315de 100644
--- a/webrtc/modules/audio_device/linux/audio_device_alsa_linux.cc
+++ b/webrtc/modules/audio_device/linux/audio_device_alsa_linux.cc
@@ -10,6 +10,7 @@
 
 #include <assert.h>
 
+#include "webrtc/base/logging.h"
 #include "webrtc/modules/audio_device/audio_device_config.h"
 #include "webrtc/modules/audio_device/linux/audio_device_alsa_linux.h"
 
@@ -155,32 +156,25 @@
     return 0;
 }
 
-int32_t AudioDeviceLinuxALSA::Init()
-{
+AudioDeviceGeneric::InitStatus AudioDeviceLinuxALSA::Init() {
+  CriticalSectionScoped lock(&_critSect);
 
-    CriticalSectionScoped lock(&_critSect);
+  // Load libasound
+  if (!AlsaSymbolTable.Load()) {
+    // Alsa is not installed on this system
+    LOG(LS_ERROR) << "failed to load symbol table";
+    return InitStatus::OTHER_ERROR;
+  }
 
-    // Load libasound
-    if (!AlsaSymbolTable.Load())
-    {
-        // Alsa is not installed on
-        // this system
-        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
-                   "  failed to load symbol table");
-        return -1;
-    }
-
-    if (_initialized)
-    {
-        return 0;
-    }
+  if (_initialized) {
+    return InitStatus::OK;
+  }
 #if defined(USE_X11)
     //Get X display handle for typing detection
     _XDisplay = XOpenDisplay(NULL);
-    if (!_XDisplay)
-    {
-        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
-          "  failed to open X display, typing detection will not work");
+    if (!_XDisplay) {
+      LOG(LS_WARNING)
+          << "failed to open X display, typing detection will not work";
     }
 #endif
     _playWarning = 0;
@@ -190,7 +184,7 @@
 
     _initialized = true;
 
-    return 0;
+    return InitStatus::OK;
 }
 
 int32_t AudioDeviceLinuxALSA::Terminate()
diff --git a/webrtc/modules/audio_device/linux/audio_device_alsa_linux.h b/webrtc/modules/audio_device/linux/audio_device_alsa_linux.h
index 340e963..aba62e8 100644
--- a/webrtc/modules/audio_device/linux/audio_device_alsa_linux.h
+++ b/webrtc/modules/audio_device/linux/audio_device_alsa_linux.h
@@ -41,7 +41,7 @@
         AudioDeviceModule::AudioLayer& audioLayer) const override;
 
     // Main initializaton and termination
-    int32_t Init() override;
+    InitStatus Init() override;
     int32_t Terminate() override;
     bool Initialized() const override;
 
diff --git a/webrtc/modules/audio_device/linux/audio_device_pulse_linux.cc b/webrtc/modules/audio_device/linux/audio_device_pulse_linux.cc
index 42c3ea8..e408f22 100644
--- a/webrtc/modules/audio_device/linux/audio_device_pulse_linux.cc
+++ b/webrtc/modules/audio_device/linux/audio_device_pulse_linux.cc
@@ -11,10 +11,9 @@
 #include <assert.h>
 
 #include "webrtc/base/checks.h"
-
+#include "webrtc/base/logging.h"
 #include "webrtc/modules/audio_device/audio_device_config.h"
 #include "webrtc/modules/audio_device/linux/audio_device_pulse_linux.h"
-
 #include "webrtc/system_wrappers/include/event_wrapper.h"
 #include "webrtc/system_wrappers/include/trace.h"
 
@@ -163,58 +162,49 @@
     return 0;
 }
 
-int32_t AudioDeviceLinuxPulse::Init()
-{
-    RTC_DCHECK(thread_checker_.CalledOnValidThread());
-    if (_initialized)
-    {
-        return 0;
+AudioDeviceGeneric::InitStatus AudioDeviceLinuxPulse::Init() {
+  RTC_DCHECK(thread_checker_.CalledOnValidThread());
+  if (_initialized) {
+    return InitStatus::OK;
+  }
+
+  // Initialize PulseAudio
+  if (InitPulseAudio() < 0) {
+    LOG(LS_ERROR) << "failed to initialize PulseAudio";
+    if (TerminatePulseAudio() < 0) {
+      LOG(LS_ERROR) << "failed to terminate PulseAudio";
     }
+    return InitStatus::OTHER_ERROR;
+  }
 
-    // Initialize PulseAudio
-    if (InitPulseAudio() < 0)
-    {
-        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
-                     "  failed to initialize PulseAudio");
+  _playWarning = 0;
+  _playError = 0;
+  _recWarning = 0;
+  _recError = 0;
 
-        if (TerminatePulseAudio() < 0)
-        {
-            WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
-                         "  failed to terminate PulseAudio");
-        }
+  // Get X display handle for typing detection
+  _XDisplay = XOpenDisplay(NULL);
+  if (!_XDisplay) {
+    LOG(LS_WARNING)
+        << "failed to open X display, typing detection will not work";
+  }
 
-        return -1;
-    }
+  // RECORDING
+  _ptrThreadRec.reset(new rtc::PlatformThread(
+      RecThreadFunc, this, "webrtc_audio_module_rec_thread"));
 
-    _playWarning = 0;
-    _playError = 0;
-    _recWarning = 0;
-    _recError = 0;
+  _ptrThreadRec->Start();
+  _ptrThreadRec->SetPriority(rtc::kRealtimePriority);
 
-    //Get X display handle for typing detection
-    _XDisplay = XOpenDisplay(NULL);
-    if (!_XDisplay)
-    {
-        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
-          "  failed to open X display, typing detection will not work");
-    }
+  // PLAYOUT
+  _ptrThreadPlay.reset(new rtc::PlatformThread(
+      PlayThreadFunc, this, "webrtc_audio_module_play_thread"));
+  _ptrThreadPlay->Start();
+  _ptrThreadPlay->SetPriority(rtc::kRealtimePriority);
 
-    // RECORDING
-    _ptrThreadRec.reset(new rtc::PlatformThread(
-        RecThreadFunc, this, "webrtc_audio_module_rec_thread"));
+  _initialized = true;
 
-    _ptrThreadRec->Start();
-    _ptrThreadRec->SetPriority(rtc::kRealtimePriority);
-
-    // PLAYOUT
-    _ptrThreadPlay.reset(new rtc::PlatformThread(
-        PlayThreadFunc, this, "webrtc_audio_module_play_thread"));
-    _ptrThreadPlay->Start();
-    _ptrThreadPlay->SetPriority(rtc::kRealtimePriority);
-
-    _initialized = true;
-
-    return 0;
+  return InitStatus::OK;
 }
 
 int32_t AudioDeviceLinuxPulse::Terminate()
diff --git a/webrtc/modules/audio_device/linux/audio_device_pulse_linux.h b/webrtc/modules/audio_device/linux/audio_device_pulse_linux.h
index a0a15e5..3aa1698 100644
--- a/webrtc/modules/audio_device/linux/audio_device_pulse_linux.h
+++ b/webrtc/modules/audio_device/linux/audio_device_pulse_linux.h
@@ -103,7 +103,7 @@
         AudioDeviceModule::AudioLayer& audioLayer) const override;
 
     // Main initializaton and termination
-    int32_t Init() override;
+    InitStatus Init() override;
     int32_t Terminate() override;
     bool Initialized() const override;
 
diff --git a/webrtc/modules/audio_device/mac/audio_device_mac.cc b/webrtc/modules/audio_device/mac/audio_device_mac.cc
index 0f33d11..70236b8 100644
--- a/webrtc/modules/audio_device/mac/audio_device_mac.cc
+++ b/webrtc/modules/audio_device/mac/audio_device_mac.cc
@@ -10,6 +10,7 @@
 
 #include "webrtc/base/arraysize.h"
 #include "webrtc/base/checks.h"
+#include "webrtc/base/logging.h"
 #include "webrtc/base/platform_thread.h"
 #include "webrtc/modules/audio_device/audio_device_config.h"
 #include "webrtc/modules/audio_device/mac/audio_device_mac.h"
@@ -221,11 +222,11 @@
   return 0;
 }
 
-int32_t AudioDeviceMac::Init() {
+AudioDeviceGeneric::InitStatus AudioDeviceMac::Init() {
   CriticalSectionScoped lock(&_critSect);
 
   if (_initialized) {
-    return 0;
+    return InitStatus::OK;
   }
 
   OSStatus err = noErr;
@@ -250,7 +251,7 @@
     if (bufSize == -1) {
       WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id,
                    " PaUtil_InitializeRingBuffer() error");
-      return -1;
+      return InitStatus::PLAYOUT_ERROR;
     }
   }
 
@@ -272,7 +273,7 @@
     if (bufSize == -1) {
       WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id,
                    " PaUtil_InitializeRingBuffer() error");
-      return -1;
+      return InitStatus::RECORDING_ERROR;
     }
   }
 
@@ -282,7 +283,7 @@
   if (kernErr != KERN_SUCCESS) {
     WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id,
                  " semaphore_create() error: %d", kernErr);
-    return -1;
+    return InitStatus::OTHER_ERROR;
   }
 
   kernErr = semaphore_create(mach_task_self(), &_captureSemaphore,
@@ -290,7 +291,7 @@
   if (kernErr != KERN_SUCCESS) {
     WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id,
                  " semaphore_create() error: %d", kernErr);
-    return -1;
+    return InitStatus::OTHER_ERROR;
   }
 
   // Setting RunLoop to NULL here instructs HAL to manage its own thread for
@@ -302,8 +303,13 @@
       kAudioObjectPropertyElementMaster};
   CFRunLoopRef runLoop = NULL;
   UInt32 size = sizeof(CFRunLoopRef);
-  WEBRTC_CA_RETURN_ON_ERR(AudioObjectSetPropertyData(
-      kAudioObjectSystemObject, &propertyAddress, 0, NULL, size, &runLoop));
+  int aoerr = AudioObjectSetPropertyData(
+      kAudioObjectSystemObject, &propertyAddress, 0, NULL, size, &runLoop);
+  if (aoerr != noErr) {
+    LOG(LS_ERROR) << "Error in AudioObjectSetPropertyData: "
+                  << (const char*)&aoerr;
+    return InitStatus::OTHER_ERROR;
+  }
 
   // Listen for any device changes.
   propertyAddress.mSelector = kAudioHardwarePropertyDevices;
@@ -338,7 +344,7 @@
 
   _initialized = true;
 
-  return 0;
+  return InitStatus::OK;
 }
 
 int32_t AudioDeviceMac::Terminate() {
diff --git a/webrtc/modules/audio_device/mac/audio_device_mac.h b/webrtc/modules/audio_device/mac/audio_device_mac.h
index 102c67e..ccde6f0 100644
--- a/webrtc/modules/audio_device/mac/audio_device_mac.h
+++ b/webrtc/modules/audio_device/mac/audio_device_mac.h
@@ -68,7 +68,7 @@
       AudioDeviceModule::AudioLayer& audioLayer) const;
 
   // Main initializaton and termination
-  virtual int32_t Init();
+  virtual InitStatus Init();
   virtual int32_t Terminate();
   virtual bool Initialized() const;
 
diff --git a/webrtc/modules/audio_device/win/audio_device_core_win.cc b/webrtc/modules/audio_device/win/audio_device_core_win.cc
index 811a04d..0c2d890 100644
--- a/webrtc/modules/audio_device/win/audio_device_core_win.cc
+++ b/webrtc/modules/audio_device/win/audio_device_core_win.cc
@@ -35,6 +35,7 @@
 #include <strsafe.h>
 #include <uuids.h>
 
+#include "webrtc/base/logging.h"
 #include "webrtc/base/platform_thread.h"
 #include "webrtc/system_wrappers/include/sleep.h"
 #include "webrtc/system_wrappers/include/trace.h"
@@ -333,7 +334,9 @@
         int temp_ok(0);
         bool available(false);
 
-        ok |= p->Init();
+        if (p->Init() != InitStatus::OK) {
+          ok |= -1;
+        }
 
         int16_t numDevsRec = p->RecordingDevices();
         for (uint16_t i = 0; i < numDevsRec; i++)
@@ -675,31 +678,27 @@
 //  Init
 // ----------------------------------------------------------------------------
 
-int32_t AudioDeviceWindowsCore::Init()
-{
+AudioDeviceGeneric::InitStatus AudioDeviceWindowsCore::Init() {
+  CriticalSectionScoped lock(&_critSect);
 
-    CriticalSectionScoped lock(&_critSect);
+  if (_initialized) {
+    return InitStatus::OK;
+  }
 
-    if (_initialized)
-    {
-        return 0;
-    }
+  _playWarning = 0;
+  _playError = 0;
+  _recWarning = 0;
+  _recError = 0;
 
-    _playWarning = 0;
-    _playError = 0;
-    _recWarning = 0;
-    _recError = 0;
+  // Enumerate all audio rendering and capturing endpoint devices.
+  // Note that, some of these will not be able to select by the user.
+  // The complete collection is for internal use only.
+  _EnumerateEndpointDevicesAll(eRender);
+  _EnumerateEndpointDevicesAll(eCapture);
 
-    // Enumerate all audio rendering and capturing endpoint devices.
-    // Note that, some of these will not be able to select by the user.
-    // The complete collection is for internal use only.
-    //
-    _EnumerateEndpointDevicesAll(eRender);
-    _EnumerateEndpointDevicesAll(eCapture);
+  _initialized = true;
 
-    _initialized = true;
-
-    return 0;
+  return InitStatus::OK;
 }
 
 // ----------------------------------------------------------------------------
diff --git a/webrtc/modules/audio_device/win/audio_device_core_win.h b/webrtc/modules/audio_device/win/audio_device_core_win.h
index 5c94cfd..b86606a 100644
--- a/webrtc/modules/audio_device/win/audio_device_core_win.h
+++ b/webrtc/modules/audio_device/win/audio_device_core_win.h
@@ -91,7 +91,7 @@
     virtual int32_t ActiveAudioLayer(AudioDeviceModule::AudioLayer& audioLayer) const;
 
     // Main initializaton and termination
-    virtual int32_t Init();
+    virtual InitStatus Init();
     virtual int32_t Terminate();
     virtual bool Initialized() const;
 
diff --git a/webrtc/modules/audio_device/win/audio_device_wave_win.cc b/webrtc/modules/audio_device/win/audio_device_wave_win.cc
index c149708..7874575 100644
--- a/webrtc/modules/audio_device/win/audio_device_wave_win.cc
+++ b/webrtc/modules/audio_device/win/audio_device_wave_win.cc
@@ -8,6 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include "webrtc/base/logging.h"
 #include "webrtc/base/timeutils.h"
 #include "webrtc/modules/audio_device/audio_device_config.h"
 #include "webrtc/modules/audio_device/win/audio_device_wave_win.h"
@@ -196,79 +197,69 @@
 //  Init
 // ----------------------------------------------------------------------------
 
-int32_t AudioDeviceWindowsWave::Init()
-{
+AudioDeviceGeneric::InitStatus AudioDeviceWindowsWave::Init() {
+  CriticalSectionScoped lock(&_critSect);
 
-    CriticalSectionScoped lock(&_critSect);
+  if (_initialized) {
+    return InitStatus::OK;
+  }
 
-    if (_initialized)
-    {
-        return 0;
-    }
+  const uint32_t nowTime(rtc::TimeMillis());
 
-    const uint32_t nowTime(rtc::TimeMillis());
+  _recordedBytes = 0;
+  _prevRecByteCheckTime = nowTime;
+  _prevRecTime = nowTime;
+  _prevPlayTime = nowTime;
+  _prevTimerCheckTime = nowTime;
 
-    _recordedBytes = 0;
-    _prevRecByteCheckTime = nowTime;
-    _prevRecTime = nowTime;
-    _prevPlayTime = nowTime;
-    _prevTimerCheckTime = nowTime;
+  _playWarning = 0;
+  _playError = 0;
+  _recWarning = 0;
+  _recError = 0;
 
-    _playWarning = 0;
-    _playError = 0;
-    _recWarning = 0;
-    _recError = 0;
+  _mixerManager.EnumerateAll();
 
-    _mixerManager.EnumerateAll();
+  if (_ptrThread) {
+    // thread is already created and active
+    return InitStatus::OK;
+  }
 
-    if (_ptrThread)
-    {
-        // thread is already created and active
-        return 0;
-    }
+  const char* threadName = "webrtc_audio_module_thread";
+  _ptrThread.reset(new rtc::PlatformThread(ThreadFunc, this, threadName));
+  _ptrThread->Start();
+  _ptrThread->SetPriority(rtc::kRealtimePriority);
 
-    const char* threadName = "webrtc_audio_module_thread";
-    _ptrThread.reset(new rtc::PlatformThread(ThreadFunc, this, threadName));
-    _ptrThread->Start();
-    _ptrThread->SetPriority(rtc::kRealtimePriority);
+  const bool periodic(true);
+  if (!_timeEvent.StartTimer(periodic, TIMER_PERIOD_MS)) {
+    LOG(LS_ERROR) << "failed to start the timer event";
+    _ptrThread->Stop();
+    _ptrThread.reset();
+    return InitStatus::OTHER_ERROR;
+  }
+  WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
+               "periodic timer (dT=%d) is now active", TIMER_PERIOD_MS);
 
-    const bool periodic(true);
-    if (!_timeEvent.StartTimer(periodic, TIMER_PERIOD_MS))
-    {
-        WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id,
-                     "failed to start the timer event");
-        _ptrThread->Stop();
-        _ptrThread.reset();
-        return -1;
-    }
-    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
-                 "periodic timer (dT=%d) is now active", TIMER_PERIOD_MS);
+  _hGetCaptureVolumeThread =
+      CreateThread(NULL, 0, GetCaptureVolumeThread, this, 0, NULL);
+  if (_hGetCaptureVolumeThread == NULL) {
+    LOG(LS_ERROR) << "  failed to create the volume getter thread";
+    return InitStatus::OTHER_ERROR;
+  }
 
-    _hGetCaptureVolumeThread =
-        CreateThread(NULL, 0, GetCaptureVolumeThread, this, 0, NULL);
-    if (_hGetCaptureVolumeThread == NULL)
-    {
-        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
-            "  failed to create the volume getter thread");
-        return -1;
-    }
+  SetThreadPriority(_hGetCaptureVolumeThread, THREAD_PRIORITY_NORMAL);
 
-    SetThreadPriority(_hGetCaptureVolumeThread, THREAD_PRIORITY_NORMAL);
+  _hSetCaptureVolumeThread =
+      CreateThread(NULL, 0, SetCaptureVolumeThread, this, 0, NULL);
+  if (_hSetCaptureVolumeThread == NULL) {
+    LOG(LS_ERROR) << "  failed to create the volume setter thread";
+    return InitStatus::OTHER_ERROR;
+  }
 
-    _hSetCaptureVolumeThread =
-        CreateThread(NULL, 0, SetCaptureVolumeThread, this, 0, NULL);
-    if (_hSetCaptureVolumeThread == NULL)
-    {
-        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
-            "  failed to create the volume setter thread");
-        return -1;
-    }
+  SetThreadPriority(_hSetCaptureVolumeThread, THREAD_PRIORITY_NORMAL);
 
-    SetThreadPriority(_hSetCaptureVolumeThread, THREAD_PRIORITY_NORMAL);
+  _initialized = true;
 
-    _initialized = true;
-
-    return 0;
+  return InitStatus::OK;
 }
 
 // ----------------------------------------------------------------------------
diff --git a/webrtc/modules/audio_device/win/audio_device_wave_win.h b/webrtc/modules/audio_device/win/audio_device_wave_win.h
index 402d575..6bb7c17 100644
--- a/webrtc/modules/audio_device/win/audio_device_wave_win.h
+++ b/webrtc/modules/audio_device/win/audio_device_wave_win.h
@@ -50,7 +50,7 @@
     virtual int32_t ActiveAudioLayer(AudioDeviceModule::AudioLayer& audioLayer) const;
 
     // Main initializaton and termination
-    virtual int32_t Init();
+    virtual InitStatus Init();
     virtual int32_t Terminate();
     virtual bool Initialized() const;
 
diff --git a/webrtc/system_wrappers/include/metrics.h b/webrtc/system_wrappers/include/metrics.h
index d5e5492..0fee344 100644
--- a/webrtc/system_wrappers/include/metrics.h
+++ b/webrtc/system_wrappers/include/metrics.h
@@ -125,6 +125,14 @@
 #define RTC_LOGGED_HISTOGRAM_PERCENTAGE(name, sample) \
   RTC_LOGGED_HISTOGRAM_ENUMERATION(name, sample, 101)
 
+// Histogram for booleans.
+#define RTC_HISTOGRAM_BOOLEAN(name, sample) \
+  RTC_HISTOGRAM_ENUMERATION(name, sample, 2)
+
+// RTC_HISTOGRAM_BOOLEAN with logging.
+#define RTC_LOGGED_HISTOGRAM_BOOLEAN(name, sample) \
+  RTC_LOGGED_HISTOGRAM_ENUMERATION(name, sample, 2)
+
 // Histogram for enumerators (evenly spaced buckets).
 // |boundary| should be above the max enumerator sample.
 #define RTC_HISTOGRAM_ENUMERATION(name, sample, boundary) \