AudioDeviceMac: fix mutex re-entry.

This change fixes two cases of encountered mutex re-entries.

Bug: webrtc:11821
Change-Id: Iaef730e4233a79b0d1b2bf6a17fe3f14e2558e98
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/180800
Reviewed-by: Henrik Andreassson <henrika@webrtc.org>
Commit-Queue: Markus Handell <handellm@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#31831}
diff --git a/modules/audio_device/mac/audio_device_mac.cc b/modules/audio_device/mac/audio_device_mac.cc
index 7a35c8e..0c6e9f5 100644
--- a/modules/audio_device/mac/audio_device_mac.cc
+++ b/modules/audio_device/mac/audio_device_mac.cc
@@ -382,12 +382,17 @@
 }
 
 int32_t AudioDeviceMac::SpeakerIsAvailable(bool& available) {
+  MutexLock lock(&mutex_);
+  return SpeakerIsAvailableLocked(available);
+}
+
+int32_t AudioDeviceMac::SpeakerIsAvailableLocked(bool& available) {
   bool wasInitialized = _mixerManager.SpeakerIsInitialized();
 
   // Make an attempt to open up the
   // output mixer corresponding to the currently selected output device.
   //
-  if (!wasInitialized && InitSpeaker() == -1) {
+  if (!wasInitialized && InitSpeakerLocked() == -1) {
     available = false;
     return 0;
   }
@@ -433,12 +438,17 @@
 }
 
 int32_t AudioDeviceMac::MicrophoneIsAvailable(bool& available) {
+  MutexLock lock(&mutex_);
+  return MicrophoneIsAvailableLocked(available);
+}
+
+int32_t AudioDeviceMac::MicrophoneIsAvailableLocked(bool& available) {
   bool wasInitialized = _mixerManager.MicrophoneIsInitialized();
 
   // Make an attempt to open up the
   // input mixer corresponding to the currently selected output device.
   //
-  if (!wasInitialized && InitMicrophone() == -1) {
+  if (!wasInitialized && InitMicrophoneLocked() == -1) {
     available = false;
     return 0;
   }
@@ -971,7 +981,7 @@
     // Make this call to check if we are using
     // one or two devices (_twoDevices)
     bool available = false;
-    if (MicrophoneIsAvailable(available) == -1) {
+    if (MicrophoneIsAvailableLocked(available) == -1) {
       RTC_LOG(LS_WARNING) << "MicrophoneIsAvailable() failed";
     }
   }
@@ -1109,7 +1119,7 @@
     // Make this call to check if we are using
     // one or two devices (_twoDevices)
     bool available = false;
-    if (SpeakerIsAvailable(available) == -1) {
+    if (SpeakerIsAvailableLocked(available) == -1) {
       RTC_LOG(LS_WARNING) << "SpeakerIsAvailable() failed";
     }
   }
diff --git a/modules/audio_device/mac/audio_device_mac.h b/modules/audio_device/mac/audio_device_mac.h
index 4fcd3b0..985db9d 100644
--- a/modules/audio_device/mac/audio_device_mac.h
+++ b/modules/audio_device/mac/audio_device_mac.h
@@ -113,31 +113,36 @@
   virtual bool MicrophoneIsInitialized() const;
 
   // Speaker volume controls
-  virtual int32_t SpeakerVolumeIsAvailable(bool& available);
+  virtual int32_t SpeakerVolumeIsAvailable(bool& available)
+      RTC_LOCKS_EXCLUDED(mutex_);
   virtual int32_t SetSpeakerVolume(uint32_t volume);
   virtual int32_t SpeakerVolume(uint32_t& volume) const;
   virtual int32_t MaxSpeakerVolume(uint32_t& maxVolume) const;
   virtual int32_t MinSpeakerVolume(uint32_t& minVolume) const;
 
   // Microphone volume controls
-  virtual int32_t MicrophoneVolumeIsAvailable(bool& available);
+  virtual int32_t MicrophoneVolumeIsAvailable(bool& available)
+      RTC_LOCKS_EXCLUDED(mutex_);
   virtual int32_t SetMicrophoneVolume(uint32_t volume);
   virtual int32_t MicrophoneVolume(uint32_t& volume) const;
   virtual int32_t MaxMicrophoneVolume(uint32_t& maxVolume) const;
   virtual int32_t MinMicrophoneVolume(uint32_t& minVolume) const;
 
   // Microphone mute control
-  virtual int32_t MicrophoneMuteIsAvailable(bool& available);
+  virtual int32_t MicrophoneMuteIsAvailable(bool& available)
+      RTC_LOCKS_EXCLUDED(mutex_);
   virtual int32_t SetMicrophoneMute(bool enable);
   virtual int32_t MicrophoneMute(bool& enabled) const;
 
   // Speaker mute control
-  virtual int32_t SpeakerMuteIsAvailable(bool& available);
+  virtual int32_t SpeakerMuteIsAvailable(bool& available)
+      RTC_LOCKS_EXCLUDED(mutex_);
   virtual int32_t SetSpeakerMute(bool enable);
   virtual int32_t SpeakerMute(bool& enabled) const;
 
   // Stereo support
-  virtual int32_t StereoPlayoutIsAvailable(bool& available);
+  virtual int32_t StereoPlayoutIsAvailable(bool& available)
+      RTC_LOCKS_EXCLUDED(mutex_);
   virtual int32_t SetStereoPlayout(bool enable);
   virtual int32_t StereoPlayout(bool& enabled) const;
   virtual int32_t StereoRecordingIsAvailable(bool& available);
@@ -154,8 +159,14 @@
   int32_t InitSpeakerLocked() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
   int32_t InitMicrophoneLocked() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
 
-  virtual int32_t MicrophoneIsAvailable(bool& available);
-  virtual int32_t SpeakerIsAvailable(bool& available);
+  virtual int32_t MicrophoneIsAvailable(bool& available)
+      RTC_LOCKS_EXCLUDED(mutex_);
+  virtual int32_t MicrophoneIsAvailableLocked(bool& available)
+      RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+  virtual int32_t SpeakerIsAvailable(bool& available)
+      RTC_LOCKS_EXCLUDED(mutex_);
+  virtual int32_t SpeakerIsAvailableLocked(bool& available)
+      RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
 
   static void AtomicSet32(int32_t* theValue, int32_t newValue);
   static int32_t AtomicGet32(int32_t* theValue);