Bug 804460 - Patch 1: Failed to set audio stream volume to correct value by bluetooth headset, r=qdot
authorGina Yeh <gyeh@mozilla.com>
Thu, 25 Oct 2012 18:50:41 +0800
changeset 111504 814a4bca12ebdb4dd017afe264b5440fb2dafba1
parent 111503 e4367fd2043ff9233a9b951cf2ba4f34440d8847
child 111505 04c6d4d7e578e390ee64a17baf07abcf8d75158f
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersqdot
bugs804460
milestone19.0a1
Bug 804460 - Patch 1: Failed to set audio stream volume to correct value by bluetooth headset, r=qdot
dom/bluetooth/BluetoothHfpManager.cpp
dom/bluetooth/BluetoothHfpManager.h
--- a/dom/bluetooth/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/BluetoothHfpManager.cpp
@@ -214,19 +214,19 @@ CloseScoSocket()
   if (!sco) {
     NS_WARNING("BluetoothScoManager is not available!");
     return;
   }
   sco->Disconnect();
 }
 
 BluetoothHfpManager::BluetoothHfpManager()
-  : mCurrentVgs(-1)
-  , mCurrentCallIndex(0)
+  : mCurrentCallIndex(0)
   , mCurrentCallState(nsIRadioInterfaceLayer::CALL_STATE_DISCONNECTED)
+  , mReceiveVgsFlag(false)
 {
   sCINDItems[CINDType::CALL].value = CallState::NO_CALL;
   sCINDItems[CINDType::CALLSETUP].value = CallSetupState::NO_CALLSETUP;
   sCINDItems[CINDType::CALLHELD].value = CallHeldState::NO_CALLHELD;
 }
 
 bool
 BluetoothHfpManager::Init()
@@ -244,16 +244,28 @@ BluetoothHfpManager::Init()
 
   if (!sHfpCommandThread) {
     if (NS_FAILED(NS_NewThread(getter_AddRefs(sHfpCommandThread)))) {
       NS_ERROR("Failed to new thread for sHfpCommandThread");
       return false;
     }
   }
 
+  float volume;
+  nsCOMPtr<nsIAudioManager> am = do_GetService("@mozilla.org/telephony/audiomanager;1");
+  if (!am) {
+    NS_WARNING("Failed to get AudioManager Service!");
+    return false;
+  }
+  am->GetMasterVolume(&volume);
+
+  // AG volume range: [0.0, 1.0]
+  // HS volume range: [0, 15]
+  mCurrentVgs = floor(volume * 15);
+
   return true;
 }
 
 BluetoothHfpManager::~BluetoothHfpManager()
 {
   Cleanup();
 }
 
@@ -349,20 +361,16 @@ BluetoothHfpManager::NotifyDialer(const 
   }
 }
 
 nsresult
 BluetoothHfpManager::HandleVolumeChanged(const nsAString& aData)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  if (GetConnectionStatus() != SocketConnectionStatus::SOCKET_CONNECTED) {
-    return NS_OK;
-  }
-
   // The string that we're interested in will be a JSON string that looks like:
   //  {"key":"volumeup", "value":1.0}
   //  {"key":"volumedown", "value":0.2}
 
   JSContext* cx = nsContentUtils::GetSafeJSContext();
   if (!cx) {
     return NS_OK;
   }
@@ -406,17 +414,26 @@ BluetoothHfpManager::HandleVolumeChanged
 
   if (!value.isNumber()) {
     return NS_ERROR_UNEXPECTED;
   }
 
   // AG volume range: [0.0, 1.0]
   // HS volume range: [0, 15]
   float volume = value.toNumber();
-  mCurrentVgs = ceil(volume * 15);
+  mCurrentVgs = floor(volume * 15);
+
+  if (mReceiveVgsFlag) {
+    mReceiveVgsFlag = false;
+    return NS_OK;
+  }
+
+  if (GetConnectionStatus() != SocketConnectionStatus::SOCKET_CONNECTED) {
+    return NS_OK;
+  }
 
   SendCommand("+VGS: ", mCurrentVgs);
 
   return NS_OK;
 }
 
 nsresult
 BluetoothHfpManager::HandleShutdown()
@@ -453,40 +470,44 @@ BluetoothHfpManager::ReceiveSocketData(U
     // SLC establishment
     SendLine("OK");
   } else if (!strncmp(msg, "AT+CHLD=?", 9)) {
     SendLine("+CHLD: (0,1,2,3)");
     SendLine("OK");
   } else if (!strncmp(msg, "AT+CHLD=", 8)) {
     SendLine("OK");
   } else if (!strncmp(msg, "AT+VGS=", 7)) {
-    // HS volume range: [0, 15]
-    int newVgs = msg[7] - '0';
+    mReceiveVgsFlag = true;
+
+    int length = strlen(msg) - 8;
+    nsAutoCString vgsString(nsDependentCSubstring(msg+7, length));
 
-    if (strlen(msg) > 8) {
-      newVgs *= 10;
-      newVgs += (msg[8] - '0');
+    nsresult rv;
+    int newVgs = vgsString.ToInteger(&rv);
+    if (NS_FAILED(rv)) {
+      NS_WARNING("Failed to extract volume value from bluetooth headset!");
+    }
+
+    if (newVgs == mCurrentVgs) {
+      SendLine("OK");
+      return;
     }
 
 #ifdef DEBUG
     NS_ASSERTION(newVgs >= 0 && newVgs <= 15, "Received invalid VGS value");
 #endif
 
-    // Currently, we send volume up/down commands to represent that
-    // volume has been changed by Bluetooth headset, and that will affect
-    // the main stream volume of our device. In the future, we may want to
-    // be able to set volume by stream.
+    // HS volume range: [0, 15]
+    // sound_manager volume range: [0, 10]
+    nsString data;
+    int volume;
     nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
-    if (newVgs > mCurrentVgs) {
-      os->NotifyObservers(nullptr, "bluetooth-volume-change", NS_LITERAL_STRING("up").get());
-    } else if (newVgs < mCurrentVgs) {
-      os->NotifyObservers(nullptr, "bluetooth-volume-change", NS_LITERAL_STRING("down").get());
-    }
-
-    mCurrentVgs = newVgs;
+    volume = ceil((float)newVgs / 15.0 * 10.0);
+    data.AppendInt(volume);
+    os->NotifyObservers(nullptr, "bluetooth-volume-change", data.get());
 
     SendLine("OK");
   } else if (!strncmp(msg, "AT+BLDN", 7)) {
     NotifyDialer(NS_LITERAL_STRING("BLDN"));
     SendLine("OK");
   } else if (!strncmp(msg, "ATA", 3)) {
     NotifyDialer(NS_LITERAL_STRING("ATA"));
     SendLine("OK");
--- a/dom/bluetooth/BluetoothHfpManager.h
+++ b/dom/bluetooth/BluetoothHfpManager.h
@@ -48,14 +48,15 @@ private:
   void NotifySettings();
   virtual void OnConnectSuccess() MOZ_OVERRIDE;
   virtual void OnConnectError() MOZ_OVERRIDE;
   virtual void OnDisconnect() MOZ_OVERRIDE;
 
   int mCurrentVgs;
   int mCurrentCallIndex;
   int mCurrentCallState;
+  bool mReceiveVgsFlag;
   nsAutoPtr<BluetoothRilListener> mListener;
 };
 
 END_BLUETOOTH_NAMESPACE
 
 #endif