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
#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.
* It is important to register a2dp callbacks before enable() gets called.
@ -520,30 +599,7 @@ BluetoothA2dpManager::InitA2dpInterface(BluetoothProfileResultHandler* aRes)
return;
}
int ret = sBtA2dpInterface->Init(&sBtA2dpCallbacks);
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();
}
sBtA2dpInterface->Init(&sBtA2dpCallbacks, new InitA2dpResultHandler(aRes));
}
BluetoothA2dpManager::~BluetoothA2dpManager()
@ -617,6 +673,99 @@ BluetoothA2dpManager::Get()
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
void
BluetoothA2dpManager::DeinitA2dpInterface(BluetoothProfileResultHandler* aRes)
@ -624,17 +773,14 @@ BluetoothA2dpManager::DeinitA2dpInterface(BluetoothProfileResultHandler* aRes)
MOZ_ASSERT(NS_IsMainThread());
if (sBtA2dpInterface) {
sBtA2dpInterface->Cleanup();
sBtA2dpInterface = nullptr;
sBtA2dpInterface->Cleanup(new CleanupA2dpResultHandler(aRes));
} else if (aRes) {
// We dispatch a runnable here to make the profile resource handler
// behave as if A2DP was initialized.
nsRefPtr<nsRunnable> r = new CleanupA2dpResultHandlerRunnable(aRes);
if (NS_FAILED(NS_DispatchToMainThread(r))) {
BT_LOGR("Failed to dispatch cleanup-result-handler runnable");
}
#if ANDROID_VERSION > 17
if (sBtAvrcpInterface) {
sBtAvrcpInterface->Cleanup();
sBtAvrcpInterface = nullptr;
}
#endif
if (aRes) {
aRes->Deinit();
}
}

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

@ -888,16 +888,27 @@ BluetoothA2dpInterface::BluetoothA2dpInterface(
BluetoothA2dpInterface::~BluetoothA2dpInterface()
{ }
bt_status_t
BluetoothA2dpInterface::Init(btav_callbacks_t* aCallbacks)
void
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
BluetoothA2dpInterface::Cleanup()
BluetoothA2dpInterface::Cleanup(BluetoothA2dpResultHandler* aRes)
{
mInterface->cleanup();
if (aRes) {
DispatchBluetoothA2dpResult(aRes, &BluetoothA2dpResultHandler::Cleanup,
BT_STATUS_SUCCESS);
}
}
bt_status_t
@ -969,16 +980,27 @@ BluetoothAvrcpInterface::BluetoothAvrcpInterface(
BluetoothAvrcpInterface::~BluetoothAvrcpInterface()
{ }
bt_status_t
BluetoothAvrcpInterface::Init(btrc_callbacks_t* aCallbacks)
void
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
BluetoothAvrcpInterface::Cleanup()
BluetoothAvrcpInterface::Cleanup(BluetoothAvrcpResultHandler* aRes)
{
mInterface->cleanup();
if (aRes) {
DispatchBluetoothAvrcpResult(aRes, &BluetoothAvrcpResultHandler::Cleanup,
BT_STATUS_SUCCESS);
}
}
bt_status_t

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

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