Bug 942712 - Ensure event 'AdapterAdded' will be fired after 'Enabled' being fired, r=gyeh

This commit is contained in:
Eric Chou 2013-11-27 16:24:51 +08:00
parent a258270b4d
commit 31b12ffadb
4 changed files with 124 additions and 62 deletions

View File

@ -164,6 +164,9 @@ public:
BluetoothSignal signal(signalName, NS_LITERAL_STRING(KEY_MANAGER), true); BluetoothSignal signal(signalName, NS_LITERAL_STRING(KEY_MANAGER), true);
gBluetoothService->DistributeSignal(signal); gBluetoothService->DistributeSignal(signal);
// Event 'AdapterAdded' has to be fired after firing 'Enabled'
gBluetoothService->TryFiringAdapterAdded();
return NS_OK; return NS_OK;
} }
@ -508,6 +511,8 @@ BluetoothService::StartStopBluetooth(bool aStart, bool aIsStartup)
LazyIdleThread::ManualShutdown); LazyIdleThread::ManualShutdown);
} }
mAdapterAddedReceived = false;
nsCOMPtr<nsIRunnable> runnable = new ToggleBtTask(aStart, aIsStartup); nsCOMPtr<nsIRunnable> runnable = new ToggleBtTask(aStart, aIsStartup);
nsresult rv = mBluetoothThread->Dispatch(runnable, NS_DISPATCH_NORMAL); nsresult rv = mBluetoothThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@ -786,6 +791,28 @@ BluetoothService::Observe(nsISupports* aSubject, const char* aTopic,
return NS_ERROR_UNEXPECTED; return NS_ERROR_UNEXPECTED;
} }
void
BluetoothService::TryFiringAdapterAdded()
{
MOZ_ASSERT(NS_IsMainThread());
if (IsToggling() || !mAdapterAddedReceived) {
return;
}
BluetoothSignal signal(NS_LITERAL_STRING("AdapterAdded"),
NS_LITERAL_STRING(KEY_MANAGER), true);
DistributeSignal(signal);
}
void
BluetoothService::AdapterAddedReceived()
{
MOZ_ASSERT(NS_IsMainThread());
mAdapterAddedReceived = true;
}
void void
BluetoothService::Notify(const BluetoothSignal& aData) BluetoothService::Notify(const BluetoothSignal& aData)
{ {

View File

@ -317,9 +317,16 @@ public:
void void
RemoveObserverFromTable(const nsAString& key); RemoveObserverFromTable(const nsAString& key);
/**
* Below 2 function/variable are used for ensuring event 'AdapterAdded' will
* be fired after event 'Enabled'.
*/
void TryFiringAdapterAdded();
void AdapterAddedReceived();
protected: protected:
BluetoothService() BluetoothService() : mEnabled(false)
: mEnabled(false) , mAdapterAddedReceived(false)
{ {
} }
@ -408,6 +415,8 @@ private:
* Bluetooth operations though. * Bluetooth operations though.
*/ */
nsCOMPtr<nsIThread> mBluetoothThread; nsCOMPtr<nsIThread> mBluetoothThread;
bool mAdapterAddedReceived;
}; };
END_BLUETOOTH_NAMESPACE END_BLUETOOTH_NAMESPACE

View File

@ -35,31 +35,6 @@ using namespace mozilla;
using namespace mozilla::ipc; using namespace mozilla::ipc;
USING_BLUETOOTH_NAMESPACE USING_BLUETOOTH_NAMESPACE
/**
* Classes only used in this file
*/
class DistributeBluetoothSignalTask : public nsRunnable {
public:
DistributeBluetoothSignalTask(const BluetoothSignal& aSignal) :
mSignal(aSignal)
{
}
NS_IMETHOD
Run()
{
MOZ_ASSERT(NS_IsMainThread());
BluetoothService* bs = BluetoothService::Get();
bs->DistributeSignal(mSignal);
return NS_OK;
}
private:
BluetoothSignal mSignal;
};
/** /**
* Static variables * Static variables
*/ */
@ -81,6 +56,70 @@ static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sUnbondingRunnableArray;
static nsTArray<int> sRequestedDeviceCountArray; static nsTArray<int> sRequestedDeviceCountArray;
static StaticAutoPtr<Monitor> sToggleBtMonitor; static StaticAutoPtr<Monitor> sToggleBtMonitor;
/**
* Classes only used in this file
*/
class DistributeBluetoothSignalTask : public nsRunnable {
public:
DistributeBluetoothSignalTask(const BluetoothSignal& aSignal) :
mSignal(aSignal)
{
}
NS_IMETHOD
Run()
{
MOZ_ASSERT(NS_IsMainThread());
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
bs->DistributeSignal(mSignal);
return NS_OK;
}
private:
BluetoothSignal mSignal;
};
class SetupAfterEnabledTask : public nsRunnable
{
public:
SetupAfterEnabledTask()
{ }
NS_IMETHOD
Run()
{
MOZ_ASSERT(NS_IsMainThread());
// Bluetooth scan mode is NONE by default
bt_scan_mode_t mode = BT_SCAN_MODE_CONNECTABLE;
bt_property_t prop;
prop.type = BT_PROPERTY_ADAPTER_SCAN_MODE;
prop.val = (void*)&mode;
prop.len = sizeof(mode);
NS_ENSURE_TRUE(sBtInterface, NS_ERROR_FAILURE);
int ret = sBtInterface->set_adapter_property(&prop);
if (ret != BT_STATUS_SUCCESS) {
BT_LOGR("%s: Fail to set: BT_SCAN_MODE_CONNECTABLE", __FUNCTION__);
}
// Try to fire event 'AdapterAdded' to fit the original behaviour when
// we used BlueZ as backend.
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
bs->AdapterAddedReceived();
bs->TryFiringAdapterAdded();
return NS_OK;
}
};
/** /**
* Static callback functions * Static callback functions
*/ */
@ -222,34 +261,6 @@ BdAddressTypeToString(bt_bdaddr_t* aBdAddressType, nsAString& aRetBdAddress)
aRetBdAddress = NS_ConvertUTF8toUTF16((char*)bdstr); aRetBdAddress = NS_ConvertUTF8toUTF16((char*)bdstr);
} }
static void
Setup()
{
// Bluetooth scan mode is NONE by default
bt_scan_mode_t mode = BT_SCAN_MODE_CONNECTABLE;
bt_property_t prop;
prop.type = BT_PROPERTY_ADAPTER_SCAN_MODE;
prop.val = (void*)&mode;
prop.len = sizeof(mode);
NS_ENSURE_TRUE_VOID(sBtInterface);
int ret = sBtInterface->set_adapter_property(&prop);
if (ret != BT_STATUS_SUCCESS) {
BT_LOGR("%s: Fail to set: BT_SCAN_MODE_CONNECTABLE", __FUNCTION__);
}
// Event 'AdapterAdded' has to be fired after enabled to notify Gaia
// that BluetoothAdapter is ready.
BluetoothSignal signal(NS_LITERAL_STRING("AdapterAdded"),
NS_LITERAL_STRING(KEY_MANAGER), true);
nsRefPtr<DistributeBluetoothSignalTask>
t = new DistributeBluetoothSignalTask(signal);
if (NS_FAILED(NS_DispatchToMainThread(t))) {
BT_WARNING("Failed to dispatch to main thread!");
}
}
static void static void
AdapterStateChangeCallback(bt_state_t aStatus) AdapterStateChangeCallback(bt_state_t aStatus)
{ {
@ -264,8 +275,9 @@ AdapterStateChangeCallback(bt_state_t aStatus)
lock.Notify(); lock.Notify();
} }
if (sIsBtEnabled) { if (sIsBtEnabled &&
Setup(); NS_FAILED(NS_DispatchToMainThread(new SetupAfterEnabledTask()))) {
BT_WARNING("Failed to dispatch to main thread!");
} }
} }

View File

@ -335,6 +335,24 @@ private:
BluetoothSignal mSignal; BluetoothSignal mSignal;
}; };
class TryFiringAdapterAddedTask : public nsRunnable
{
public:
NS_IMETHOD
Run()
{
MOZ_ASSERT(NS_IsMainThread());
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
bs->AdapterAddedReceived();
bs->TryFiringAdapterAdded();
return NS_OK;
}
};
static bool static bool
IsDBusMessageError(DBusMessage* aMsg, DBusError* aErr, nsAString& aErrorStr) IsDBusMessageError(DBusMessage* aMsg, DBusError* aErr, nsAString& aErrorStr)
{ {
@ -709,11 +727,7 @@ GetProperty(DBusMessageIter aIter, Properties* aPropertyTypes,
// Notify BluetoothManager whenever adapter name is ready. // Notify BluetoothManager whenever adapter name is ready.
if (!propertyValue.get_nsString().IsEmpty()) { if (!propertyValue.get_nsString().IsEmpty()) {
sAdapterNameIsReady = true; sAdapterNameIsReady = true;
BluetoothSignal signal(NS_LITERAL_STRING("AdapterAdded"), NS_DispatchToMainThread(new TryFiringAdapterAddedTask());
NS_LITERAL_STRING(KEY_MANAGER), sAdapterPath);
nsRefPtr<DistributeBluetoothSignalTask> task =
new DistributeBluetoothSignalTask(signal);
NS_DispatchToMainThread(task);
} }
} }