diff --git a/dom/bluetooth/BluetoothHfpManager.cpp b/dom/bluetooth/BluetoothHfpManager.cpp index f147d8f12e90..c077d82be160 100644 --- a/dom/bluetooth/BluetoothHfpManager.cpp +++ b/dom/bluetooth/BluetoothHfpManager.cpp @@ -8,7 +8,7 @@ #include "BluetoothHfpManager.h" -#include "BluetoothA2dpManager.h" +#include "BluetoothProfileController.h" #include "BluetoothReplyRunnable.h" #include "BluetoothService.h" #include "BluetoothSocket.h" @@ -358,6 +358,8 @@ BluetoothHfpManager::Reset() // Please see Bug 878728 for more information. mBSIR = false; + mController = nullptr; + ResetCallArray(); } @@ -657,7 +659,7 @@ BluetoothHfpManager::HandleShutdown() { MOZ_ASSERT(NS_IsMainThread()); sInShutdown = true; - Disconnect(); + Disconnect(nullptr); DisconnectSco(); sBluetoothHfpManager = nullptr; } @@ -1000,43 +1002,38 @@ respond_with_ok: void BluetoothHfpManager::Connect(const nsAString& aDeviceAddress, - const bool aIsHandsfree, - BluetoothReplyRunnable* aRunnable) + BluetoothProfileController* aController) { MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(aController && !mController); BluetoothService* bs = BluetoothService::Get(); if (!bs || sInShutdown) { - DispatchBluetoothReply(aRunnable, BluetoothValue(), - NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE)); + aController->OnConnect(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE)); return; } if (mSocket) { if (mDeviceAddress == aDeviceAddress) { - DispatchBluetoothReply(aRunnable, BluetoothValue(), - NS_LITERAL_STRING(ERR_ALREADY_CONNECTED)); + aController->OnConnect(NS_LITERAL_STRING(ERR_ALREADY_CONNECTED)); } else { - DispatchBluetoothReply(aRunnable, BluetoothValue(), - NS_LITERAL_STRING(ERR_REACHED_CONNECTION_LIMIT)); + aController->OnConnect(NS_LITERAL_STRING(ERR_REACHED_CONNECTION_LIMIT)); } - return; } mNeedsUpdatingSdpRecords = true; - mIsHandsfree = aIsHandsfree; + mIsHandsfree = !IS_HEADSET(aController->GetCod()); nsString uuid; - if (aIsHandsfree) { + if (mIsHandsfree) { BluetoothUuidHelper::GetString(BluetoothServiceClass::HANDSFREE, uuid); } else { BluetoothUuidHelper::GetString(BluetoothServiceClass::HEADSET, uuid); } if (NS_FAILED(bs->GetServiceChannel(aDeviceAddress, uuid, this))) { - DispatchBluetoothReply(aRunnable, BluetoothValue(), - NS_LITERAL_STRING(ERR_SERVICE_CHANNEL_NOT_FOUND)); + aController->OnConnect(NS_LITERAL_STRING(ERR_SERVICE_CHANNEL_NOT_FOUND)); return; } @@ -1051,9 +1048,7 @@ BluetoothHfpManager::Connect(const nsAString& aDeviceAddress, mHeadsetSocket = nullptr; } - MOZ_ASSERT(!mRunnable); - - mRunnable = aRunnable; + mController = aController; mSocket = new BluetoothSocket(this, BluetoothSocketType::RFCOMM, true, true); } @@ -1103,16 +1098,22 @@ BluetoothHfpManager::Listen() } void -BluetoothHfpManager::Disconnect() +BluetoothHfpManager::Disconnect(BluetoothProfileController* aController) { - if (mSocket) { - mSocket->Disconnect(); - mSocket = nullptr; + MOZ_ASSERT(NS_IsMainThread()); + + if (!mSocket) { + if (aController) { + aController->OnDisconnect(NS_LITERAL_STRING(ERR_ALREADY_DISCONNECTED)); + } + return; } - BluetoothA2dpManager* a2dp = BluetoothA2dpManager::Get(); - NS_ENSURE_TRUE_VOID(a2dp); - a2dp->Disconnect(); + MOZ_ASSERT(!mController); + + mController = aController; + mSocket->Disconnect(); + mSocket = nullptr; } bool @@ -1450,7 +1451,7 @@ BluetoothHfpManager::HandleCallStateChanged(uint32_t aCallIndex, } void -BluetoothHfpManager::OnConnectSuccess(BluetoothSocket* aSocket) +BluetoothHfpManager::OnSocketConnectSuccess(BluetoothSocket* aSocket) { MOZ_ASSERT(aSocket); @@ -1486,15 +1487,6 @@ BluetoothHfpManager::OnConnectSuccess(BluetoothSocket* aSocket) 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 = nullptr; - } - mFirstCKPD = true; // Cache device path for NotifySettings() since we can't get socket address @@ -1505,13 +1497,11 @@ BluetoothHfpManager::OnConnectSuccess(BluetoothSocket* aSocket) ListenSco(); - BluetoothA2dpManager* a2dp = BluetoothA2dpManager::Get(); - NS_ENSURE_TRUE_VOID(a2dp); - a2dp->Connect(mDeviceAddress); + OnConnect(EmptyString()); } void -BluetoothHfpManager::OnConnectError(BluetoothSocket* aSocket) +BluetoothHfpManager::OnSocketConnectError(BluetoothSocket* aSocket) { // Failed to create a SCO socket if (aSocket == mScoSocket) { @@ -1519,25 +1509,14 @@ BluetoothHfpManager::OnConnectError(BluetoothSocket* aSocket) return; } - // For active connection request, we need to reply the DOMRequest - if (mRunnable) { - NS_NAMED_LITERAL_STRING(replyError, - "Failed to connect with a bluetooth headset!"); - DispatchBluetoothReply(mRunnable, BluetoothValue(), replyError); - - mRunnable = nullptr; - } - - mSocket = nullptr; mHandsfreeSocket = nullptr; mHeadsetSocket = nullptr; - // If connecting for some reason didn't work, restart listening - Listen(); + OnConnect(NS_LITERAL_STRING("SocketConnectionError")); } void -BluetoothHfpManager::OnDisconnect(BluetoothSocket* aSocket) +BluetoothHfpManager::OnSocketDisconnect(BluetoothSocket* aSocket) { MOZ_ASSERT(aSocket); @@ -1552,12 +1531,12 @@ BluetoothHfpManager::OnDisconnect(BluetoothSocket* aSocket) return; } - mSocket = nullptr; DisconnectSco(); - Listen(); NotifyConnectionStatusChanged(NS_LITERAL_STRING(BLUETOOTH_HFP_STATUS_CHANGED_ID)); DispatchConnectionStatusChanged(NS_LITERAL_STRING(HFP_STATUS_CHANGED_ID)); + OnDisconnect(EmptyString()); + Reset(); } @@ -1581,11 +1560,7 @@ BluetoothHfpManager::OnUpdateSdpRecords(const nsAString& aDeviceAddress) // Since we have updated SDP records of the target device, we should // try to get the channel of target service again. if (NS_FAILED(bs->GetServiceChannel(aDeviceAddress, uuid, this))) { - DispatchBluetoothReply(mRunnable, BluetoothValue(), - NS_LITERAL_STRING(ERR_SERVICE_CHANNEL_NOT_FOUND)); - mRunnable = nullptr; - mSocket = nullptr; - Listen(); + OnConnect(NS_LITERAL_STRING(ERR_SERVICE_CHANNEL_NOT_FOUND)); } } @@ -1596,7 +1571,6 @@ BluetoothHfpManager::OnGetServiceChannel(const nsAString& aDeviceAddress, { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!aDeviceAddress.IsEmpty()); - MOZ_ASSERT(mRunnable); BluetoothService* bs = BluetoothService::Get(); NS_ENSURE_TRUE_VOID(bs); @@ -1608,22 +1582,14 @@ BluetoothHfpManager::OnGetServiceChannel(const nsAString& aDeviceAddress, mNeedsUpdatingSdpRecords = false; bs->UpdateSdpRecords(aDeviceAddress, this); } else { - DispatchBluetoothReply(mRunnable, v, - NS_LITERAL_STRING(ERR_SERVICE_CHANNEL_NOT_FOUND)); - mRunnable = nullptr; - mSocket = nullptr; - Listen(); + OnConnect(NS_LITERAL_STRING(ERR_SERVICE_CHANNEL_NOT_FOUND)); } return; } if (!mSocket->Connect(NS_ConvertUTF16toUTF8(aDeviceAddress), aChannel)) { - DispatchBluetoothReply(mRunnable, v, - NS_LITERAL_STRING("SocketConnectionError")); - mRunnable = nullptr; - mSocket = nullptr; - Listen(); + OnConnect(NS_LITERAL_STRING("SocketConnectionError")); } } @@ -1773,4 +1739,44 @@ BluetoothHfpManager::IsScoConnected() return false; } +void +BluetoothHfpManager::OnConnect(const nsAString& aErrorStr) +{ + MOZ_ASSERT(NS_IsMainThread()); + + // When we failed to create a socket, restart listening. + if (!aErrorStr.IsEmpty()) { + mSocket = nullptr; + Listen(); + } + + /** + * On the one hand, notify the controller that we've done for outbound + * connections. On the other hand, we do nothing for inbound connections. + */ + NS_ENSURE_TRUE_VOID(mController); + + mController->OnConnect(aErrorStr); + mController = nullptr; +} + +void +BluetoothHfpManager::OnDisconnect(const nsAString& aErrorStr) +{ + MOZ_ASSERT(NS_IsMainThread()); + + // Start listening + mSocket = nullptr; + Listen(); + + /** + * On the one hand, notify the controller that we've done for outbound + * connections. On the other hand, we do nothing for inbound connections. + */ + NS_ENSURE_TRUE_VOID(mController); + + mController->OnDisconnect(aErrorStr); + mController = nullptr; +} + NS_IMPL_ISUPPORTS1(BluetoothHfpManager, nsIObserver) diff --git a/dom/bluetooth/BluetoothHfpManager.h b/dom/bluetooth/BluetoothHfpManager.h index 8766dc738518..d6299d5f721a 100644 --- a/dom/bluetooth/BluetoothHfpManager.h +++ b/dom/bluetooth/BluetoothHfpManager.h @@ -61,22 +61,26 @@ public: static BluetoothHfpManager* Get(); ~BluetoothHfpManager(); + // The following functions are inherited from BluetoothSocketObserver virtual void ReceiveSocketData( BluetoothSocket* aSocket, nsAutoPtr& 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 OnSocketConnectSuccess(BluetoothSocket* aSocket) MOZ_OVERRIDE; + virtual void OnSocketConnectError(BluetoothSocket* aSocket) MOZ_OVERRIDE; + virtual void OnSocketDisconnect(BluetoothSocket* aSocket) MOZ_OVERRIDE; + + // The following functions are inherited from BluetoothProfileManagerBase virtual void OnGetServiceChannel(const nsAString& aDeviceAddress, const nsAString& aServiceUuid, int aChannel) MOZ_OVERRIDE; virtual void OnUpdateSdpRecords(const nsAString& aDeviceAddress) MOZ_OVERRIDE; virtual void GetAddress(nsAString& aDeviceAddress) MOZ_OVERRIDE; + virtual void Connect(const nsAString& aDeviceAddress, + BluetoothProfileController* aController) MOZ_OVERRIDE; + virtual void Disconnect(BluetoothProfileController* aController) MOZ_OVERRIDE; + virtual void OnConnect(const nsAString& aErrorStr) MOZ_OVERRIDE; + virtual void OnDisconnect(const nsAString& AErrorStr) MOZ_OVERRIDE; - void Connect(const nsAString& aDeviceAddress, - const bool aIsHandsfree, - BluetoothReplyRunnable* aRunnable); - void Disconnect(); bool Listen(); bool ConnectSco(BluetoothReplyRunnable* aRunnable = nullptr); bool DisconnectSco(); @@ -148,6 +152,7 @@ private: nsTArray mCurrentCallArray; nsAutoPtr mListener; nsRefPtr mRunnable; + BluetoothProfileController* mController; nsRefPtr mScoRunnable; // If a connection has been established, mSocket will be the socket diff --git a/dom/bluetooth/BluetoothProfileManagerBase.h b/dom/bluetooth/BluetoothProfileManagerBase.h index 08386597d646..98657c63e624 100644 --- a/dom/bluetooth/BluetoothProfileManagerBase.h +++ b/dom/bluetooth/BluetoothProfileManagerBase.h @@ -23,6 +23,7 @@ #include "nsIObserver.h" BEGIN_BLUETOOTH_NAMESPACE +class BluetoothProfileController; class BluetoothProfileManagerBase : public nsIObserver { @@ -31,8 +32,35 @@ public: const nsAString& aServiceUuid, int aChannel) = 0; virtual void OnUpdateSdpRecords(const nsAString& aDeviceAddress) = 0; + + /** + * Returns the address of the connected device. + */ virtual void GetAddress(nsAString& aDeviceAddress) = 0; + + /** + * Returns true if the profile is connected. + */ virtual bool IsConnected() = 0; + + /** + * Connect to a specific remote device. When it has been done, the + * callback "OnConnect" will be invoked. + */ + virtual void Connect(const nsAString& aDeviceAddress, + BluetoothProfileController* aController) = 0; + + /** + * Close the socket and then invoke the callback "OnDisconnect". + */ + virtual void Disconnect(BluetoothProfileController* aController) = 0; + + /** + * If it establishes/releases a connection successfully, the error string + * will be empty. Otherwise, the error string shows the failure reason. + */ + virtual void OnConnect(const nsAString& aErrorStr) = 0; + virtual void OnDisconnect(const nsAString& aErrorStr) = 0; }; END_BLUETOOTH_NAMESPACE