Bug 906305 - Patch 4: Fix BluetoothHfpManager, r=echou

This commit is contained in:
Gina Yeh 2013-09-06 19:20:43 +08:00
parent 53070ae399
commit b49c5f26fd
3 changed files with 116 additions and 77 deletions

View File

@ -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)

View File

@ -61,22 +61,26 @@ public:
static BluetoothHfpManager* Get();
~BluetoothHfpManager();
// The following functions are inherited from BluetoothSocketObserver
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 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<Call> mCurrentCallArray;
nsAutoPtr<BluetoothTelephonyListener> mListener;
nsRefPtr<BluetoothReplyRunnable> mRunnable;
BluetoothProfileController* mController;
nsRefPtr<BluetoothReplyRunnable> mScoRunnable;
// If a connection has been established, mSocket will be the socket

View File

@ -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