Back out bug 851046 because of rebase problems
authorMatt Brubeck <mbrubeck@mozilla.com>
Thu, 04 Apr 2013 17:45:06 -0700
changeset 127734 03a6b2be2d610ff22b75194d0abe335507b716f2
parent 127733 ca34eba9c8b630ede0c9eb62fa7717c3df7c06a8
child 127735 2418deea4b19e48fb1f5f5ef5402563c3d428501
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)
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
Back out bug 851046 because of rebase problems
dom/bluetooth/BluetoothCommon.h
dom/bluetooth/BluetoothHfpManager.cpp
dom/bluetooth/BluetoothHfpManager.h
dom/bluetooth/BluetoothOppManager.cpp
dom/bluetooth/BluetoothOppManager.h
dom/bluetooth/BluetoothScoManager.cpp
dom/bluetooth/BluetoothScoManager.h
dom/bluetooth/BluetoothService.h
dom/bluetooth/BluetoothSocket.cpp
dom/bluetooth/BluetoothSocket.h
dom/bluetooth/BluetoothSocketObserver.h
dom/bluetooth/Makefile.in
dom/bluetooth/ipc/BluetoothServiceChildProcess.cpp
dom/bluetooth/ipc/BluetoothServiceChildProcess.h
dom/bluetooth/linux/BluetoothDBusService.cpp
dom/bluetooth/linux/BluetoothDBusService.h
ipc/unixsocket/UnixSocket.h
--- a/dom/bluetooth/BluetoothCommon.h
+++ b/dom/bluetooth/BluetoothCommon.h
@@ -48,17 +48,16 @@ extern bool gBluetoothDebugFlag;
 
 #define KEY_LOCAL_AGENT  "/B2G/bluetooth/agent"
 #define KEY_REMOTE_AGENT "/B2G/bluetooth/remote_device_agent"
 #define KEY_MANAGER      "/B2G/bluetooth/manager"
 #define KEY_ADAPTER      "/B2G/bluetooth/adapter"
 
 // Bluetooth address format: xx:xx:xx:xx:xx:xx (or xx_xx_xx_xx_xx_xx)
 #define BLUETOOTH_ADDRESS_LENGTH 17
-#define BLUETOOTH_ADDRESS_NONE   "00:00:00:00:00:00"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 enum BluetoothSocketType {
   RFCOMM = 1,
   SCO = 2,
   L2CAP = 3
 };
--- a/dom/bluetooth/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/BluetoothHfpManager.cpp
@@ -6,17 +6,16 @@
 
 #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"
@@ -35,29 +34,27 @@
 /**
  * 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 {
-  StaticAutoPtr<BluetoothHfpManager> gBluetoothHfpManager;
+  StaticRefPtr<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,
@@ -258,17 +255,17 @@ BluetoothHfpManagerObserver::Observe(nsI
   }
 
   MOZ_ASSERT(false, "BluetoothHfpManager got unexpected topic!");
   return NS_ERROR_UNEXPECTED;
 }
 
 NS_IMPL_ISUPPORTS1(BluetoothHfpManagerObserver, nsIObserver)
 
-class BluetoothHfpManager::SendRingIndicatorTask : public Task
+class SendRingIndicatorTask : public Task
 {
 public:
   SendRingIndicatorTask(const nsAString& aNumber, int aType)
     : mNumber(aNumber)
     , mType(aType)
   {
     MOZ_ASSERT(NS_IsMainThread());
   }
@@ -282,29 +279,30 @@ public:
       return;
     }
 
     if (!gBluetoothHfpManager) {
       NS_WARNING("BluetoothHfpManager no longer exists, cannot send ring!");
       return;
     }
 
+    const char* kHfpCrlf = "\xd\xa";
     nsAutoCString ringMsg(kHfpCrlf);
-    ringMsg.AppendLiteral("RING");
-    ringMsg.AppendLiteral(kHfpCrlf);
-    gBluetoothHfpManager->SendLine(ringMsg.get());
+    ringMsg += "RING";
+    ringMsg += kHfpCrlf;
+    gBluetoothHfpManager->SendSocketData(ringMsg);
 
     if (!mNumber.IsEmpty()) {
       nsAutoCString clipMsg(kHfpCrlf);
-      clipMsg.AppendLiteral("+CLIP: \"");
-      clipMsg.Append(NS_ConvertUTF16toUTF8(mNumber).get());
-      clipMsg.AppendLiteral("\",");
+      clipMsg += "+CLIP: \"";
+      clipMsg += NS_ConvertUTF16toUTF8(mNumber).get();
+      clipMsg += "\",";
       clipMsg.AppendInt(mType);
-      clipMsg.AppendLiteral(kHfpCrlf);
-      gBluetoothHfpManager->SendLine(clipMsg.get());
+      clipMsg += kHfpCrlf;
+      gBluetoothHfpManager->SendSocketData(clipMsg);
     }
 
     MessageLoop::current()->
       PostDelayedTask(FROM_HERE,
                       new SendRingIndicatorTask(mNumber, mType),
                       sRingInterval);
   }
 
@@ -388,21 +386,17 @@ BluetoothHfpManager::Reset()
   ResetCallArray();
 }
 
 bool
 BluetoothHfpManager::Init()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  mSocket = new BluetoothSocket(this,
-                                BluetoothSocketType::RFCOMM,
-                                true,
-                                true);
-  mPrevSocketStatus = mSocket->GetConnectionStatus();
+  mSocketStatus = GetConnectionStatus();
 
   sHfpObserver = new BluetoothHfpManagerObserver();
   if (!sHfpObserver->Init()) {
     NS_WARNING("Cannot set up Hfp Observers!");
   }
 
   mListener = new BluetoothTelephonyListener();
   if (!mListener->StartListening()) {
@@ -455,34 +449,38 @@ 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
-  BluetoothHfpManager* manager = new BluetoothHfpManager();
-  NS_ENSURE_TRUE(manager->Init(), nullptr);
+  nsRefPtr<BluetoothHfpManager> manager = new BluetoothHfpManager();
+  NS_ENSURE_TRUE(manager, nullptr);
+
+  if (!manager->Init()) {
+    return 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 = (mSocket->GetConnectionStatus() ==
-       SocketConnectionStatus::SOCKET_CONNECTED);
+  v = (GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTED)
+    ? true : false ;
   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");
@@ -568,17 +566,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 (mSocket->GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTED) {
+  if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTED) {
     SendCommand("+VGS: ", mCurrentVgs);
   }
 
   return NS_OK;
 }
 
 nsresult
 BluetoothHfpManager::HandleVoiceConnectionChanged()
@@ -660,25 +658,24 @@ BluetoothHfpManager::HandleIccInfoChange
   return NS_OK;
 }
 
 nsresult
 BluetoothHfpManager::HandleShutdown()
 {
   MOZ_ASSERT(NS_IsMainThread());
   gInShutdown = true;
-  Disconnect();
+  CloseSocket();
   gBluetoothHfpManager = nullptr;
   return NS_OK;
 }
 
 // Virtual function of class SocketConsumer
 void
-BluetoothHfpManager::ReceiveSocketData(BluetoothSocket* aSocket,
-                                       nsAutoPtr<UnixSocketRawData>& aMessage)
+BluetoothHfpManager::ReceiveSocketData(nsAutoPtr<UnixSocketRawData>& aMessage)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   nsAutoCString msg((const char*)aMessage->mData.get(), aMessage->mSize);
   msg.StripWhitespace();
 
   nsTArray<nsCString> atCommandValues;
 
@@ -740,19 +737,19 @@ BluetoothHfpManager::ReceiveSocketData(B
       } else {
         SendLine("ERROR");
       }
       return;
     }
   } else if (msg.Find("AT+COPS?") != -1) {
     nsAutoCString message("+COPS: ");
     message.AppendInt(mNetworkSelectionMode);
-    message.AppendLiteral(",0,\"");
-    message.Append(NS_ConvertUTF16toUTF8(mOperatorName));
-    message.AppendLiteral("\"");
+    message += ",0,\"";
+    message += NS_ConvertUTF16toUTF8(mOperatorName);
+    message += "\"";
     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;
@@ -906,20 +903,20 @@ BluetoothHfpManager::ReceiveSocketData(B
         break;
       default:
         NS_WARNING("Not handling state changed");
         break;
     }
   } else if (msg.Find("AT+CNUM") != -1) {
     if (!mMsisdn.IsEmpty()) {
       nsAutoCString message("+CNUM: ,\"");
-      message.Append(NS_ConvertUTF16toUTF8(mMsisdn).get());
-      message.AppendLiteral("\",");
+      message += NS_ConvertUTF16toUTF8(mMsisdn).get();
+      message += "\",";
       message.AppendInt(TOA_UNKNOWN);
-      message.AppendLiteral(",,4");
+      message += ",,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());
@@ -940,25 +937,23 @@ BluetoothHfpManager::Connect(const nsASt
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (gInShutdown) {
     NS_WARNING("Connect called while in shutdown!");
     return false;
   }
 
-  SocketConnectionStatus s = mSocket->GetConnectionStatus();
-
-  if (s == SocketConnectionStatus::SOCKET_CONNECTED ||
-      s == SocketConnectionStatus::SOCKET_CONNECTING) {
-    NS_WARNING("BluetoothHfpManager has been already connected");
+  if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTED ||
+      GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTING) {
+    NS_WARNING("BluetoothHfpManager has connected/is connecting to a headset!");
     return false;
   }
 
-  mSocket->Disconnect();
+  CloseSocket();
 
   BluetoothService* bs = BluetoothService::Get();
   NS_ENSURE_TRUE(bs, false);
 
   nsString uuid;
   if (aIsHandsfree) {
     BluetoothUuidHelper::GetString(BluetoothServiceClass::HANDSFREE, uuid);
   } else {
@@ -967,71 +962,82 @@ BluetoothHfpManager::Connect(const nsASt
 
   mRunnable = aRunnable;
 
   nsresult rv = bs->GetSocketViaService(aDevicePath,
                                         uuid,
                                         BluetoothSocketType::RFCOMM,
                                         true,
                                         true,
-                                        mSocket,
+                                        this,
                                         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 (mSocket->GetConnectionStatus() ==
-      SocketConnectionStatus::SOCKET_LISTENING) {
+  if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_LISTENING) {
     NS_WARNING("BluetoothHfpManager has been already listening");
     return true;
   }
 
-  mSocket->Disconnect();
+  CloseSocket();
+
+  BluetoothService* bs = BluetoothService::Get();
+  NS_ENSURE_TRUE(bs, false);
 
-  if (!mSocket->Listen(BluetoothReservedChannels::CHANNEL_HANDSFREE_AG)) {
-    NS_WARNING("[HFP] Can't listen on socket!");
-    return false;
-  }
+  nsresult rv =
+    bs->ListenSocketViaService(BluetoothReservedChannels::CHANNEL_HANDSFREE_AG,
+                               BluetoothSocketType::RFCOMM,
+                               true,
+                               true,
+                               this);
 
-  mPrevSocketStatus = mSocket->GetConnectionStatus();
-  return true;
+  mSocketStatus = GetConnectionStatus();
+
+  return NS_FAILED(rv) ? false : true;
 }
 
 void
 BluetoothHfpManager::Disconnect()
 {
-  mSocket->Disconnect();
+  if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_DISCONNECTED) {
+    NS_WARNING("BluetoothHfpManager has been disconnected!");
+    return;
+  }
+
+  CloseSocket();
 }
 
 bool
 BluetoothHfpManager::SendLine(const char* aMessage)
 {
+  const char* kHfpCrlf = "\xd\xa";
   nsAutoCString msg;
 
-  msg.AppendLiteral(kHfpCrlf);
-  msg.Append(aMessage);
-  msg.AppendLiteral(kHfpCrlf);
+  msg += kHfpCrlf;
+  msg += aMessage;
+  msg += kHfpCrlf;
 
-  return mSocket->SendSocketData(msg);
+  return SendSocketData(msg);
 }
 
 bool
 BluetoothHfpManager::SendCommand(const char* aCommand, uint8_t aValue)
 {
-  if (mPrevSocketStatus != SocketConnectionStatus::SOCKET_CONNECTED) {
+  if (mSocketStatus != SocketConnectionStatus::SOCKET_CONNECTED) {
     return false;
   }
 
   nsAutoCString message;
   int value = aValue;
   message += aCommand;
 
   if (!strcmp(aCommand, "+CIEV: ")) {
@@ -1041,57 +1047,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.AppendLiteral(",");
+    message += ",";
     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.AppendLiteral("(\"");
-        message.Append(sCINDItems[i].name);
-        message.AppendLiteral("\",(");
-        message.Append(sCINDItems[i].range);
-        message.AppendLiteral(")");
+        message += "(\"";
+        message += sCINDItems[i].name;
+        message += "\",(";
+        message += sCINDItems[i].range;
+        message += ")";
         if (i == (ArrayLength(sCINDItems) - 1)) {
-          message.AppendLiteral(")");
+          message +=")";
           break;
         }
-        message.AppendLiteral("),");
+        message += "),";
       }
     } 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.AppendLiteral(",");
+        message += ",";
       }
     }
   } 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.AppendLiteral(",");
+      message += ",";
       message.AppendInt(call.mDirection);
-      message.AppendLiteral(",");
+      message += ",";
 
       switch (call.mState) {
         case nsITelephonyProvider::CALL_STATE_CONNECTED:
           message.AppendInt(0);
           break;
         case nsITelephonyProvider::CALL_STATE_HELD:
           message.AppendInt(1);
           break;
@@ -1103,19 +1109,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.AppendLiteral(",0,0,\"");
-      message.Append(NS_ConvertUTF16toUTF8(call.mNumber));
-      message.AppendLiteral("\",");
+      message += ",0,0,\"";
+      message += NS_ConvertUTF16toUTF8(call.mNumber).get();
+      message += "\",";
       message.AppendInt(call.mType);
 
       rv &= SendLine(message.get());
     }
     return rv;
   } else {
     message.AppendInt(value);
   }
@@ -1136,18 +1142,17 @@ BluetoothHfpManager::UpdateCIND(uint8_t 
 }
 
 void
 BluetoothHfpManager::HandleCallStateChanged(uint32_t aCallIndex,
                                             uint16_t aCallState,
                                             const nsAString& aNumber,
                                             bool aSend)
 {
-  if (mSocket->GetConnectionStatus() !=
-      SocketConnectionStatus::SOCKET_CONNECTED) {
+  if (GetConnectionStatus() != SocketConnectionStatus::SOCKET_CONNECTED) {
     return;
   }
 
   while (aCallIndex >= mCurrentCallArray.Length()) {
     Call call;
     mCurrentCallArray.AppendElement(call);
   }
 
@@ -1171,18 +1176,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.Append(NS_ConvertUTF16toUTF8(aNumber));
-          ccwaMsg.AppendLiteral("\",");
+          ccwaMsg += NS_ConvertUTF16toUTF8(aNumber).get();
+          ccwaMsg += "\",";
           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);
@@ -1196,37 +1201,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);
 
-      mSocket->GetAddress(address);
+      GetSocketAddr(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.
-      mSocket->GetAddress(address);
+      GetSocketAddr(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;
 
-          mSocket->GetAddress(address);
+          GetSocketAddr(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
@@ -1300,77 +1305,66 @@ BluetoothHfpManager::HandleCallStateChan
       NS_WARNING("Not handling state changed");
       sCINDItems[CINDType::CALL].value = CallState::NO_CALL;
       sCINDItems[CINDType::CALLSETUP].value = CallSetupState::NO_CALLSETUP;
       sCINDItems[CINDType::CALLHELD].value = CallHeldState::NO_CALLHELD;
   }
 }
 
 void
-BluetoothHfpManager::OnConnectSuccess(BluetoothSocket* aSocket)
+BluetoothHfpManager::OnConnectSuccess()
 {
-  MOZ_ASSERT(aSocket == mSocket);
-
   nsCOMPtr<nsITelephonyProvider> provider =
     do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
   NS_ENSURE_TRUE_VOID(provider);
   provider->EnumerateCalls(mListener->GetListener());
 
   // For active connection request, we need to reply the DOMRequest
   if (mRunnable) {
     BluetoothValue v = true;
     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
-  mSocket->GetAddress(mDevicePath);
-  mPrevSocketStatus = mSocket->GetConnectionStatus();
+  GetSocketAddr(mDevicePath);
+  mSocketStatus = GetConnectionStatus();
 
   NotifySettings();
 }
 
 void
-BluetoothHfpManager::OnConnectError(BluetoothSocket* aSocket)
+BluetoothHfpManager::OnConnectError()
 {
-  MOZ_ASSERT(aSocket == mSocket);
-
   // For active connection request, we need to reply the DOMRequest
   if (mRunnable) {
     BluetoothValue v;
     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(BluetoothSocket* aSocket)
+BluetoothHfpManager::OnDisconnect()
 {
-  MOZ_ASSERT(aSocket == mSocket);
-
   // When we close a connected socket, then restart listening again and
   // notify Settings app.
-  if (mPrevSocketStatus == SocketConnectionStatus::SOCKET_CONNECTED) {
+  if (mSocketStatus == SocketConnectionStatus::SOCKET_CONNECTED) {
     Listen();
     NotifySettings();
-  } else if (mPrevSocketStatus == SocketConnectionStatus::SOCKET_CONNECTING) {
+  } 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,26 +3,24 @@
 /* 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 BluetoothReplyRunnable;
 class BluetoothHfpManagerObserver;
-class BluetoothReplyRunnable;
-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,
@@ -45,51 +43,42 @@ 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 BluetoothSocketObserver
+class BluetoothHfpManager : public mozilla::ipc::UnixSocketConsumer
 {
 public:
   static BluetoothHfpManager* Get();
-  ~BluetoothHfpManager();
-
-  virtual void ReceiveSocketData(
-    BluetoothSocket* aSocket,
-    nsAutoPtr<mozilla::ipc::UnixSocketRawData>& aMessage) MOZ_OVERRIDE;
-  virtual void OnConnectSuccess(BluetoothSocket* aSocket) MOZ_OVERRIDE;
-  virtual void OnConnectError(BluetoothSocket* aSocket) MOZ_OVERRIDE;
-  virtual void OnDisconnect(BluetoothSocket* aSocket) MOZ_OVERRIDE;
+  virtual void ReceiveSocketData(nsAutoPtr<mozilla::ipc::UnixSocketRawData>& aMessage)
+    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();
@@ -97,31 +86,34 @@ 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;
-  SocketConnectionStatus mPrevSocketStatus;
+  enum mozilla::ipc::SocketConnectionStatus mSocketStatus;
 
   nsTArray<Call> mCurrentCallArray;
   nsAutoPtr<BluetoothTelephonyListener> mListener;
   nsRefPtr<BluetoothReplyRunnable> mRunnable;
-  nsRefPtr<BluetoothSocket> mSocket;
 };
 
 END_BLUETOOTH_NAMESPACE
 
 #endif
--- a/dom/bluetooth/BluetoothOppManager.cpp
+++ b/dom/bluetooth/BluetoothOppManager.cpp
@@ -4,17 +4,16 @@
  * 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/. */
 
 #include "base/basictypes.h"
 #include "BluetoothOppManager.h"
 
 #include "BluetoothReplyRunnable.h"
 #include "BluetoothService.h"
-#include "BluetoothSocket.h"
 #include "BluetoothUtils.h"
 #include "BluetoothUuid.h"
 #include "ObexBase.h"
 
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
@@ -80,17 +79,17 @@ namespace {
 static const uint32_t kUpdateProgressBase = 50 * 1024;
 
 /*
  * The format of the header of an PUT request is
  * [opcode:1][packet length:2][headerId:1][header length:2]
  */
 static const uint32_t kPutRequestHeaderSize = 6;
 
-StaticAutoPtr<BluetoothOppManager> sInstance;
+StaticRefPtr<BluetoothOppManager> sInstance;
 StaticRefPtr<BluetoothOppManagerObserver> sOppObserver;
 
 /*
  * FIXME / Bug 806749
  *
  * Currently Bluetooth*Manager inherits mozilla::ipc::UnixSocketConsumer,
  * which means that each Bluetooth*Manager can handle only one socket
  * connection at a time. We need to support concurrent multiple socket
@@ -190,33 +189,28 @@ public:
 private:
   nsCOMPtr<nsIInputStream> mInputStream;
   uint32_t mAvailablePacketSize;
 };
 
 class CloseSocketTask : public Task
 {
 public:
-  CloseSocketTask(BluetoothSocket* aSocket) : mSocket(aSocket)
-  {
-    MOZ_ASSERT(aSocket);
-  }
-
   void Run() MOZ_OVERRIDE
   {
-    MOZ_ASSERT(NS_IsMainThread());
+    if (!sInstance) {
+      NS_WARNING("BluetoothOppManager no longer exists, cannot close socket!");
+      return;
+    }
 
-    if (mSocket->GetConnectionStatus() ==
-        SocketConnectionStatus::SOCKET_CONNECTED) {
-      mSocket->Disconnect();
+    if (sInstance->GetConnectionStatus() ==
+          SocketConnectionStatus::SOCKET_CONNECTED) {
+      sInstance->CloseSocket();
     }
   }
-
-private:
-  nsRefPtr<BluetoothSocket> mSocket;
 };
 
 BluetoothOppManager::BluetoothOppManager() : mConnected(false)
                                            , mRemoteObexVersion(0)
                                            , mRemoteConnectionFlags(0)
                                            , mRemoteMaxPacketLength(0)
                                            , mLastCommand(0)
                                            , mPacketLeftLength(0)
@@ -224,57 +218,50 @@ BluetoothOppManager::BluetoothOppManager
                                            , mReceivedDataBufferOffset(0)
                                            , mAbortFlag(false)
                                            , mNewFileFlag(false)
                                            , mPutFinalFlag(false)
                                            , mSendTransferCompleteFlag(false)
                                            , mSuccessFlag(false)
                                            , mWaitingForConfirmationFlag(false)
 {
-  mConnectedDeviceAddress.AssignLiteral(BLUETOOTH_ADDRESS_NONE);
-
-  mSocket = new BluetoothSocket(this,
-                                BluetoothSocketType::RFCOMM,
-                                true,
-                                true);
-  mPrevSocketStatus = mSocket->GetConnectionStatus();
+  mConnectedDeviceAddress.AssignLiteral("00:00:00:00:00:00");
+  mSocketStatus = GetConnectionStatus();
 }
 
 BluetoothOppManager::~BluetoothOppManager()
 {
 }
 
 //static
 BluetoothOppManager*
 BluetoothOppManager::Get()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  if (!sInstance) {
+  if (sInstance == nullptr) {
     sInstance = new BluetoothOppManager();
   }
 
   return sInstance;
 }
 
 bool
 BluetoothOppManager::Connect(const nsAString& aDeviceObjectPath,
                              BluetoothReplyRunnable* aRunnable)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  SocketConnectionStatus s = mSocket->GetConnectionStatus();
-
-  if (s == SocketConnectionStatus::SOCKET_CONNECTED ||
-      s == SocketConnectionStatus::SOCKET_CONNECTING) {
+  if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTED ||
+      GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTING) {
     NS_WARNING("BluetoothOppManager has been already connected");
     return false;
   }
 
-  Disconnect();
+  CloseSocket();
 
   BluetoothService* bs = BluetoothService::Get();
   if (!bs) {
     NS_WARNING("BluetoothService not available!");
     return false;
   }
 
   nsString uuid;
@@ -282,58 +269,70 @@ BluetoothOppManager::Connect(const nsASt
 
   mRunnable = aRunnable;
 
   nsresult rv = bs->GetSocketViaService(aDeviceObjectPath,
                                         uuid,
                                         BluetoothSocketType::RFCOMM,
                                         true,
                                         true,
-                                        mSocket,
+                                        this,
                                         mRunnable);
 
   return NS_FAILED(rv) ? false : true;
 }
 
 void
 BluetoothOppManager::Disconnect()
 {
-  mSocket->Disconnect();
+  if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_DISCONNECTED) {
+    NS_WARNING("BluetoothOppManager has been disconnected!");
+    return;
+  }
+
+  CloseSocket();
 }
 
 nsresult
 BluetoothOppManager::HandleShutdown()
 {
   MOZ_ASSERT(NS_IsMainThread());
   sInShutdown = true;
-  Disconnect();
+  CloseSocket();
   sInstance = nullptr;
   return NS_OK;
 }
 
 bool
 BluetoothOppManager::Listen()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  if (mSocket->GetConnectionStatus() ==
-      SocketConnectionStatus::SOCKET_LISTENING) {
+  if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_LISTENING) {
     NS_WARNING("BluetoothOppManager has been already listening");
     return true;
   }
 
-  Disconnect();
+  CloseSocket();
 
-  if (!mSocket->Listen(BluetoothReservedChannels::CHANNEL_OPUSH)) {
-    NS_WARNING("[OPP] Can't listen on socket!");
+  BluetoothService* bs = BluetoothService::Get();
+  if (!bs) {
+    NS_WARNING("BluetoothService not available!");
     return false;
   }
 
-  mPrevSocketStatus = mSocket->GetConnectionStatus();
-  return true;
+  nsresult rv =
+    bs->ListenSocketViaService(BluetoothReservedChannels::CHANNEL_OPUSH,
+                               BluetoothSocketType::RFCOMM,
+                               true,
+                               true,
+                               this);
+  mSocketStatus = GetConnectionStatus();
+
+  return NS_FAILED(rv) ? false : true;
 }
 
 bool
 BluetoothOppManager::SendFile(BlobParent* aActor)
 {
   if (mBlob) {
     // Means there's a sending process. Reply error.
     return false;
@@ -687,18 +686,17 @@ BluetoothOppManager::ServerDataHandler(U
     packetLength = mPacketLeftLength;
   } else {
     opCode = aMessage->mData[0];
     packetLength = (((int)aMessage->mData[1]) << 8) | aMessage->mData[2];
 
     // When there's a Put packet right after a PutFinal packet,
     // which means it's the start point of a new file.
     if (mPutFinalFlag &&
-        (opCode == ObexRequestCode::Put ||
-         opCode == ObexRequestCode::PutFinal)) {
+        (opCode == ObexRequestCode::Put || opCode == ObexRequestCode::PutFinal)) {
       mNewFileFlag = true;
       AfterFirstPut();
     }
   }
 
   ObexHeaderSet pktHeaders(opCode);
   if (opCode == ObexRequestCode::Connect) {
     // Section 3.3.1 "Connect", IrOBEX 1.2
@@ -861,17 +859,17 @@ BluetoothOppManager::ClientDataHandler(U
     SendDisconnectRequest();
     FileTransferComplete();
   } else if (mLastCommand == ObexRequestCode::Disconnect) {
     AfterOppDisconnected();
     // Most devices will directly terminate connection after receiving
     // Disconnect request, so we make a delay here. If the socket hasn't been
     // disconnected, we will close it.
     MessageLoop::current()->
-      PostDelayedTask(FROM_HERE, new CloseSocketTask(mSocket), 1000);
+      PostDelayedTask(FROM_HERE, new CloseSocketTask(), 1000);
   } else if (mLastCommand == ObexRequestCode::Connect) {
     MOZ_ASSERT(!sFileName.IsEmpty());
     MOZ_ASSERT(mBlob);
 
     AfterOppConnected();
 
     // Keep remote information
     mRemoteObexVersion = aMessage->mData[3];
@@ -923,18 +921,17 @@ BluetoothOppManager::ClientDataHandler(U
     }
   } else {
     NS_WARNING("Unhandled ObexRequestCode");
   }
 }
 
 // Virtual function of class SocketConsumer
 void
-BluetoothOppManager::ReceiveSocketData(BluetoothSocket* aSocket,
-                                       nsAutoPtr<UnixSocketRawData>& aMessage)
+BluetoothOppManager::ReceiveSocketData(nsAutoPtr<UnixSocketRawData>& aMessage)
 {
   if (mLastCommand) {
     ClientDataHandler(aMessage);
     return;
   }
 
   ServerDataHandler(aMessage);
 }
@@ -955,17 +952,17 @@ BluetoothOppManager::SendConnectRequest(
   req[5] = BluetoothOppManager::MAX_PACKET_LENGTH >> 8;
   req[6] = (uint8_t)BluetoothOppManager::MAX_PACKET_LENGTH;
 
   SetObexPacketInfo(req, ObexRequestCode::Connect, index);
   mLastCommand = ObexRequestCode::Connect;
 
   UnixSocketRawData* s = new UnixSocketRawData(index);
   memcpy(s->mData, req, s->mSize);
-  mSocket->SendSocketData(s);
+  SendSocketData(s);
 }
 
 void
 BluetoothOppManager::SendPutHeaderRequest(const nsAString& aFileName,
                                           int aFileSize)
 {
   uint8_t* req = new uint8_t[mRemoteMaxPacketLength];
 
@@ -985,17 +982,17 @@ BluetoothOppManager::SendPutHeaderReques
   index += AppendHeaderName(&req[index], (char*)fileName, (len + 1) * 2);
   index += AppendHeaderLength(&req[index], aFileSize);
 
   SetObexPacketInfo(req, ObexRequestCode::Put, index);
   mLastCommand = ObexRequestCode::Put;
 
   UnixSocketRawData* s = new UnixSocketRawData(index);
   memcpy(s->mData, req, s->mSize);
-  mSocket->SendSocketData(s);
+  SendSocketData(s);
 
   delete [] fileName;
   delete [] req;
 }
 
 void
 BluetoothOppManager::SendPutRequest(uint8_t* aFileBody,
                                     int aFileBodyLength)
@@ -1015,17 +1012,17 @@ BluetoothOppManager::SendPutRequest(uint
   int index = 3;
   index += AppendHeaderBody(&req[index], aFileBody, aFileBodyLength);
 
   SetObexPacketInfo(req, ObexRequestCode::Put, index);
   mLastCommand = ObexRequestCode::Put;
 
   UnixSocketRawData* s = new UnixSocketRawData(index);
   memcpy(s->mData, req, s->mSize);
-  mSocket->SendSocketData(s);
+  SendSocketData(s);
 
   delete [] req;
 }
 
 void
 BluetoothOppManager::SendPutFinalRequest()
 {
   if (!mConnected) return;
@@ -1041,17 +1038,17 @@ BluetoothOppManager::SendPutFinalRequest
   int index = 3;
   uint8_t* req = new uint8_t[mRemoteMaxPacketLength];
   index += AppendHeaderEndOfBody(&req[index]);
   SetObexPacketInfo(req, ObexRequestCode::PutFinal, index);
   mLastCommand = ObexRequestCode::PutFinal;
 
   UnixSocketRawData* s = new UnixSocketRawData(index);
   memcpy(s->mData, req, s->mSize);
-  mSocket->SendSocketData(s);
+  SendSocketData(s);
 
   sWaitingToSendPutFinal = false;
 
   delete [] req;
 }
 
 void
 BluetoothOppManager::SendDisconnectRequest()
@@ -1061,33 +1058,33 @@ BluetoothOppManager::SendDisconnectReque
   uint8_t req[255];
   int index = 3;
 
   SetObexPacketInfo(req, ObexRequestCode::Disconnect, index);
   mLastCommand = ObexRequestCode::Disconnect;
 
   UnixSocketRawData* s = new UnixSocketRawData(index);
   memcpy(s->mData, req, s->mSize);
-  mSocket->SendSocketData(s);
+  SendSocketData(s);
 }
 
 void
 BluetoothOppManager::SendAbortRequest()
 {
   // Section 3.3.5 "Abort", IrOBEX 1.2
   // [opcode:1][length:2][Headers:var]
   uint8_t req[255];
   int index = 3;
 
   SetObexPacketInfo(req, ObexRequestCode::Abort, index);
   mLastCommand = ObexRequestCode::Abort;
 
   UnixSocketRawData* s = new UnixSocketRawData(index);
   memcpy(s->mData, req, s->mSize);
-  mSocket->SendSocketData(s);
+  SendSocketData(s);
 }
 
 bool
 BluetoothOppManager::IsTransferring()
 {
   return (mConnected && !mSendTransferCompleteFlag);
 }
 
@@ -1107,17 +1104,17 @@ BluetoothOppManager::ReplyToConnect()
   req[4] = 0x00; // flag=0x00
   req[5] = BluetoothOppManager::MAX_PACKET_LENGTH >> 8;
   req[6] = (uint8_t)BluetoothOppManager::MAX_PACKET_LENGTH;
 
   SetObexPacketInfo(req, ObexResponseCode::Success, index);
 
   UnixSocketRawData* s = new UnixSocketRawData(index);
   memcpy(s->mData, req, s->mSize);
-  mSocket->SendSocketData(s);
+  SendSocketData(s);
 }
 
 void
 BluetoothOppManager::ReplyToDisconnect()
 {
   if (!mConnected) return;
   mConnected = false;
 
@@ -1125,17 +1122,17 @@ BluetoothOppManager::ReplyToDisconnect()
   // [opcode:1][length:2][Headers:var]
   uint8_t req[255];
   int index = 3;
 
   SetObexPacketInfo(req, ObexResponseCode::Success, index);
 
   UnixSocketRawData* s = new UnixSocketRawData(index);
   memcpy(s->mData, req, s->mSize);
-  mSocket->SendSocketData(s);
+  SendSocketData(s);
 }
 
 void
 BluetoothOppManager::ReplyToPut(bool aFinal, bool aContinue)
 {
   if (!mConnected) return;
 
   // Section 3.3.2 "Disconnect", IrOBEX 1.2
@@ -1156,17 +1153,17 @@ BluetoothOppManager::ReplyToPut(bool aFi
       SetObexPacketInfo(req,
                         ObexResponseCode::Unauthorized & (~FINAL_BIT),
                         index);
     }
   }
 
   UnixSocketRawData* s = new UnixSocketRawData(index);
   memcpy(s->mData, req, s->mSize);
-  mSocket->SendSocketData(s);
+  SendSocketData(s);
 }
 
 void
 BluetoothOppManager::FileTransferComplete()
 {
   if (mSendTransferCompleteFlag) {
     return;
   }
@@ -1298,89 +1295,83 @@ BluetoothOppManager::ReceivingFileConfir
 
   if (!BroadcastSystemMessage(type, parameters)) {
     NS_WARNING("Failed to send [bluetooth-opp-receiving-file-confirmation]");
     return;
   }
 }
 
 void
-BluetoothOppManager::OnConnectSuccess(BluetoothSocket* aSocket)
+BluetoothOppManager::OnConnectSuccess()
 {
-  MOZ_ASSERT(aSocket == mSocket);
-
   if (mRunnable) {
     BluetoothReply* reply = new BluetoothReply(BluetoothReplySuccess(true));
     mRunnable->SetReply(reply);
     if (NS_FAILED(NS_DispatchToMainThread(mRunnable))) {
       NS_WARNING("Failed to dispatch to main thread!");
     }
     mRunnable.forget();
   }
 
   // Cache device address since we can't get socket address when a remote
   // device disconnect with us.
-  mSocket->GetAddress(mConnectedDeviceAddress);
-  mPrevSocketStatus = mSocket->GetConnectionStatus();
+  GetSocketAddr(mConnectedDeviceAddress);
+
+  mSocketStatus = GetConnectionStatus();
 }
 
 void
-BluetoothOppManager::OnConnectError(BluetoothSocket* aSocket)
+BluetoothOppManager::OnConnectError()
 {
-  MOZ_ASSERT(aSocket == mSocket);
-
   if (mRunnable) {
     nsString errorStr;
     errorStr.AssignLiteral("Failed to connect with a bluetooth opp manager!");
     BluetoothReply* reply = new BluetoothReply(BluetoothReplyError(errorStr));
     mRunnable->SetReply(reply);
     if (NS_FAILED(NS_DispatchToMainThread(mRunnable))) {
       NS_WARNING("Failed to dispatch to main thread!");
     }
     mRunnable.forget();
   }
 
-  mSocket->Disconnect();
-  mPrevSocketStatus = mSocket->GetConnectionStatus();
+  CloseSocket();
+  mSocketStatus = GetConnectionStatus();
   Listen();
 }
 
 void
-BluetoothOppManager::OnDisconnect(BluetoothSocket* aSocket)
+BluetoothOppManager::OnDisconnect()
 {
-  MOZ_ASSERT(aSocket == mSocket);
-
   /**
    * It is valid for a bluetooth device which is transfering file via OPP
    * closing socket without sending OBEX disconnect request first. So we
    * delete the broken file when we failed to receive a file from the remote,
    * and notify the transfer has been completed (but failed). We also call
    * AfterOppDisconnected here to ensure all variables will be cleaned.
    */
-  if (mPrevSocketStatus == SocketConnectionStatus::SOCKET_CONNECTED) {
+  if (mSocketStatus == SocketConnectionStatus::SOCKET_CONNECTED) {
     if (mTransferMode) {
       if (!mSuccessFlag) {
         DeleteReceivedFile();
       } else if (mDsFile) {
         nsString data;
         CopyASCIItoUTF16("modified", data);
 
-        nsCOMPtr<nsIObserverService> obs =
-          mozilla::services::GetObserverService();
+        nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
         if (obs) {
           obs->NotifyObservers(mDsFile, "file-watcher-notify", data.get());
         }
       }
     }
 
     if (!mSuccessFlag) {
       FileTransferComplete();
     }
 
     Listen();
-  } else if (mPrevSocketStatus == SocketConnectionStatus::SOCKET_CONNECTING) {
+  } else if (mSocketStatus == SocketConnectionStatus::SOCKET_CONNECTING) {
     NS_WARNING("BluetoothOppManager got unexpected socket status!");
   }
 
   AfterOppDisconnected();
-  mConnectedDeviceAddress.AssignLiteral(BLUETOOTH_ADDRESS_NONE);
+  mConnectedDeviceAddress.AssignLiteral("00:00:00:00:00:00");
   mSuccessFlag = false;
 }
--- a/dom/bluetooth/BluetoothOppManager.h
+++ b/dom/bluetooth/BluetoothOppManager.h
@@ -3,43 +3,43 @@
 /* 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_bluetoothoppmanager_h__
 #define mozilla_dom_bluetooth_bluetoothoppmanager_h__
 
 #include "BluetoothCommon.h"
-#include "BluetoothSocketObserver.h"
 #include "mozilla/dom/ipc/Blob.h"
 #include "mozilla/ipc/UnixSocket.h"
 #include "DeviceStorage.h"
 
 class nsIOutputStream;
 class nsIInputStream;
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothReplyRunnable;
-class BluetoothSocket;
 class ObexHeaderSet;
 
-class BluetoothOppManager : public BluetoothSocketObserver
+class BluetoothOppManager : public mozilla::ipc::UnixSocketConsumer
 {
 public:
   /*
    * Channel of reserved services are fixed values, please check
    * function add_reserved_service_records() in
    * external/bluetooth/bluez/src/adapter.c for more information.
    */
   static const int DEFAULT_OPP_CHANNEL = 10;
   static const int MAX_PACKET_LENGTH = 0xFFFE;
 
   ~BluetoothOppManager();
   static BluetoothOppManager* Get();
+  void ReceiveSocketData(nsAutoPtr<mozilla::ipc::UnixSocketRawData>& aMessage)
+    MOZ_OVERRIDE;
   void ClientDataHandler(mozilla::ipc::UnixSocketRawData* aMessage);
   void ServerDataHandler(mozilla::ipc::UnixSocketRawData* aMessage);
 
   /*
    * If a application wnats to send a file, first, it needs to
    * call Connect() to create a valid RFCOMM connection. After
    * that, call SendFile()/StopSendingFile() to control file-sharing
    * process. During the file transfering process, the application
@@ -67,29 +67,16 @@ public:
 
   void ExtractPacketHeaders(const ObexHeaderSet& aHeader);
   bool ExtractBlobHeaders();
   nsresult HandleShutdown();
 
   // Return true if there is an ongoing file-transfer session, please see
   // Bug 827267 for more information.
   bool IsTransferring();
-
-  // Implement interface BluetoothSocketObserver
-  void ReceiveSocketData(
-    BluetoothSocket* aSocket,
-    nsAutoPtr<mozilla::ipc::UnixSocketRawData>& aMessage) MOZ_OVERRIDE;
-
-  virtual void OnConnectSuccess(BluetoothSocket* aSocket) MOZ_OVERRIDE;
-  virtual void OnConnectError(BluetoothSocket* aSocket) MOZ_OVERRIDE;
-  virtual void OnDisconnect(BluetoothSocket* aSocket) MOZ_OVERRIDE;
-  void OnConnectSuccess() MOZ_OVERRIDE;
-  void OnConnectError() MOZ_OVERRIDE;
-  void OnDisconnect() MOZ_OVERRIDE;
-
 private:
   BluetoothOppManager();
   void StartFileTransfer();
   void FileTransferComplete();
   void UpdateProgress();
   void ReceivingFileConfirmation();
   bool CreateFile();
   bool WriteToFile(const uint8_t* aData, int aDataLength);
@@ -98,20 +85,24 @@ private:
   void ReplyToDisconnect();
   void ReplyToPut(bool aFinal, bool aContinue);
   void AfterOppConnected();
   void AfterFirstPut();
   void AfterOppDisconnected();
   void ValidateFileName();
   bool IsReservedChar(PRUnichar c);
 
+  virtual void OnConnectSuccess() MOZ_OVERRIDE;
+  virtual void OnConnectError() MOZ_OVERRIDE;
+  virtual void OnDisconnect() MOZ_OVERRIDE;
+
   /**
    * RFCOMM socket status.
    */
-  mozilla::ipc::SocketConnectionStatus mPrevSocketStatus;
+  enum mozilla::ipc::SocketConnectionStatus mSocketStatus;
 
   /**
    * OBEX session status.
    * Set when OBEX session is established.
    */
   bool mConnected;
   nsString mConnectedDeviceAddress;
 
@@ -177,14 +168,13 @@ private:
 
   nsCOMPtr<nsIDOMBlob> mBlob;
   nsCOMPtr<nsIThread> mReadFileThread;
   nsCOMPtr<nsIOutputStream> mOutputStream;
   nsCOMPtr<nsIInputStream> mInputStream;
 
   nsRefPtr<BluetoothReplyRunnable> mRunnable;
   nsRefPtr<DeviceStorageFile> mDsFile;
-  nsRefPtr<BluetoothSocket> mSocket;
 };
 
 END_BLUETOOTH_NAMESPACE
 
 #endif
--- a/dom/bluetooth/BluetoothScoManager.cpp
+++ b/dom/bluetooth/BluetoothScoManager.cpp
@@ -5,17 +5,16 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "base/basictypes.h"
 
 #include "BluetoothScoManager.h"
 
 #include "BluetoothReplyRunnable.h"
 #include "BluetoothService.h"
-#include "BluetoothSocket.h"
 #include "BluetoothUtils.h"
 
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
 #include "nsContentUtils.h"
 #include "nsIAudioManager.h"
 #include "nsIObserverService.h"
@@ -89,17 +88,17 @@ BluetoothScoManager::NotifyAudioManager(
     do_GetService("@mozilla.org/telephony/audiomanager;1");
   NS_ENSURE_TRUE_VOID(am);
   am->SetForceForUse(am->USE_COMMUNICATION, am->FORCE_BT_SCO);
 }
 
 NS_IMPL_ISUPPORTS1(BluetoothScoManagerObserver, nsIObserver)
 
 namespace {
-StaticAutoPtr<BluetoothScoManager> gBluetoothScoManager;
+StaticRefPtr<BluetoothScoManager> gBluetoothScoManager;
 StaticRefPtr<BluetoothScoManagerObserver> sScoObserver;
 bool gInShutdown = false;
 } // anonymous namespace
 
 NS_IMETHODIMP
 BluetoothScoManagerObserver::Observe(nsISupports* aSubject,
                                      const char* aTopic,
                                      const PRUnichar* aData)
@@ -115,21 +114,17 @@ BluetoothScoManagerObserver::Observe(nsI
 
 BluetoothScoManager::BluetoothScoManager()
 {
 }
 
 bool
 BluetoothScoManager::Init()
 {
-  mSocket = new BluetoothSocket(this,
-                                BluetoothSocketType::SCO,
-                                true,
-                                false);
-  mPrevSocketStatus = mSocket->GetConnectionStatus();
+  mSocketStatus = GetConnectionStatus();
 
   sScoObserver = new BluetoothScoManagerObserver();
   if (!sScoObserver->Init()) {
     NS_WARNING("Cannot set up SCO observers!");
   }
   return true;
 }
 
@@ -158,133 +153,135 @@ BluetoothScoManager::Get()
 
   // If we're in shutdown, don't create a new instance
   if (gInShutdown) {
     NS_WARNING("BluetoothScoManager can't be created during shutdown");
     return nullptr;
   }
 
   // Create new instance, register, return
-  BluetoothScoManager* manager = new BluetoothScoManager();
-  NS_ENSURE_TRUE(manager->Init(), nullptr);
+  nsRefPtr<BluetoothScoManager> manager = new BluetoothScoManager();
+  NS_ENSURE_TRUE(manager, nullptr);
+
+  if (!manager->Init()) {
+    return nullptr;
+  }
 
   gBluetoothScoManager = manager;
   return gBluetoothScoManager;
 }
 
 // Virtual function of class SocketConsumer
 void
-BluetoothScoManager::ReceiveSocketData(BluetoothSocket* aSocket,
-                                       nsAutoPtr<UnixSocketRawData>& aMessage)
+BluetoothScoManager::ReceiveSocketData(nsAutoPtr<UnixSocketRawData>& aMessage)
 {
   // SCO socket do nothing here
   MOZ_NOT_REACHED("This should never be called!");
 }
 
 nsresult
 BluetoothScoManager::HandleShutdown()
 {
   MOZ_ASSERT(NS_IsMainThread());
   gInShutdown = true;
-  mSocket->Disconnect();
+  CloseSocket();
   gBluetoothScoManager = nullptr;
   return NS_OK;
 }
 
 bool
 BluetoothScoManager::Connect(const nsAString& aDeviceAddress)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (gInShutdown) {
     MOZ_ASSERT(false, "Connect called while in shutdown!");
     return false;
   }
 
-  if (mSocket->GetConnectionStatus() ==
-      SocketConnectionStatus::SOCKET_CONNECTED) {
+  if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTED) {
     NS_WARNING("Sco socket has been connected");
     return false;
   }
 
-  mSocket->Disconnect();
+  CloseSocket();
 
   BluetoothService* bs = BluetoothService::Get();
   if (!bs) {
     NS_WARNING("BluetoothService not available!");
     return false;
   }
 
   nsresult rv = bs->GetScoSocket(aDeviceAddress,
                                  true,
                                  false,
-                                 mSocket);
+                                 this);
 
   return NS_FAILED(rv) ? false : true;
 }
 
 bool
 BluetoothScoManager::Listen()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (gInShutdown) {
     MOZ_ASSERT(false, "Listen called while in shutdown!");
     return false;
   }
 
-  if (mSocket->GetConnectionStatus() ==
-      SocketConnectionStatus::SOCKET_LISTENING) {
-    NS_WARNING("BluetoothScoManager has been already listening");
-    return true;
-  }
+  CloseSocket();
 
-  mSocket->Disconnect();
-
-  if (!mSocket->Listen(-1)) {
-    NS_WARNING("[SCO] Can't listen on socket!");
+  BluetoothService* bs = BluetoothService::Get();
+  if (!bs) {
+    NS_WARNING("BluetoothService not available!");
     return false;
   }
 
-  mPrevSocketStatus = mSocket->GetConnectionStatus();
-  return true;
+  nsresult rv = bs->ListenSocketViaService(-1,
+                                           BluetoothSocketType::SCO,
+                                           true,
+                                           true,
+                                           this);
+
+  mSocketStatus = GetConnectionStatus();
+
+  return NS_FAILED(rv) ? false : true;
 }
 
 void
 BluetoothScoManager::Disconnect()
 {
-  mSocket->Disconnect();
+  if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_DISCONNECTED) {
+    return;
+  }
+
+  CloseSocket();
 }
 
 void
-BluetoothScoManager::OnConnectSuccess(BluetoothSocket* aSocket)
+BluetoothScoManager::OnConnectSuccess()
 {
-  MOZ_ASSERT(aSocket == mSocket);
-
   nsString address;
-  mSocket->GetAddress(address);
+  GetSocketAddr(address);
   NotifyAudioManager(address);
 
-  mPrevSocketStatus = mSocket->GetConnectionStatus();
+  mSocketStatus = GetConnectionStatus();
 }
 
 void
-BluetoothScoManager::OnConnectError(BluetoothSocket* aSocket)
+BluetoothScoManager::OnConnectError()
 {
-  MOZ_ASSERT(aSocket == mSocket);
-
-  mSocket->Disconnect();
-  mPrevSocketStatus = mSocket->GetConnectionStatus();
+  CloseSocket();
+  mSocketStatus = GetConnectionStatus();
   Listen();
 }
 
 void
-BluetoothScoManager::OnDisconnect(BluetoothSocket* aSocket)
+BluetoothScoManager::OnDisconnect()
 {
-  MOZ_ASSERT(aSocket == mSocket);
-
-  if (mPrevSocketStatus == SocketConnectionStatus::SOCKET_CONNECTED) {
+  if (mSocketStatus == SocketConnectionStatus::SOCKET_CONNECTED) {
     Listen();
 
     nsString address = NS_LITERAL_STRING("");
     NotifyAudioManager(address);
   }
 }
--- a/dom/bluetooth/BluetoothScoManager.h
+++ b/dom/bluetooth/BluetoothScoManager.h
@@ -3,49 +3,46 @@
 /* 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_bluetoothscomanager_h__
 #define mozilla_dom_bluetooth_bluetoothscomanager_h__
 
 #include "BluetoothCommon.h"
-#include "BluetoothSocketObserver.h"
+#include "mozilla/ipc/UnixSocket.h"
 #include "nsIObserver.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothReplyRunnable;
 class BluetoothScoManagerObserver;
-class BluetoothSocket;
 
-class BluetoothScoManager : public BluetoothSocketObserver
+class BluetoothScoManager : public mozilla::ipc::UnixSocketConsumer
 {
 public:
-  static BluetoothScoManager* Get();
   ~BluetoothScoManager();
 
-  virtual void ReceiveSocketData(
-    BluetoothSocket* aSocket,
-    nsAutoPtr<mozilla::ipc::UnixSocketRawData>& aMessage) MOZ_OVERRIDE;
-  virtual void OnConnectSuccess(BluetoothSocket* aSocket) MOZ_OVERRIDE;
-  virtual void OnConnectError(BluetoothSocket* aSocket) MOZ_OVERRIDE;
-  virtual void OnDisconnect(BluetoothSocket* aSocket) MOZ_OVERRIDE;
+  static BluetoothScoManager* Get();
+  void ReceiveSocketData(nsAutoPtr<mozilla::ipc::UnixSocketRawData>& aMessage)
+    MOZ_OVERRIDE;
 
   bool Connect(const nsAString& aDeviceObjectPath);
   void Disconnect();
   bool Listen();
 
 private:
   friend class BluetoothScoManagerObserver;
   BluetoothScoManager();
   bool Init();
   void Cleanup();
   nsresult HandleShutdown();
   void NotifyAudioManager(const nsAString& aAddress);
+  virtual void OnConnectSuccess() MOZ_OVERRIDE;
+  virtual void OnConnectError() MOZ_OVERRIDE;
+  virtual void OnDisconnect() MOZ_OVERRIDE;
 
-  SocketConnectionStatus mPrevSocketStatus;
-  nsRefPtr<BluetoothSocket> mSocket;
+  int mSocketStatus;
 };
 
 END_BLUETOOTH_NAMESPACE
 
 #endif
--- a/dom/bluetooth/BluetoothService.h
+++ b/dom/bluetooth/BluetoothService.h
@@ -244,16 +244,23 @@ public:
            BlobParent* aBlobParent,
            BlobChild* aBlobChild,
            BluetoothReplyRunnable* aRunnable) = 0;
 
   virtual void
   StopSendingFile(const nsAString& aDeviceAddress,
                   BluetoothReplyRunnable* aRunnable) = 0;
 
+  virtual nsresult
+  ListenSocketViaService(int aChannel,
+                         BluetoothSocketType aType,
+                         bool aAuth,
+                         bool aEncrypt,
+                         mozilla::ipc::UnixSocketConsumer* aConsumer) = 0;
+
   virtual void
   ConfirmReceivingFile(const nsAString& aDeviceAddress, bool aConfirm,
                        BluetoothReplyRunnable* aRunnable) = 0;
 
   bool
   IsEnabled() const
   {
     return mEnabled;
deleted file mode 100644
--- a/dom/bluetooth/BluetoothSocket.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* 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/. */
-
-#include "BluetoothSocket.h"
-
-#include "BluetoothSocketObserver.h"
-#include "BluetoothUnixSocketConnector.h"
-#include "nsThreadUtils.h"
-
-using namespace mozilla::ipc;
-USING_BLUETOOTH_NAMESPACE
-
-BluetoothSocket::BluetoothSocket(BluetoothSocketObserver* aObserver,
-                                 BluetoothSocketType aType,
-                                 bool aAuth,
-                                 bool aEncrypt)
-  : mObserver(aObserver)
-  , mType(aType)
-  , mAuth(aAuth)
-  , mEncrypt(aEncrypt)
-{
-  MOZ_ASSERT(aObserver);
-}
-
-bool
-BluetoothSocket::Connect(const nsACString& aDeviceAddress, int aChannel)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(!aDeviceAddress.IsEmpty());
-
-  nsAutoPtr<BluetoothUnixSocketConnector> c(
-    new BluetoothUnixSocketConnector(mType, aChannel, mAuth, mEncrypt));
-
-  if (!ConnectSocket(c.forget(), aDeviceAddress.BeginReading())) {
-    nsAutoString addr;
-    GetAddress(addr);
-    BT_LOG("%s failed. Current connected device address: %s",
-           __FUNCTION__, NS_ConvertUTF16toUTF8(addr).get());
-    return false;
-  }
-
-  return true;
-}
-
-bool
-BluetoothSocket::Listen(int aChannel)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  nsAutoPtr<BluetoothUnixSocketConnector> c(
-    new BluetoothUnixSocketConnector(mType, aChannel, mAuth, mEncrypt));
-
-  if (!ListenSocket(c.forget())) {
-    nsAutoString addr;
-    GetAddress(addr);
-    BT_LOG("%s failed. Current connected device address: %s",
-           __FUNCTION__, NS_ConvertUTF16toUTF8(addr).get());
-    return false;
-  }
-
-  return true;
-}
-
-void
-BluetoothSocket::ReceiveSocketData(nsAutoPtr<UnixSocketRawData>& aMessage)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(mObserver);
-  mObserver->ReceiveSocketData(this, aMessage);
-}
-
-void
-BluetoothSocket::OnConnectSuccess()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(mObserver);
-  mObserver->OnConnectSuccess(this);
-}
-
-void
-BluetoothSocket::OnConnectError()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(mObserver);
-  mObserver->OnConnectError(this);
-}
-
-void
-BluetoothSocket::OnDisconnect()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(mObserver);
-  mObserver->OnDisconnect(this);
-}
-
deleted file mode 100644
--- a/dom/bluetooth/BluetoothSocket.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* 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_BluetoothSocket_h
-#define mozilla_dom_bluetooth_BluetoothSocket_h
-
-#include "BluetoothCommon.h"
-#include "mozilla/ipc/UnixSocket.h"
-
-BEGIN_BLUETOOTH_NAMESPACE
-
-class BluetoothSocketObserver;
-
-class BluetoothSocket : public mozilla::ipc::UnixSocketConsumer
-{
-public:
-  BluetoothSocket(BluetoothSocketObserver* aObserver,
-                  BluetoothSocketType aType,
-                  bool aAuth,
-                  bool aEncrypt);
-
-  bool Connect(const nsACString& aDeviceAddress, int aChannel);
-  bool Listen(int aChannel);
-  inline void Disconnect()
-  {
-    CloseSocket();
-  }
-
-  virtual void OnConnectSuccess() MOZ_OVERRIDE;
-  virtual void OnConnectError() MOZ_OVERRIDE;
-  virtual void OnDisconnect() MOZ_OVERRIDE;
-  virtual void ReceiveSocketData(
-    nsAutoPtr<mozilla::ipc::UnixSocketRawData>& aMessage) MOZ_OVERRIDE;
-
-  inline void GetAddress(nsAString& aDeviceAddress)
-  {
-    GetSocketAddr(aDeviceAddress);
-  }
-
-private:
-  BluetoothSocketObserver* mObserver;
-  BluetoothSocketType mType;
-  bool mAuth;
-  bool mEncrypt;
-};
-
-END_BLUETOOTH_NAMESPACE
-
-#endif
deleted file mode 100644
--- a/dom/bluetooth/BluetoothSocketObserver.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* 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_BluetoothSocketObserver_h
-#define mozilla_dom_bluetooth_BluetoothSocketObserver_h
-
-#include "BluetoothCommon.h"
-#include <mozilla/ipc/UnixSocket.h>
-
-using namespace mozilla::ipc;
-
-BEGIN_BLUETOOTH_NAMESPACE
-
-class BluetoothSocket;
-
-class BluetoothSocketObserver
-{
-public:
-  virtual void ReceiveSocketData(BluetoothSocket* aSocket,
-                                 nsAutoPtr<UnixSocketRawData>& aMessage) = 0;
- 
-   /**
-    * A callback function which would be called when a socket connection
-    * is established successfully. To be more specific, this would be called
-    * when socket state changes from CONNECTING/LISTENING to CONNECTED.
-    */
-  virtual void OnConnectSuccess(BluetoothSocket* aSocket) = 0;
- 
-   /**
-    * A callback function which would be called when BluetoothSocket::Connect()
-    * fails.
-    */
-  virtual void OnConnectError(BluetoothSocket* aSocket) = 0;
- 
-   /**
-    * A callback function which would be called when a socket connection
-    * is dropped. To be more specific, this would be called when socket state
-    * changes from CONNECTED/LISTENING to DISCONNECTED.
-    */
-  virtual void OnDisconnect(BluetoothSocket* aSocket) = 0;
-
-};
-
-END_BLUETOOTH_NAMESPACE
-
-#endif
--- a/dom/bluetooth/Makefile.in
+++ b/dom/bluetooth/Makefile.in
@@ -49,17 +49,16 @@ CPPSRCS += \
   BluetoothParent.cpp \
   BluetoothServiceChildProcess.cpp \
   BluetoothUnixSocketConnector.cpp \
   BluetoothHfpManager.cpp \
   BluetoothOppManager.cpp \
   ObexBase.cpp \
   BluetoothScoManager.cpp \
   BluetoothUuid.cpp \
-  BluetoothSocket.cpp \
   $(NULL)
 
 ifdef MOZ_B2G_RIL
 CPPSRCS += BluetoothTelephonyListener.cpp
 endif
 
 ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
 VPATH += \
--- a/dom/bluetooth/ipc/BluetoothServiceChildProcess.cpp
+++ b/dom/bluetooth/ipc/BluetoothServiceChildProcess.cpp
@@ -207,16 +207,29 @@ BluetoothServiceChildProcess::GetSocketV
                                        bool aEncrypt,
                                        mozilla::ipc::UnixSocketConsumer* aConsumer,
                                        BluetoothReplyRunnable* aRunnable)
 {
   MOZ_NOT_REACHED("This should never be called!");
   return NS_ERROR_FAILURE;
 }
 
+
+nsresult
+BluetoothServiceChildProcess::ListenSocketViaService(
+  int aChannel,
+  BluetoothSocketType aType,
+  bool aAuth,
+  bool aEncrypt,
+  mozilla::ipc::UnixSocketConsumer* aConsumer)
+{
+  MOZ_NOT_REACHED("This should never be called!");
+  return NS_ERROR_FAILURE;
+}
+
 bool
 BluetoothServiceChildProcess::SetPinCodeInternal(
                                                 const nsAString& aDeviceAddress,
                                                 const nsAString& aPinCode,
                                                 BluetoothReplyRunnable* aRunnable)
 {
   SendRequest(aRunnable,
               SetPinCodeRequest(nsString(aDeviceAddress), nsString(aPinCode)));
--- a/dom/bluetooth/ipc/BluetoothServiceChildProcess.h
+++ b/dom/bluetooth/ipc/BluetoothServiceChildProcess.h
@@ -86,16 +86,23 @@ public:
   GetSocketViaService(const nsAString& aObjectPath,
                       const nsAString& aService,
                       BluetoothSocketType aType,
                       bool aAuth,
                       bool aEncrypt,
                       mozilla::ipc::UnixSocketConsumer* aConsumer,
                       BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
+  virtual nsresult
+  ListenSocketViaService(int aChannel,
+                         BluetoothSocketType aType,
+                         bool aAuth,
+                         bool aEncrypt,
+                         mozilla::ipc::UnixSocketConsumer* aConsumer) MOZ_OVERRIDE;
+
   virtual bool
   SetPinCodeInternal(const nsAString& aDeviceAddress,
                      const nsAString& aPinCode,
                      BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual bool
   SetPasskeyInternal(const nsAString& aDeviceAddress,
                      uint32_t aPasskey,
--- a/dom/bluetooth/linux/BluetoothDBusService.cpp
+++ b/dom/bluetooth/linux/BluetoothDBusService.cpp
@@ -828,27 +828,27 @@ public:
 class ShutdownProfileManagersRunnable : public nsRunnable
 {
 public:
   NS_IMETHOD
   Run()
   {
     BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
     if (hfp) {
-      hfp->Disconnect();
+      hfp->CloseSocket();
     }
 
     BluetoothOppManager* opp = BluetoothOppManager::Get();
     if (opp) {
-      opp->Disconnect();
+      opp->CloseSocket();
     }
 
     BluetoothScoManager* sco = BluetoothScoManager::Get();
     if (sco) {
-      sco->Disconnect();
+      sco->CloseSocket();
     }
 
     return NS_OK;
   }
 };
 
 class PrepareAdapterRunnable : public nsRunnable
 {
@@ -2542,17 +2542,18 @@ 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->IsConnected());
+    return (hfp->GetConnectionStatus() ==
+            SocketConnectionStatus::SOCKET_CONNECTED);
   } else if (aProfileId == BluetoothServiceClass::OBJECT_PUSH) {
     BluetoothOppManager* opp = BluetoothOppManager::Get();
     return opp->IsTransferring();
   }
 
   return false;
 }
 
@@ -2788,8 +2789,27 @@ BluetoothDBusService::ConfirmReceivingFi
 
   if (!opp->ConfirmReceivingFile(aConfirm)) {
     errorStr.AssignLiteral("Calling ConfirmReceivingFile() failed");
   }
 
   DispatchBluetoothReply(aRunnable, v, errorStr);
 }
 
+nsresult
+BluetoothDBusService::ListenSocketViaService(
+                                    int aChannel,
+                                    BluetoothSocketType aType,
+                                    bool aAuth,
+                                    bool aEncrypt,
+                                    mozilla::ipc::UnixSocketConsumer* aConsumer)
+{
+  NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!");
+
+  BluetoothUnixSocketConnector* c =
+    new BluetoothUnixSocketConnector(aType, aChannel, aAuth, aEncrypt);
+  if (!aConsumer->ListenSocket(c)) {
+    NS_WARNING("Can't listen on socket!");
+    return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
+}
--- a/dom/bluetooth/linux/BluetoothDBusService.h
+++ b/dom/bluetooth/linux/BluetoothDBusService.h
@@ -82,16 +82,23 @@ public:
                       const nsAString& aService,
                       BluetoothSocketType aType,
                       bool aAuth,
                       bool aEncrypt,
                       mozilla::ipc::UnixSocketConsumer* aConsumer,
                       BluetoothReplyRunnable* aRunnable);
 
   virtual nsresult
+  ListenSocketViaService(int aChannel,
+                         BluetoothSocketType aType,
+                         bool aAuth,
+                         bool aEncrypt,
+                         mozilla::ipc::UnixSocketConsumer* aConsumer);
+
+  virtual nsresult
   CreatePairedDeviceInternal(const nsAString& aDeviceAddress,
                              int aTimeout,
                              BluetoothReplyRunnable* aRunnable);
 
   virtual nsresult
   RemoveDeviceInternal(const nsAString& aDeviceObjectPath,
                        BluetoothReplyRunnable* aRunnable);
 
--- a/ipc/unixsocket/UnixSocket.h
+++ b/ipc/unixsocket/UnixSocket.h
@@ -137,17 +137,17 @@ enum SocketConnectionStatus {
 
 class UnixSocketConsumer : public RefCounted<UnixSocketConsumer>
 {
 public:
   UnixSocketConsumer();
 
   virtual ~UnixSocketConsumer();
 
-  SocketConnectionStatus GetConnectionStatus() const
+  SocketConnectionStatus GetConnectionStatus()
   {
     return mConnectionStatus;
   }
 
   /**
    * Function to be called whenever data is received. This is only called on the
    * main thread.
    *