Bug 851046: Patch 5 - Apply BluetoothSocket to BluetoothHfpManager; r=mrbkap
authorEric Chou <echou@mozilla.com>
Thu, 04 Apr 2013 17:54:22 -0700
changeset 127744 4530d1c784f36d12cb9de3e0631d56eb4c1bd243
parent 127743 a7a3e3a4e53450fc2c98983368fbf98650cacbc7
child 127745 1d5a3e86a843e9bcf3512364c9203420a3ed8ebc
push id24512
push userryanvm@gmail.com
push dateFri, 05 Apr 2013 20:13:49 +0000
treeherdermozilla-central@139b6ba547fa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmrbkap
bugs851046
milestone23.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 851046: Patch 5 - Apply BluetoothSocket to BluetoothHfpManager; r=mrbkap
dom/bluetooth/BluetoothHfpManager.cpp
dom/bluetooth/BluetoothHfpManager.h
dom/bluetooth/linux/BluetoothDBusService.cpp
--- a/dom/bluetooth/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/BluetoothHfpManager.cpp
@@ -6,16 +6,17 @@
 
 #include "base/basictypes.h"
 
 #include "BluetoothHfpManager.h"
 
 #include "BluetoothReplyRunnable.h"
 #include "BluetoothScoManager.h"
 #include "BluetoothService.h"
+#include "BluetoothSocket.h"
 #include "BluetoothUtils.h"
 #include "BluetoothUuid.h"
 
 #include "MobileConnection.h"
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
 #include "mozilla/Hal.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
@@ -34,27 +35,29 @@
 /**
  * These constants are used in result code such as +CLIP and +CCWA. The value
  * of these constants is the same as TOA_INTERNATIONAL/TOA_UNKNOWN defined in
  * ril_consts.js
  */
 #define TOA_UNKNOWN 0x81
 #define TOA_INTERNATIONAL 0x91
 
+#define CR_LF "\xd\xa";
+
 using namespace mozilla;
 using namespace mozilla::ipc;
 USING_BLUETOOTH_NAMESPACE
 
 namespace {
-  StaticRefPtr<BluetoothHfpManager> gBluetoothHfpManager;
+  StaticAutoPtr<BluetoothHfpManager> gBluetoothHfpManager;
   StaticRefPtr<BluetoothHfpManagerObserver> sHfpObserver;
   bool gInShutdown = false;
   static bool sStopSendingRingFlag = true;
-
   static int sRingInterval = 3000; //unit: ms
+  static const char kHfpCrlf[] = "\xd\xa";
 } // anonymous namespace
 
 /* CallState for sCINDItems[CINDType::CALL].value
  * - NO_CALL: there are no calls in progress
  * - IN_PROGRESS: at least one call is in progress
  */
 enum CallState {
   NO_CALL,
@@ -255,17 +258,17 @@ BluetoothHfpManagerObserver::Observe(nsI
   }
 
   MOZ_ASSERT(false, "BluetoothHfpManager got unexpected topic!");
   return NS_ERROR_UNEXPECTED;
 }
 
 NS_IMPL_ISUPPORTS1(BluetoothHfpManagerObserver, nsIObserver)
 
-class SendRingIndicatorTask : public Task
+class BluetoothHfpManager::SendRingIndicatorTask : public Task
 {
 public:
   SendRingIndicatorTask(const nsAString& aNumber, int aType)
     : mNumber(aNumber)
     , mType(aType)
   {
     MOZ_ASSERT(NS_IsMainThread());
   }
@@ -279,30 +282,29 @@ public:
       return;
     }
 
     if (!gBluetoothHfpManager) {
       NS_WARNING("BluetoothHfpManager no longer exists, cannot send ring!");
       return;
     }
 
-    const char* kHfpCrlf = "\xd\xa";
     nsAutoCString ringMsg(kHfpCrlf);
-    ringMsg += "RING";
-    ringMsg += kHfpCrlf;
-    gBluetoothHfpManager->SendSocketData(ringMsg);
+    ringMsg.AppendLiteral("RING");
+    ringMsg.AppendLiteral(kHfpCrlf);
+    gBluetoothHfpManager->SendLine(ringMsg.get());
 
     if (!mNumber.IsEmpty()) {
       nsAutoCString clipMsg(kHfpCrlf);
-      clipMsg += "+CLIP: \"";
-      clipMsg += NS_ConvertUTF16toUTF8(mNumber).get();
-      clipMsg += "\",";
+      clipMsg.AppendLiteral("+CLIP: \"");
+      clipMsg.Append(NS_ConvertUTF16toUTF8(mNumber).get());
+      clipMsg.AppendLiteral("\",");
       clipMsg.AppendInt(mType);
-      clipMsg += kHfpCrlf;
-      gBluetoothHfpManager->SendSocketData(clipMsg);
+      clipMsg.AppendLiteral(kHfpCrlf);
+      gBluetoothHfpManager->SendLine(clipMsg.get());
     }
 
     MessageLoop::current()->
       PostDelayedTask(FROM_HERE,
                       new SendRingIndicatorTask(mNumber, mType),
                       sRingInterval);
   }
 
@@ -386,17 +388,21 @@ BluetoothHfpManager::Reset()
   ResetCallArray();
 }
 
 bool
 BluetoothHfpManager::Init()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  mSocketStatus = GetConnectionStatus();
+  mSocket = new BluetoothSocket(this,
+                                BluetoothSocketType::RFCOMM,
+                                true,
+                                true);
+  mSocketStatus = mSocket->GetConnectionStatus();
 
   sHfpObserver = new BluetoothHfpManagerObserver();
   if (!sHfpObserver->Init()) {
     NS_WARNING("Cannot set up Hfp Observers!");
   }
 
   mListener = new BluetoothTelephonyListener();
   if (!mListener->StartListening()) {
@@ -449,38 +455,35 @@ BluetoothHfpManager::Get()
 
   // If we're in shutdown, don't create a new instance
   if (gInShutdown) {
     NS_WARNING("BluetoothHfpManager can't be created during shutdown");
     return nullptr;
   }
 
   // Create new instance, register, return
-  nsRefPtr<BluetoothHfpManager> manager = new BluetoothHfpManager();
+  BluetoothHfpManager* manager = new BluetoothHfpManager();
   NS_ENSURE_TRUE(manager, nullptr);
-
-  if (!manager->Init()) {
-    return nullptr;
-  }
+  NS_ENSURE_TRUE(manager->Init(), nullptr);
 
   gBluetoothHfpManager = manager;
   return gBluetoothHfpManager;
 }
 
 void
 BluetoothHfpManager::NotifySettings()
 {
   nsString type, name;
   BluetoothValue v;
   InfallibleTArray<BluetoothNamedValue> parameters;
   type.AssignLiteral("bluetooth-hfp-status-changed");
 
   name.AssignLiteral("connected");
-  v = (GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTED)
-    ? true : false ;
+  v = (mSocket->GetConnectionStatus() ==
+       SocketConnectionStatus::SOCKET_CONNECTED);
   parameters.AppendElement(BluetoothNamedValue(name, v));
 
   name.AssignLiteral("address");
   v = mDevicePath;
   parameters.AppendElement(BluetoothNamedValue(name, v));
 
   if (!BroadcastSystemMessage(type, parameters)) {
     NS_WARNING("Failed to broadcast system message to settings");
@@ -566,17 +569,17 @@ BluetoothHfpManager::HandleVolumeChanged
 
   // Adjust volume by headset and we don't have to send volume back to headset
   if (mReceiveVgsFlag) {
     mReceiveVgsFlag = false;
     return NS_OK;
   }
 
   // Only send volume back when there's a connected headset
-  if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTED) {
+  if (mSocket->GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTED) {
     SendCommand("+VGS: ", mCurrentVgs);
   }
 
   return NS_OK;
 }
 
 nsresult
 BluetoothHfpManager::HandleVoiceConnectionChanged()
@@ -658,17 +661,17 @@ BluetoothHfpManager::HandleIccInfoChange
   return NS_OK;
 }
 
 nsresult
 BluetoothHfpManager::HandleShutdown()
 {
   MOZ_ASSERT(NS_IsMainThread());
   gInShutdown = true;
-  CloseSocket();
+  Disconnect();
   gBluetoothHfpManager = nullptr;
   return NS_OK;
 }
 
 // Virtual function of class SocketConsumer
 void
 BluetoothHfpManager::ReceiveSocketData(nsAutoPtr<UnixSocketRawData>& aMessage)
 {
@@ -737,19 +740,19 @@ BluetoothHfpManager::ReceiveSocketData(n
       } else {
         SendLine("ERROR");
       }
       return;
     }
   } else if (msg.Find("AT+COPS?") != -1) {
     nsAutoCString message("+COPS: ");
     message.AppendInt(mNetworkSelectionMode);
-    message += ",0,\"";
-    message += NS_ConvertUTF16toUTF8(mOperatorName);
-    message += "\"";
+    message.AppendLiteral(",0,\"");
+    message.Append(NS_ConvertUTF16toUTF8(mOperatorName));
+    message.AppendLiteral("\"");
     SendLine(message.get());
     return;
   } else if (msg.Find("AT+VTS=") != -1) {
     ParseAtCommand(msg, 7, atCommandValues);
 
     if (atCommandValues.Length() != 1) {
       NS_WARNING("Couldn't get the value of command [AT+VTS=]");
       goto respond_with_ok;
@@ -903,20 +906,20 @@ BluetoothHfpManager::ReceiveSocketData(n
         break;
       default:
         NS_WARNING("Not handling state changed");
         break;
     }
   } else if (msg.Find("AT+CNUM") != -1) {
     if (!mMsisdn.IsEmpty()) {
       nsAutoCString message("+CNUM: ,\"");
-      message += NS_ConvertUTF16toUTF8(mMsisdn).get();
-      message += "\",";
+      message.Append(NS_ConvertUTF16toUTF8(mMsisdn).get());
+      message.AppendLiteral("\",");
       message.AppendInt(TOA_UNKNOWN);
-      message += ",,4";
+      message.AppendLiteral(",,4");
       SendLine(message.get());
     }
   } else {
     nsCString warningMsg;
     warningMsg.Append(NS_LITERAL_CSTRING("Unsupported AT command: "));
     warningMsg.Append(msg);
     warningMsg.Append(NS_LITERAL_CSTRING(", reply with ERROR"));
     NS_WARNING(warningMsg.get());
@@ -937,23 +940,25 @@ BluetoothHfpManager::Connect(const nsASt
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (gInShutdown) {
     NS_WARNING("Connect called while in shutdown!");
     return false;
   }
 
-  if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTED ||
-      GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTING) {
-    NS_WARNING("BluetoothHfpManager has connected/is connecting to a headset!");
+  SocketConnectionStatus s = mSocket->GetConnectionStatus();
+
+  if (s == SocketConnectionStatus::SOCKET_CONNECTED ||
+      s == SocketConnectionStatus::SOCKET_CONNECTING) {
+    NS_WARNING("BluetoothHfpManager has been already connected");
     return false;
   }
 
-  CloseSocket();
+  mSocket->Disconnect();
 
   BluetoothService* bs = BluetoothService::Get();
   NS_ENSURE_TRUE(bs, false);
 
   nsString uuid;
   if (aIsHandsfree) {
     BluetoothUuidHelper::GetString(BluetoothServiceClass::HANDSFREE, uuid);
   } else {
@@ -962,76 +967,65 @@ BluetoothHfpManager::Connect(const nsASt
 
   mRunnable = aRunnable;
 
   nsresult rv = bs->GetSocketViaService(aDevicePath,
                                         uuid,
                                         BluetoothSocketType::RFCOMM,
                                         true,
                                         true,
-                                        this,
+                                        mSocket,
                                         mRunnable);
 
   return NS_FAILED(rv) ? false : true;
 }
 
 bool
 BluetoothHfpManager::Listen()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (gInShutdown) {
     MOZ_ASSERT(false, "Listen called while in shutdown!");
     return false;
   }
 
-  if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_LISTENING) {
+  if (mSocket->GetConnectionStatus() ==
+      SocketConnectionStatus::SOCKET_LISTENING) {
     NS_WARNING("BluetoothHfpManager has been already listening");
     return true;
   }
 
-  CloseSocket();
-
-  BluetoothService* bs = BluetoothService::Get();
-  NS_ENSURE_TRUE(bs, false);
+  mSocket->Disconnect();
 
-  nsresult rv =
-    bs->ListenSocketViaService(BluetoothReservedChannels::CHANNEL_HANDSFREE_AG,
-                               BluetoothSocketType::RFCOMM,
-                               true,
-                               true,
-                               this);
+  if (!mSocket->Listen(BluetoothReservedChannels::CHANNEL_HANDSFREE_AG)) {
+    NS_WARNING("[HFP] Can't listen on socket!");
+    return false;
+  }
 
-  mSocketStatus = GetConnectionStatus();
-
-  return NS_FAILED(rv) ? false : true;
+  mSocketStatus = mSocket->GetConnectionStatus();
+  return true;
 }
 
 void
 BluetoothHfpManager::Disconnect()
 {
-  if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_DISCONNECTED) {
-    NS_WARNING("BluetoothHfpManager has been disconnected!");
-    return;
-  }
-
-  CloseSocket();
+  mSocket->Disconnect();
 }
 
 bool
 BluetoothHfpManager::SendLine(const char* aMessage)
 {
-  const char* kHfpCrlf = "\xd\xa";
   nsAutoCString msg;
 
-  msg += kHfpCrlf;
-  msg += aMessage;
-  msg += kHfpCrlf;
+  msg.AppendLiteral(kHfpCrlf);
+  msg.Append(aMessage);
+  msg.AppendLiteral(kHfpCrlf);
 
-  return SendSocketData(msg);
+  return mSocket->SendSocketData(msg);
 }
 
 bool
 BluetoothHfpManager::SendCommand(const char* aCommand, uint8_t aValue)
 {
   if (mSocketStatus != SocketConnectionStatus::SOCKET_CONNECTED) {
     return false;
   }
@@ -1047,57 +1041,57 @@ BluetoothHfpManager::SendCommand(const c
     }
 
     if ((aValue < 1) || (aValue > ArrayLength(sCINDItems) - 1)) {
       NS_WARNING("unexpected CINDType for CIEV command");
       return false;
     }
 
     message.AppendInt(aValue);
-    message += ",";
+    message.AppendLiteral(",");
     message.AppendInt(sCINDItems[aValue].value);
   } else if (!strcmp(aCommand, "+CIND: ")) {
     if (!aValue) {
       // Query for range
       for (uint8_t i = 1; i < ArrayLength(sCINDItems); i++) {
-        message += "(\"";
-        message += sCINDItems[i].name;
-        message += "\",(";
-        message += sCINDItems[i].range;
-        message += ")";
+        message.AppendLiteral("(\"");
+        message.Append(sCINDItems[i].name);
+        message.AppendLiteral("\",(");
+        message.Append(sCINDItems[i].range);
+        message.AppendLiteral(")");
         if (i == (ArrayLength(sCINDItems) - 1)) {
-          message +=")";
+          message.AppendLiteral(")");
           break;
         }
-        message += "),";
+        message.AppendLiteral("),");
       }
     } else {
       // Query for value
       for (uint8_t i = 1; i < ArrayLength(sCINDItems); i++) {
         message.AppendInt(sCINDItems[i].value);
         if (i == (ArrayLength(sCINDItems) - 1)) {
           break;
         }
-        message += ",";
+        message.AppendLiteral(",");
       }
     }
   } else if (!strcmp(aCommand, "+CLCC: ")) {
     bool rv = true;
     uint32_t callNumbers = mCurrentCallArray.Length();
     for (uint32_t i = 1; i < callNumbers; i++) {
       Call& call = mCurrentCallArray[i];
       if (call.mState == nsITelephonyProvider::CALL_STATE_DISCONNECTED) {
         continue;
       }
 
       message.AssignLiteral("+CLCC: ");
       message.AppendInt(i);
-      message += ",";
+      message.AppendLiteral(",");
       message.AppendInt(call.mDirection);
-      message += ",";
+      message.AppendLiteral(",");
 
       switch (call.mState) {
         case nsITelephonyProvider::CALL_STATE_CONNECTED:
           message.AppendInt(0);
           break;
         case nsITelephonyProvider::CALL_STATE_HELD:
           message.AppendInt(1);
           break;
@@ -1109,19 +1103,19 @@ BluetoothHfpManager::SendCommand(const c
           break;
         case nsITelephonyProvider::CALL_STATE_INCOMING:
           message.AppendInt((i == mCurrentCallIndex) ? 4 : 5);
           break;
         default:
           NS_WARNING("Not handling call status for CLCC");
           break;
       }
-      message += ",0,0,\"";
-      message += NS_ConvertUTF16toUTF8(call.mNumber).get();
-      message += "\",";
+      message.AppendLiteral(",0,0,\"");
+      message.Append(NS_ConvertUTF16toUTF8(call.mNumber));
+      message.AppendLiteral("\",");
       message.AppendInt(call.mType);
 
       rv &= SendLine(message.get());
     }
     return rv;
   } else {
     message.AppendInt(value);
   }
@@ -1142,17 +1136,18 @@ BluetoothHfpManager::UpdateCIND(uint8_t 
 }
 
 void
 BluetoothHfpManager::HandleCallStateChanged(uint32_t aCallIndex,
                                             uint16_t aCallState,
                                             const nsAString& aNumber,
                                             bool aSend)
 {
-  if (GetConnectionStatus() != SocketConnectionStatus::SOCKET_CONNECTED) {
+  if (mSocket->GetConnectionStatus() !=
+      SocketConnectionStatus::SOCKET_CONNECTED) {
     return;
   }
 
   while (aCallIndex >= mCurrentCallArray.Length()) {
     Call call;
     mCurrentCallArray.AppendElement(call);
   }
 
@@ -1176,18 +1171,18 @@ BluetoothHfpManager::HandleCallStateChan
       SendCommand("+CIEV: ", CINDType::CALLHELD);
       break;
     case nsITelephonyProvider::CALL_STATE_INCOMING:
       mCurrentCallArray[aCallIndex].mDirection = true;
 
       if (mCurrentCallIndex) {
         if (mCCWA) {
           nsAutoCString ccwaMsg("+CCWA: \"");
-          ccwaMsg += NS_ConvertUTF16toUTF8(aNumber).get();
-          ccwaMsg += "\",";
+          ccwaMsg.Append(NS_ConvertUTF16toUTF8(aNumber));
+          ccwaMsg.AppendLiteral("\",");
           ccwaMsg.AppendInt(mCurrentCallArray[aCallIndex].mType);
           SendLine(ccwaMsg.get());
         }
         UpdateCIND(CINDType::CALLSETUP, CallSetupState::INCOMING, aSend);
       } else {
         // Start sending RING indicator to HF
         sStopSendingRingFlag = false;
         UpdateCIND(CINDType::CALLSETUP, CallSetupState::INCOMING, aSend);
@@ -1201,37 +1196,37 @@ BluetoothHfpManager::HandleCallStateChan
           new SendRingIndicatorTask(number, mCurrentCallArray[aCallIndex].mType),
           sRingInterval);
       }
       break;
     case nsITelephonyProvider::CALL_STATE_DIALING:
       mCurrentCallArray[aCallIndex].mDirection = false;
       UpdateCIND(CINDType::CALLSETUP, CallSetupState::OUTGOING, aSend);
 
-      GetSocketAddr(address);
+      mSocket->GetAddress(address);
       OpenScoSocket(address);
       break;
     case nsITelephonyProvider::CALL_STATE_ALERTING:
       mCurrentCallArray[aCallIndex].mDirection = false;
       UpdateCIND(CINDType::CALLSETUP, CallSetupState::OUTGOING_ALERTING, aSend);
 
       // If there's an ongoing call when the headset is just connected, we have
       // to open a sco socket here.
-      GetSocketAddr(address);
+      mSocket->GetAddress(address);
       OpenScoSocket(address);
       break;
     case nsITelephonyProvider::CALL_STATE_CONNECTED:
       mCurrentCallIndex = aCallIndex;
       switch (prevCallState) {
         case nsITelephonyProvider::CALL_STATE_INCOMING:
         case nsITelephonyProvider::CALL_STATE_DISCONNECTED:
           // Incoming call, no break
           sStopSendingRingFlag = true;
 
-          GetSocketAddr(address);
+          mSocket->GetAddress(address);
           OpenScoSocket(address);
         case nsITelephonyProvider::CALL_STATE_ALERTING:
           // Outgoing call
           UpdateCIND(CINDType::CALL, CallState::IN_PROGRESS, aSend);
           UpdateCIND(CINDType::CALLSETUP, CallSetupState::NO_CALLSETUP, aSend);
           break;
         case nsITelephonyProvider::CALL_STATE_HELD:
           // Check whether to update CINDType::CALLHELD or not
@@ -1323,18 +1318,18 @@ BluetoothHfpManager::OnConnectSuccess()
     nsString errorStr;
     DispatchBluetoothReply(mRunnable, v, errorStr);
 
     mRunnable.forget();
   }
 
   // Cache device path for NotifySettings() since we can't get socket address
   // when a headset disconnect with us
-  GetSocketAddr(mDevicePath);
-  mSocketStatus = GetConnectionStatus();
+  mSocket->GetAddress(mDevicePath);
+  mSocketStatus = mSocket->GetConnectionStatus();
 
   NotifySettings();
 }
 
 void
 BluetoothHfpManager::OnConnectError()
 {
   // For active connection request, we need to reply the DOMRequest
@@ -1343,18 +1338,16 @@ BluetoothHfpManager::OnConnectError()
     nsString errorStr;
     errorStr.AssignLiteral("Failed to connect with a bluetooth headset!");
     DispatchBluetoothReply(mRunnable, v, errorStr);
 
     mRunnable.forget();
   }
 
   // If connecting for some reason didn't work, restart listening
-  CloseSocket();
-  mSocketStatus = GetConnectionStatus();
   Listen();
 }
 
 void
 BluetoothHfpManager::OnDisconnect()
 {
   // When we close a connected socket, then restart listening again and
   // notify Settings app.
@@ -1363,8 +1356,15 @@ BluetoothHfpManager::OnDisconnect()
     NotifySettings();
   } else if (mSocketStatus == SocketConnectionStatus::SOCKET_CONNECTING) {
     NS_WARNING("BluetoothHfpManager got unexpected socket status!");
   }
 
   CloseScoSocket();
   Reset();
 }
+
+bool
+BluetoothHfpManager::IsConnected()
+{
+  return mSocket->GetConnectionStatus() ==
+         SocketConnectionStatus::SOCKET_CONNECTED;
+}
--- a/dom/bluetooth/BluetoothHfpManager.h
+++ b/dom/bluetooth/BluetoothHfpManager.h
@@ -3,24 +3,26 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_bluetooth_bluetoothhfpmanager_h__
 #define mozilla_dom_bluetooth_bluetoothhfpmanager_h__
 
 #include "BluetoothCommon.h"
+#include "BluetoothSocketObserver.h"
 #include "BluetoothTelephonyListener.h"
 #include "mozilla/ipc/UnixSocket.h"
 #include "nsIObserver.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
+class BluetoothHfpManagerObserver;
 class BluetoothReplyRunnable;
-class BluetoothHfpManagerObserver;
+class BluetoothSocket;
 class Call;
 
 /**
  * These costants are defined in 4.33.2 "AT Capabilities Re-Used from GSM 07.07
  * and 3GPP 27.007" in Bluetooth hands-free profile 1.6
  */
 enum BluetoothCmeError {
   AG_FAILURE = 0,
@@ -43,42 +45,50 @@ enum BluetoothCmeError {
   INVALID_CHARACTERS_IN_TEXT_STRING = 25,
   DIAL_STRING_TOO_LONG = 26,
   INVALID_CHARACTERS_IN_DIAL_STRING = 27,
   NO_NETWORK_SERVICE = 30,
   NETWORK_TIMEOUT = 31,
   NETWORK_NOT_ALLOWED = 32
 };
 
-class BluetoothHfpManager : public mozilla::ipc::UnixSocketConsumer
+class BluetoothHfpManager : public BluetoothSocketObserver
 {
 public:
   static BluetoothHfpManager* Get();
-  virtual void ReceiveSocketData(nsAutoPtr<mozilla::ipc::UnixSocketRawData>& aMessage)
-    MOZ_OVERRIDE;
+  ~BluetoothHfpManager();
+
+  virtual void ReceiveSocketData(
+    nsAutoPtr<mozilla::ipc::UnixSocketRawData>& aMessage) MOZ_OVERRIDE;
+  virtual void OnConnectSuccess() MOZ_OVERRIDE;
+  virtual void OnConnectError() MOZ_OVERRIDE;
+  virtual void OnDisconnect() MOZ_OVERRIDE;
 
   bool Connect(const nsAString& aDeviceObjectPath,
                const bool aIsHandsfree,
                BluetoothReplyRunnable* aRunnable);
   void Disconnect();
   bool Listen();
 
   /**
    * @param aSend A boolean indicates whether we need to notify headset or not
    */
   void HandleCallStateChanged(uint32_t aCallIndex, uint16_t aCallState,
                               const nsAString& aNumber, bool aSend);
+  bool IsConnected();
 
 private:
   class GetVolumeTask;
+  class SendRingIndicatorTask;
+
   friend class GetVolumeTask;
+  friend class SendRingIndicatorTask;
   friend class BluetoothHfpManagerObserver;
 
   BluetoothHfpManager();
-  ~BluetoothHfpManager();
   nsresult HandleIccInfoChanged();
   nsresult HandleShutdown();
   nsresult HandleVolumeChanged(const nsAString& aData);
   nsresult HandleVoiceConnectionChanged();
 
   bool Init();
   void Cleanup();
   void Reset();
@@ -86,34 +96,31 @@ private:
 
   void NotifyDialer(const nsAString& aCommand);
   void NotifySettings();
 
   bool SendCommand(const char* aCommand, uint8_t aValue = 0);
   bool SendLine(const char* aMessage);
   void UpdateCIND(uint8_t aType, uint8_t aValue, bool aSend);
 
-  virtual void OnConnectSuccess() MOZ_OVERRIDE;
-  virtual void OnConnectError() MOZ_OVERRIDE;
-  virtual void OnDisconnect() MOZ_OVERRIDE;
-
   int mCurrentVgs;
   int mCurrentVgm;
   uint32_t mCurrentCallIndex;
   bool mCCWA;
   bool mCLIP;
   bool mCMEE;
   bool mCMER;
   int mNetworkSelectionMode;
   bool mReceiveVgsFlag;
   nsString mDevicePath;
   nsString mMsisdn;
   nsString mOperatorName;
-  enum mozilla::ipc::SocketConnectionStatus mSocketStatus;
+  enum SocketConnectionStatus mSocketStatus;
 
   nsTArray<Call> mCurrentCallArray;
   nsAutoPtr<BluetoothTelephonyListener> mListener;
   nsRefPtr<BluetoothReplyRunnable> mRunnable;
+  nsRefPtr<BluetoothSocket> mSocket;
 };
 
 END_BLUETOOTH_NAMESPACE
 
 #endif
--- a/dom/bluetooth/linux/BluetoothDBusService.cpp
+++ b/dom/bluetooth/linux/BluetoothDBusService.cpp
@@ -2542,18 +2542,17 @@ BluetoothDBusService::Disconnect(const u
 bool
 BluetoothDBusService::IsConnected(const uint16_t aProfileId)
 {
   NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!");
 
   if (aProfileId == BluetoothServiceClass::HANDSFREE ||
       aProfileId == BluetoothServiceClass::HEADSET) {
     BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
-    return (hfp->GetConnectionStatus() ==
-            SocketConnectionStatus::SOCKET_CONNECTED);
+    return (hfp->IsConnected());
   } else if (aProfileId == BluetoothServiceClass::OBJECT_PUSH) {
     BluetoothOppManager* opp = BluetoothOppManager::Get();
     return opp->IsTransferring();
   }
 
   return false;
 }