Bug 1042691: Asynchronous init and cleanup of A2DP/AVRCP (under bluetooth2/), r=btian

This commit is contained in:
Thomas Zimmermann 2014-07-28 09:52:51 +02:00
Родитель 6c5cf788bd
Коммит abbdf7f4d9
3 изменённых файлов: 217 добавлений и 47 удалений

Просмотреть файл

@ -492,6 +492,85 @@ static btrc_callbacks_t sBtAvrcpCallbacks = {
}; };
#endif #endif
#if ANDROID_VERSION > 17
class InitAvrcpResultHandler MOZ_FINAL : public BluetoothAvrcpResultHandler
{
public:
InitAvrcpResultHandler(BluetoothProfileResultHandler* aRes)
: mRes(aRes)
{ }
void OnError(bt_status_t aStatus) MOZ_OVERRIDE
{
BT_WARNING("BluetoothAvrcpInterface::Init failed: %d",
(int)aStatus);
if (mRes) {
mRes->OnError(NS_ERROR_FAILURE);
}
}
void Init() MOZ_OVERRIDE
{
if (mRes) {
mRes->Init();
}
}
private:
nsRefPtr<BluetoothProfileResultHandler> mRes;
};
#endif
class InitA2dpResultHandler MOZ_FINAL : public BluetoothA2dpResultHandler
{
public:
InitA2dpResultHandler(BluetoothProfileResultHandler* aRes)
: mRes(aRes)
{ }
void OnError(bt_status_t aStatus) MOZ_OVERRIDE
{
BT_WARNING("BluetoothA2dpInterface::Init failed: %d",
(int)aStatus);
if (mRes) {
mRes->OnError(NS_ERROR_FAILURE);
}
}
void Init() MOZ_OVERRIDE
{
#if ANDROID_VERSION > 17
/* Also init AVRCP if it's available, ... */
BluetoothInterface* btInf = BluetoothInterface::GetInstance();
if (!btInf) {
if (mRes) {
mRes->OnError(NS_ERROR_FAILURE);
}
return;
}
sBtAvrcpInterface = btInf->GetBluetoothAvrcpInterface();
if (!sBtAvrcpInterface) {
if (mRes) {
mRes->OnError(NS_ERROR_FAILURE);
}
return;
}
sBtAvrcpInterface->Init(&sBtAvrcpCallbacks,
new InitAvrcpResultHandler(mRes));
#else
/* ...or signal success otherwise. */
if (mRes) {
mRes->Init();
}
#endif
}
private:
nsRefPtr<BluetoothProfileResultHandler> mRes;
};
/* /*
* This function will be only called when Bluetooth is turning on. * This function will be only called when Bluetooth is turning on.
* It is important to register a2dp callbacks before enable() gets called. * It is important to register a2dp callbacks before enable() gets called.
@ -520,30 +599,7 @@ BluetoothA2dpManager::InitA2dpInterface(BluetoothProfileResultHandler* aRes)
return; return;
} }
int ret = sBtA2dpInterface->Init(&sBtA2dpCallbacks); sBtA2dpInterface->Init(&sBtA2dpCallbacks, new InitA2dpResultHandler(aRes));
if (ret != BT_STATUS_SUCCESS) {
BT_LOGR("Warning: failed to init a2dp module");
}
#if ANDROID_VERSION > 17
sBtAvrcpInterface = btInf->GetBluetoothAvrcpInterface();
if (!sBtAvrcpInterface) {
BT_LOGR("Error: Bluetooth AVRCP interface not available");
if (aRes) {
aRes->OnError(NS_ERROR_FAILURE);
}
return;
}
ret = sBtAvrcpInterface->Init(&sBtAvrcpCallbacks);
if (ret != BT_STATUS_SUCCESS) {
BT_LOGR("Warning: failed to init avrcp module");
}
#endif
if (aRes) {
aRes->Init();
}
} }
BluetoothA2dpManager::~BluetoothA2dpManager() BluetoothA2dpManager::~BluetoothA2dpManager()
@ -617,6 +673,99 @@ BluetoothA2dpManager::Get()
return sBluetoothA2dpManager; return sBluetoothA2dpManager;
} }
#if ANDROID_VERSION > 17
class CleanupAvrcpResultHandler MOZ_FINAL : public BluetoothAvrcpResultHandler
{
public:
CleanupAvrcpResultHandler(BluetoothProfileResultHandler* aRes)
: mRes(aRes)
{ }
void OnError(bt_status_t aStatus) MOZ_OVERRIDE
{
BT_WARNING("BluetoothAvrcpInterface::Cleanup failed: %d",
(int)aStatus);
if (mRes) {
mRes->OnError(NS_ERROR_FAILURE);
}
}
void Cleanup() MOZ_OVERRIDE
{
sBtAvrcpInterface = nullptr;
if (mRes) {
mRes->Deinit();
}
}
private:
nsRefPtr<BluetoothProfileResultHandler> mRes;
};
#endif
class CleanupA2dpResultHandler MOZ_FINAL : public BluetoothA2dpResultHandler
{
public:
CleanupA2dpResultHandler(BluetoothProfileResultHandler* aRes)
: mRes(aRes)
{ }
void OnError(bt_status_t aStatus) MOZ_OVERRIDE
{
BT_WARNING("BluetoothA2dpInterface::Cleanup failed: %d",
(int)aStatus);
if (mRes) {
mRes->OnError(NS_ERROR_FAILURE);
}
}
void Cleanup() MOZ_OVERRIDE
{
sBtA2dpInterface = nullptr;
#if ANDROID_VERSION > 17
/* Cleanup AVRCP if it's available and initialized, ...*/
if (sBtAvrcpInterface) {
sBtAvrcpInterface->Cleanup(new CleanupAvrcpResultHandler(mRes));
} else
#endif
if (mRes) {
/* ...or simply signal success from here. */
mRes->Deinit();
}
}
private:
nsRefPtr<BluetoothProfileResultHandler> mRes;
};
class CleanupA2dpResultHandlerRunnable MOZ_FINAL : public nsRunnable
{
public:
CleanupA2dpResultHandlerRunnable(BluetoothProfileResultHandler* aRes)
: mRes(aRes)
{ }
NS_IMETHOD Run() MOZ_OVERRIDE
{
sBtA2dpInterface = nullptr;
#if ANDROID_VERSION > 17
/* Cleanup AVRCP if it's available and initialized, ...*/
if (sBtAvrcpInterface) {
sBtAvrcpInterface->Cleanup(new CleanupAvrcpResultHandler(mRes));
} else
#endif
if (mRes) {
/* ...or simply signal success from here. */
mRes->Deinit();
}
return NS_OK;
}
private:
nsRefPtr<BluetoothProfileResultHandler> mRes;
};
// static // static
void void
BluetoothA2dpManager::DeinitA2dpInterface(BluetoothProfileResultHandler* aRes) BluetoothA2dpManager::DeinitA2dpInterface(BluetoothProfileResultHandler* aRes)
@ -624,17 +773,14 @@ BluetoothA2dpManager::DeinitA2dpInterface(BluetoothProfileResultHandler* aRes)
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
if (sBtA2dpInterface) { if (sBtA2dpInterface) {
sBtA2dpInterface->Cleanup(); sBtA2dpInterface->Cleanup(new CleanupA2dpResultHandler(aRes));
sBtA2dpInterface = nullptr; } else if (aRes) {
} // We dispatch a runnable here to make the profile resource handler
#if ANDROID_VERSION > 17 // behave as if A2DP was initialized.
if (sBtAvrcpInterface) { nsRefPtr<nsRunnable> r = new CleanupA2dpResultHandlerRunnable(aRes);
sBtAvrcpInterface->Cleanup(); if (NS_FAILED(NS_DispatchToMainThread(r))) {
sBtAvrcpInterface = nullptr; BT_LOGR("Failed to dispatch cleanup-result-handler runnable");
} }
#endif
if (aRes) {
aRes->Deinit();
} }
} }

Просмотреть файл

@ -888,16 +888,27 @@ BluetoothA2dpInterface::BluetoothA2dpInterface(
BluetoothA2dpInterface::~BluetoothA2dpInterface() BluetoothA2dpInterface::~BluetoothA2dpInterface()
{ } { }
bt_status_t void
BluetoothA2dpInterface::Init(btav_callbacks_t* aCallbacks) BluetoothA2dpInterface::Init(btav_callbacks_t* aCallbacks,
BluetoothA2dpResultHandler* aRes)
{ {
return mInterface->init(aCallbacks); bt_status_t status = mInterface->init(aCallbacks);
if (aRes) {
DispatchBluetoothA2dpResult(aRes, &BluetoothA2dpResultHandler::Init,
status);
}
} }
void void
BluetoothA2dpInterface::Cleanup() BluetoothA2dpInterface::Cleanup(BluetoothA2dpResultHandler* aRes)
{ {
mInterface->cleanup(); mInterface->cleanup();
if (aRes) {
DispatchBluetoothA2dpResult(aRes, &BluetoothA2dpResultHandler::Cleanup,
BT_STATUS_SUCCESS);
}
} }
bt_status_t bt_status_t
@ -969,16 +980,27 @@ BluetoothAvrcpInterface::BluetoothAvrcpInterface(
BluetoothAvrcpInterface::~BluetoothAvrcpInterface() BluetoothAvrcpInterface::~BluetoothAvrcpInterface()
{ } { }
bt_status_t void
BluetoothAvrcpInterface::Init(btrc_callbacks_t* aCallbacks) BluetoothAvrcpInterface::Init(btrc_callbacks_t* aCallbacks,
BluetoothAvrcpResultHandler* aRes)
{ {
return mInterface->init(aCallbacks); bt_status_t status = mInterface->init(aCallbacks);
if (aRes) {
DispatchBluetoothAvrcpResult(aRes, &BluetoothAvrcpResultHandler::Init,
status);
}
} }
void void
BluetoothAvrcpInterface::Cleanup() BluetoothAvrcpInterface::Cleanup(BluetoothAvrcpResultHandler* aRes)
{ {
mInterface->cleanup(); mInterface->cleanup();
if (aRes) {
DispatchBluetoothAvrcpResult(aRes, &BluetoothAvrcpResultHandler::Cleanup,
BT_STATUS_SUCCESS);
}
} }
bt_status_t bt_status_t

Просмотреть файл

@ -204,8 +204,9 @@ class BluetoothA2dpInterface
public: public:
friend class BluetoothInterface; friend class BluetoothInterface;
bt_status_t Init(btav_callbacks_t *aCallbacks); void Init(btav_callbacks_t *aCallbacks,
void Cleanup(); BluetoothA2dpResultHandler* aRes);
void Cleanup(BluetoothA2dpResultHandler* aRes);
bt_status_t Connect(bt_bdaddr_t *aBdAddr); bt_status_t Connect(bt_bdaddr_t *aBdAddr);
bt_status_t Disconnect(bt_bdaddr_t *aBdAddr); bt_status_t Disconnect(bt_bdaddr_t *aBdAddr);
@ -261,8 +262,9 @@ class BluetoothAvrcpInterface
public: public:
friend class BluetoothInterface; friend class BluetoothInterface;
bt_status_t Init(btrc_callbacks_t* aCallbacks); void Init(btrc_callbacks_t* aCallbacks,
void Cleanup(); BluetoothAvrcpResultHandler* aRes);
void Cleanup(BluetoothAvrcpResultHandler* aRes);
bt_status_t GetPlayStatusRsp(btrc_play_status_t aPlayStatus, bt_status_t GetPlayStatusRsp(btrc_play_status_t aPlayStatus,
uint32_t aSongLen, uint32_t aSongPos); uint32_t aSongLen, uint32_t aSongPos);