Bug 1038645: Asynchronous Bluetooth Handsfree init and cleanup methods (under bluetooth2/), r=btian

This commit is contained in:
Thomas Zimmermann 2014-07-22 13:53:28 +02:00
parent 3274cb40bb
commit 7d9b6e07cc
3 changed files with 152 additions and 26 deletions

View File

@ -617,16 +617,29 @@ BluetoothHandsfreeInterface::BluetoothHandsfreeInterface(
BluetoothHandsfreeInterface::~BluetoothHandsfreeInterface()
{ }
bt_status_t
BluetoothHandsfreeInterface::Init(bthf_callbacks_t* aCallbacks)
void
BluetoothHandsfreeInterface::Init(bthf_callbacks_t* aCallbacks,
BluetoothHandsfreeResultHandler* aRes)
{
return mInterface->init(aCallbacks);
bt_status_t status = mInterface->init(aCallbacks);
if (aRes) {
DispatchBluetoothHandsfreeResult(aRes,
&BluetoothHandsfreeResultHandler::Init,
status);
}
}
void
BluetoothHandsfreeInterface::Cleanup()
BluetoothHandsfreeInterface::Cleanup(BluetoothHandsfreeResultHandler* aRes)
{
mInterface->cleanup();
if (aRes) {
DispatchBluetoothHandsfreeResult(aRes,
&BluetoothHandsfreeResultHandler::Cleanup,
BT_STATUS_SUCCESS);
}
}
/* Connect / Disconnect */

View File

@ -112,8 +112,9 @@ class BluetoothHandsfreeInterface
public:
friend class BluetoothInterface;
bt_status_t Init(bthf_callbacks_t* aCallbacks);
void Cleanup();
void Init(bthf_callbacks_t* aCallbacks,
BluetoothHandsfreeResultHandler* aRes);
void Cleanup(BluetoothHandsfreeResultHandler* aRes);
/* Connect / Disconnect */

View File

@ -428,6 +428,72 @@ BluetoothHfpManager::Init()
return true;
}
class CleanupInitResultHandler MOZ_FINAL : public BluetoothHandsfreeResultHandler
{
public:
CleanupInitResultHandler(BluetoothHandsfreeInterface* aInterface,
BluetoothProfileResultHandler* aRes)
: mInterface(aInterface)
, mRes(aRes)
{
MOZ_ASSERT(mInterface);
}
void OnError(bt_status_t aStatus) MOZ_OVERRIDE
{
BT_WARNING("BluetoothHandsfreeInterface::Init failed: %d", (int)aStatus);
if (mRes) {
mRes->OnError(NS_ERROR_FAILURE);
}
}
void Init() MOZ_OVERRIDE
{
sBluetoothHfpInterface = mInterface;
if (mRes) {
mRes->Init();
}
}
void Cleanup() MOZ_OVERRIDE
{
sBluetoothHfpInterface = nullptr;
/* During re-initialization, a previouly initialized
* |BluetoothHandsfreeInterface| has now been cleaned
* up, so we start initialization.
*/
RunInit();
}
void RunInit()
{
mInterface->Init(&sBluetoothHfpCallbacks, this);
}
private:
BluetoothHandsfreeInterface* mInterface;
nsRefPtr<BluetoothProfileResultHandler> mRes;
};
class InitResultHandlerRunnable MOZ_FINAL : public nsRunnable
{
public:
InitResultHandlerRunnable(CleanupInitResultHandler* aRes)
: mRes(aRes)
{
MOZ_ASSERT(mRes);
}
NS_IMETHOD Run() MOZ_OVERRIDE
{
mRes->RunInit();
return NS_OK;
}
private:
nsRefPtr<CleanupInitResultHandler> mRes;
};
// static
void
BluetoothHfpManager::InitHfpInterface(BluetoothProfileResultHandler* aRes)
@ -441,11 +507,6 @@ BluetoothHfpManager::InitHfpInterface(BluetoothProfileResultHandler* aRes)
return;
}
if (sBluetoothHfpInterface) {
sBluetoothHfpInterface->Cleanup();
sBluetoothHfpInterface = nullptr;
}
BluetoothHandsfreeInterface *interface =
btInf->GetBluetoothHandsfreeInterface();
if (!interface) {
@ -456,17 +517,19 @@ BluetoothHfpManager::InitHfpInterface(BluetoothProfileResultHandler* aRes)
return;
}
if (interface->Init(&sBluetoothHfpCallbacks) != BT_STATUS_SUCCESS) {
if (aRes) {
aRes->OnError(NS_ERROR_FAILURE);
}
return;
}
nsRefPtr<CleanupInitResultHandler> res =
new CleanupInitResultHandler(interface, aRes);
sBluetoothHfpInterface = interface;
if (aRes) {
aRes->Init();
if (sBluetoothHfpInterface) {
// Cleanup an initialized HFP before initializing again.
sBluetoothHfpInterface->Cleanup(res);
} else {
// If there's no HFP interface to cleanup first, we dispatch
// a runnable that calls the profile result handler.
nsRefPtr<nsRunnable> r = new InitResultHandlerRunnable(res);
if (NS_FAILED(NS_DispatchToMainThread(r))) {
BT_LOGR("Failed to dispatch HFP init runnable");
}
}
}
@ -488,16 +551,65 @@ BluetoothHfpManager::~BluetoothHfpManager()
hal::UnregisterBatteryObserver(this);
}
class CleanupResultHandler MOZ_FINAL : public BluetoothHandsfreeResultHandler
{
public:
CleanupResultHandler(BluetoothProfileResultHandler* aRes)
: mRes(aRes)
{ }
void OnError(bt_status_t aStatus) MOZ_OVERRIDE
{
BT_WARNING("BluetoothHandsfreeInterface::Cleanup failed: %d", (int)aStatus);
if (mRes) {
mRes->OnError(NS_ERROR_FAILURE);
}
}
void Cleanup() MOZ_OVERRIDE
{
sBluetoothHfpInterface = nullptr;
if (mRes) {
mRes->Deinit();
}
}
private:
nsRefPtr<BluetoothProfileResultHandler> mRes;
};
class DeinitResultHandlerRunnable MOZ_FINAL : public nsRunnable
{
public:
DeinitResultHandlerRunnable(BluetoothProfileResultHandler* aRes)
: mRes(aRes)
{
MOZ_ASSERT(mRes);
}
NS_IMETHOD Run() MOZ_OVERRIDE
{
mRes->Deinit();
return NS_OK;
}
private:
nsRefPtr<BluetoothProfileResultHandler> mRes;
};
// static
void
BluetoothHfpManager::DeinitHfpInterface(BluetoothProfileResultHandler* aRes)
{
if (sBluetoothHfpInterface) {
sBluetoothHfpInterface->Cleanup();
sBluetoothHfpInterface = nullptr;
sBluetoothHfpInterface->Cleanup(new CleanupResultHandler(aRes));
} else if (aRes) {
// We dispatch a runnable here to make the profile resource handler
// behave as if HFP was initialized.
nsRefPtr<nsRunnable> r = new DeinitResultHandlerRunnable(aRes);
if (NS_FAILED(NS_DispatchToMainThread(r))) {
BT_LOGR("Failed to dispatch cleanup-result-handler runnable");
}
if (aRes) {
aRes->Deinit();
}
}