Bug 1083708: Handle non-existant Bluetooth profile interfaces correctly, r=shawnjohnjr

Bluetooth profile managers just return an error if a profile interface is
not available. Doing so breaks the initialization and cleanup routines. This
patch changes the profile managers to still report an error, but signal
progress to the given result runnable.
This commit is contained in:
Thomas Zimmermann 2014-10-16 16:40:49 +02:00
parent 2c80c4d658
commit 7b70c83aca
4 changed files with 176 additions and 20 deletions

View File

@ -193,6 +193,28 @@ private:
nsRefPtr<BluetoothProfileResultHandler> mRes;
};
class OnErrorProfileResultHandlerRunnable MOZ_FINAL : public nsRunnable
{
public:
OnErrorProfileResultHandlerRunnable(BluetoothProfileResultHandler* aRes,
nsresult aRv)
: mRes(aRes)
, mRv(aRv)
{
MOZ_ASSERT(mRes);
}
NS_IMETHOD Run() MOZ_OVERRIDE
{
mRes->OnError(mRv);
return NS_OK;
}
private:
nsRefPtr<BluetoothProfileResultHandler> mRes;
nsresult mRv;
};
/*
* This function will be only called when Bluetooth is turning on.
* It is important to register a2dp callbacks before enable() gets called.
@ -204,10 +226,28 @@ void
BluetoothA2dpManager::InitA2dpInterface(BluetoothProfileResultHandler* aRes)
{
BluetoothInterface* btInf = BluetoothInterface::GetInstance();
NS_ENSURE_TRUE_VOID(btInf);
if (NS_WARN_IF(!btInf)) {
// If there's no HFP interface, we dispatch a runnable
// that calls the profile result handler.
nsRefPtr<nsRunnable> r =
new OnErrorProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
if (NS_FAILED(NS_DispatchToMainThread(r))) {
BT_LOGR("Failed to dispatch HFP OnError runnable");
}
return;
}
sBtA2dpInterface = btInf->GetBluetoothA2dpInterface();
NS_ENSURE_TRUE_VOID(sBtA2dpInterface);
if (NS_WARN_IF(!sBtA2dpInterface)) {
// If there's no HFP interface, we dispatch a runnable
// that calls the profile result handler.
nsRefPtr<nsRunnable> r =
new OnErrorProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
if (NS_FAILED(NS_DispatchToMainThread(r))) {
BT_LOGR("Failed to dispatch HFP OnError runnable");
}
return;
}
BluetoothA2dpManager* a2dpManager = BluetoothA2dpManager::Get();
sBtA2dpInterface->Init(a2dpManager, new InitA2dpResultHandler(aRes));
@ -341,6 +381,11 @@ public:
sBtA2dpInterface = nullptr;
if (sBtAvrcpInterface) {
sBtAvrcpInterface->Cleanup(new CleanupAvrcpResultHandler(mRes));
} else if (mRes) {
/* Not all backends support AVRCP. If it's not available
* we signal success from here.
*/
mRes->Deinit();
}
}
@ -360,6 +405,11 @@ public:
sBtA2dpInterface = nullptr;
if (sBtAvrcpInterface) {
sBtAvrcpInterface->Cleanup(new CleanupAvrcpResultHandler(mRes));
} else if (mRes) {
/* Not all backends support AVRCP. If it's not available
* we signal success from here.
*/
mRes->Deinit();
}
return NS_OK;

View File

@ -329,16 +329,56 @@ private:
nsRefPtr<CleanupInitResultHandler> mRes;
};
class OnErrorProfileResultHandlerRunnable MOZ_FINAL : public nsRunnable
{
public:
OnErrorProfileResultHandlerRunnable(BluetoothProfileResultHandler* aRes,
nsresult aRv)
: mRes(aRes)
, mRv(aRv)
{
MOZ_ASSERT(mRes);
}
NS_IMETHOD Run() MOZ_OVERRIDE
{
mRes->OnError(mRv);
return NS_OK;
}
private:
nsRefPtr<BluetoothProfileResultHandler> mRes;
nsresult mRv;
};
// static
void
BluetoothHfpManager::InitHfpInterface(BluetoothProfileResultHandler* aRes)
{
BluetoothInterface* btInf = BluetoothInterface::GetInstance();
NS_ENSURE_TRUE_VOID(btInf);
if (NS_WARN_IF(!btInf)) {
// If there's no backend interface, we dispatch a runnable
// that calls the profile result handler.
nsRefPtr<nsRunnable> r =
new OnErrorProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
if (NS_FAILED(NS_DispatchToMainThread(r))) {
BT_LOGR("Failed to dispatch HFP OnError runnable");
}
return;
}
BluetoothHandsfreeInterface *interface =
btInf->GetBluetoothHandsfreeInterface();
NS_ENSURE_TRUE_VOID(interface);
if (NS_WARN_IF(!interface)) {
// If there's no HFP interface, we dispatch a runnable
// that calls the profile result handler.
nsRefPtr<nsRunnable> r =
new OnErrorProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
if (NS_FAILED(NS_DispatchToMainThread(r))) {
BT_LOGR("Failed to dispatch HFP OnError runnable");
}
return;
}
nsRefPtr<CleanupInitResultHandler> res =
new CleanupInitResultHandler(interface, aRes);

View File

@ -197,6 +197,28 @@ private:
nsRefPtr<BluetoothProfileResultHandler> mRes;
};
class OnErrorProfileResultHandlerRunnable MOZ_FINAL : public nsRunnable
{
public:
OnErrorProfileResultHandlerRunnable(BluetoothProfileResultHandler* aRes,
nsresult aRv)
: mRes(aRes)
, mRv(aRv)
{
MOZ_ASSERT(mRes);
}
NS_IMETHOD Run() MOZ_OVERRIDE
{
mRes->OnError(mRv);
return NS_OK;
}
private:
nsRefPtr<BluetoothProfileResultHandler> mRes;
nsresult mRv;
};
/*
* This function will be only called when Bluetooth is turning on.
* It is important to register a2dp callbacks before enable() gets called.
@ -208,19 +230,25 @@ void
BluetoothA2dpManager::InitA2dpInterface(BluetoothProfileResultHandler* aRes)
{
BluetoothInterface* btInf = BluetoothInterface::GetInstance();
if (!btInf) {
BT_LOGR("Error: Bluetooth interface not available");
if (aRes) {
aRes->OnError(NS_ERROR_FAILURE);
if (NS_WARN_IF(!btInf)) {
// If there's no backend interface, we dispatch a runnable
// that calls the profile result handler.
nsRefPtr<nsRunnable> r =
new OnErrorProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
if (NS_FAILED(NS_DispatchToMainThread(r))) {
BT_LOGR("Failed to dispatch HFP OnError runnable");
}
return;
}
sBtA2dpInterface = btInf->GetBluetoothA2dpInterface();
if (!sBtA2dpInterface) {
BT_LOGR("Error: Bluetooth A2DP interface not available");
if (aRes) {
aRes->OnError(NS_ERROR_FAILURE);
if (NS_WARN_IF(!sBtA2dpInterface)) {
// If there's no A2DP interface, we dispatch a runnable
// that calls the profile result handler.
nsRefPtr<nsRunnable> r =
new OnErrorProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
if (NS_FAILED(NS_DispatchToMainThread(r))) {
BT_LOGR("Failed to dispatch HFP OnError runnable");
}
return;
}
@ -357,6 +385,11 @@ public:
sBtA2dpInterface = nullptr;
if (sBtAvrcpInterface) {
sBtAvrcpInterface->Cleanup(new CleanupAvrcpResultHandler(mRes));
} else if (mRes) {
/* Not all backends support AVRCP. If it's not available
* we signal success from here.
*/
mRes->Deinit();
}
}
@ -376,6 +409,11 @@ public:
sBtA2dpInterface = nullptr;
if (sBtAvrcpInterface) {
sBtAvrcpInterface->Cleanup(new CleanupAvrcpResultHandler(mRes));
} else if (mRes) {
/* Not all backends support AVRCP. If it's not available
* we signal success from here.
*/
mRes->Deinit();
}
return NS_OK;

View File

@ -320,25 +320,53 @@ private:
nsRefPtr<CleanupInitResultHandler> mRes;
};
class OnErrorProfileResultHandlerRunnable MOZ_FINAL : public nsRunnable
{
public:
OnErrorProfileResultHandlerRunnable(BluetoothProfileResultHandler* aRes,
nsresult aRv)
: mRes(aRes)
, mRv(aRv)
{
MOZ_ASSERT(mRes);
}
NS_IMETHOD Run() MOZ_OVERRIDE
{
mRes->OnError(mRv);
return NS_OK;
}
private:
nsRefPtr<BluetoothProfileResultHandler> mRes;
nsresult mRv;
};
// static
void
BluetoothHfpManager::InitHfpInterface(BluetoothProfileResultHandler* aRes)
{
BluetoothInterface* btInf = BluetoothInterface::GetInstance();
if (!btInf) {
BT_LOGR("Error: Bluetooth interface not available");
if (aRes) {
aRes->OnError(NS_ERROR_FAILURE);
if (NS_WARN_IF(!btInf)) {
// If there's no backend interface, we dispatch a runnable
// that calls the profile result handler.
nsRefPtr<nsRunnable> r =
new OnErrorProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
if (NS_FAILED(NS_DispatchToMainThread(r))) {
BT_LOGR("Failed to dispatch HFP OnError runnable");
}
return;
}
BluetoothHandsfreeInterface *interface =
btInf->GetBluetoothHandsfreeInterface();
if (!interface) {
BT_LOGR("Error: Bluetooth Handsfree interface not available");
if (aRes) {
aRes->OnError(NS_ERROR_FAILURE);
if (NS_WARN_IF(!interface)) {
// If there's no HFP interface, we dispatch a runnable
// that calls the profile result handler.
nsRefPtr<nsRunnable> r =
new OnErrorProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
if (NS_FAILED(NS_DispatchToMainThread(r))) {
BT_LOGR("Failed to dispatch HFP OnError runnable");
}
return;
}