Bug 796300 - Final version: Set audio device BLUETOOTH_SCO_HEADSET to unavailable when disconnect Sco socket, r=qdot
authorGina Yeh <gyeh@mozilla.com>
Wed, 03 Oct 2012 10:55:28 +0800
changeset 109102 a2756948142d25f95ae71e47a17f46a3629022cc
parent 109101 56e8259f189b772a7f1315e7f8f7c2f1e3500da6
child 109103 a742bf08f125941501a1097ba2a63a5be39cda52
push id82
push usershu@rfrn.org
push dateFri, 05 Oct 2012 13:20:22 +0000
reviewersqdot
bugs796300
milestone18.0a1
Bug 796300 - Final version: Set audio device BLUETOOTH_SCO_HEADSET to unavailable when disconnect Sco socket, r=qdot
dom/bluetooth/BluetoothHfpManager.cpp
dom/bluetooth/linux/BluetoothDBusService.cpp
dom/system/gonk/AudioManager.cpp
hal/HalTypes.h
--- a/dom/bluetooth/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/BluetoothHfpManager.cpp
@@ -11,26 +11,28 @@
 #include "BluetoothReplyRunnable.h"
 #include "BluetoothScoManager.h"
 #include "BluetoothService.h"
 #include "BluetoothServiceUuid.h"
 
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
 #include "mozilla/Services.h"
 #include "nsContentUtils.h"
+#include "nsIAudioManager.h"
 #include "nsIObserverService.h"
 #include "nsIRadioInterfaceLayer.h"
 #include "nsISystemMessagesInternal.h"
 #include "BluetoothUtils.h"
 
 #include "nsVariant.h"
 
 #include <unistd.h> /* usleep() */
 
 #define MOZSETTINGS_CHANGED_ID "mozsettings-changed"
+#define BLUETOOTH_SCO_STATUS_CHANGED "bluetooth-sco-status-changed"
 #define AUDIO_VOLUME_MASTER "audio.volume.master"
 
 USING_BLUETOOTH_NAMESPACE
 using namespace mozilla::ipc;
 
 static nsRefPtr<BluetoothHfpManager> sInstance = nullptr;
 static nsCOMPtr<nsIThread> sHfpCommandThread;
 static bool sStopSendingRingFlag = true;
@@ -77,24 +79,39 @@ OpenScoSocket(const nsAString& aDevicePa
   }
 }
 
 void
 CloseScoSocket()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
+  nsCOMPtr<nsIAudioManager> am = do_GetService("@mozilla.org/telephony/audiomanager;1");
+  if (!am) {
+    NS_WARNING("Failed to get AudioManager Service!");
+    return;
+  }
+  am->SetForceForUse(am->USE_COMMUNICATION, am->FORCE_NONE);
+
   BluetoothScoManager* sco = BluetoothScoManager::Get();
   if (!sco) {
     NS_WARNING("BluetoothScoManager is not available!");
     return;
   }
 
-  if (sco->GetConnected())
+  if (sco->GetConnected()) {
+    nsCOMPtr<nsIObserverService> obs = do_GetService("@mozilla.org/observer-service;1");
+    if (obs) {
+      if (NS_FAILED(obs->NotifyObservers(nullptr, BLUETOOTH_SCO_STATUS_CHANGED, nullptr))) {
+        NS_WARNING("Failed to notify bluetooth-sco-status-changed observsers!");
+        return;
+      }
+    }
     sco->Disconnect();
+  }
 }
 
 BluetoothHfpManager::BluetoothHfpManager()
   : mCurrentVgs(-1)
   , mCurrentCallIndex(0)
   , mCurrentCallState(nsIRadioInterfaceLayer::CALL_STATE_DISCONNECTED)
 {
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
--- a/dom/bluetooth/linux/BluetoothDBusService.cpp
+++ b/dom/bluetooth/linux/BluetoothDBusService.cpp
@@ -185,16 +185,19 @@ public:
   }
 
   NS_IMETHOD
   Run()
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     nsCOMPtr<nsIAudioManager> am = do_GetService("@mozilla.org/telephony/audiomanager;1");
+    if (!am) {
+      NS_WARNING("Failed to get AudioManager service!");
+    }
     am->SetForceForUse(am->USE_COMMUNICATION, am->FORCE_BT_SCO);
 
     nsCOMPtr<nsIObserverService> obs = do_GetService("@mozilla.org/observer-service;1");
     if (obs) {
       if (NS_FAILED(obs->NotifyObservers(nullptr, BLUETOOTH_SCO_STATUS_CHANGED, mObjectPath.get()))) {
         NS_WARNING("Failed to notify bluetooth-sco-status-changed observsers!");
         return NS_ERROR_FAILURE;
       }
--- a/dom/system/gonk/AudioManager.cpp
+++ b/dom/system/gonk/AudioManager.cpp
@@ -31,17 +31,16 @@ using namespace mozilla;
 #define HEADPHONES_STATUS_CHANGED "headphones-status-changed"
 #define HEADPHONES_STATUS_ON      NS_LITERAL_STRING("on").get()
 #define HEADPHONES_STATUS_OFF     NS_LITERAL_STRING("off").get()
 #define HEADPHONES_STATUS_UNKNOWN NS_LITERAL_STRING("unknown").get()
 #define BLUETOOTH_SCO_STATUS_CHANGED "bluetooth-sco-status-changed"
 
 // A bitwise variable for recording what kind of headset is attached.
 static int sHeadsetState;
-static const char* sDeviceAddress;
 static int kBtSampleRate = 8000;
 
 static bool
 IsFmRadioAudioOn()
 {
   if (static_cast<
       audio_policy_dev_state_t (*) (audio_devices_t, const char *)
       >(AudioSystem::getDeviceConnectionState)) {
@@ -75,20 +74,16 @@ InternalSetAudioRoutesICS(SwitchState aS
   if (aState == SWITCH_STATE_HEADSET) {
     AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_WIRED_HEADSET,
                                           AUDIO_POLICY_DEVICE_STATE_AVAILABLE, "");
     sHeadsetState |= AUDIO_DEVICE_OUT_WIRED_HEADSET;
   } else if (aState == SWITCH_STATE_HEADPHONE) {
     AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
                                           AUDIO_POLICY_DEVICE_STATE_AVAILABLE, "");
     sHeadsetState |= AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
-  } else if (aState == SWITCH_STATE_BLUETOOTH_SCO) {
-    AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
-                                          AUDIO_POLICY_DEVICE_STATE_AVAILABLE, sDeviceAddress);
-    sHeadsetState |= AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
   } else if (aState == SWITCH_STATE_OFF) {
     AudioSystem::setDeviceConnectionState(static_cast<audio_devices_t>(sHeadsetState),
                                           AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, "");
     sHeadsetState = 0;
   }
 
   // The audio volume is not consistent when we plug and unplug the headset.
   // Set the fm volume again here.
@@ -130,22 +125,32 @@ InternalSetAudioRoutes(SwitchState aStat
 }
 
 nsresult
 AudioManager::Observe(nsISupports* aSubject,
                       const char* aTopic,
                       const PRUnichar* aData)
 {
   if (!strcmp(aTopic, BLUETOOTH_SCO_STATUS_CHANGED)) {
-    String8 cmd;
-    cmd.appendFormat("bt_samplerate=%d", kBtSampleRate);
-    AudioSystem::setParameters(0, cmd);
+    if (aData) {
+      String8 cmd;
+      cmd.appendFormat("bt_samplerate=%d", kBtSampleRate);
+      AudioSystem::setParameters(0, cmd);
+      const char* address = NS_ConvertUTF16toUTF8(nsDependentString(aData)).get();
+      AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
+                                            AUDIO_POLICY_DEVICE_STATE_AVAILABLE, address);
+      AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
+                                            AUDIO_POLICY_DEVICE_STATE_AVAILABLE, address);
+    } else {
+      AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
+                                            AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, "");
+      AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
+                                            AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, "");
+    }
 
-    sDeviceAddress = NS_ConvertUTF16toUTF8(nsDependentString(aData)).get();
-    InternalSetAudioRoutes(SwitchState::SWITCH_STATE_BLUETOOTH_SCO);
     return NS_OK;
   }
   return NS_ERROR_UNEXPECTED;
 }
 
 static void
 NotifyHeadphonesStatus(SwitchState aState)
 {
--- a/hal/HalTypes.h
+++ b/hal/HalTypes.h
@@ -57,17 +57,16 @@ enum SwitchDevice {
 };
 
 enum SwitchState {
   SWITCH_STATE_UNKNOWN = -1,
   SWITCH_STATE_ON,
   SWITCH_STATE_OFF,
   SWITCH_STATE_HEADSET,          // Headphone with microphone
   SWITCH_STATE_HEADPHONE,        // without microphone
-  SWITCH_STATE_BLUETOOTH_SCO,
   NUM_SWITCH_STATE
 };
 
 typedef Observer<SwitchEvent> SwitchObserver;
 
 enum ProcessPriority {
   PROCESS_PRIORITY_BACKGROUND,
   PROCESS_PRIORITY_FOREGROUND,