Bug 1054242: Implement Bluetooth Core notifications (under bluetooth2/), r=btian

This patch adds the Gecko-side of the Core notifications. The current
implementation of the notification methods has been copied from the
repsective Bluedroid callback methods, with only minor changes to adapt
them to Gecko data types.
This commit is contained in:
Thomas Zimmermann 2014-09-02 12:38:45 +02:00
parent 374b11c2ec
commit ba20a966b7
4 changed files with 433 additions and 2 deletions

View File

@ -20,7 +20,6 @@
#include "BluetoothA2dpManager.h"
#include "BluetoothHfpManager.h"
#include "BluetoothInterface.h"
#include "BluetoothOppManager.h"
#include "BluetoothProfileController.h"
#include "BluetoothReplyRunnable.h"
@ -342,7 +341,7 @@ public:
/**
* AdapterPropertiesCallback will be called after enable() but before
* AdapterStateChangeCallback is called. At that moment, both
* AdapterStateChangedCallback is called. At that moment, both
* BluetoothManager/BluetoothAdapter does not register observer yet.
*/
static void
@ -1779,3 +1778,367 @@ void
BluetoothServiceBluedroid::ToggleCalls(BluetoothReplyRunnable* aRunnable)
{
}
//
// Bluetooth notifications
//
void
BluetoothServiceBluedroid::AdapterStateChangedNotification(bool aState)
{
MOZ_ASSERT(NS_IsMainThread());
BT_LOGR("BT_STATE: %d", aState);
sAdapterEnabled = aState;
if (!sAdapterEnabled &&
NS_FAILED(NS_DispatchToMainThread(new CleanupTask()))) {
BT_WARNING("Failed to dispatch to main thread!");
return;
}
nsRefPtr<nsRunnable> runnable =
new BluetoothService::ToggleBtAck(sAdapterEnabled);
if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
BT_WARNING("Failed to dispatch to main thread!");
return;
}
if (sAdapterEnabled &&
NS_FAILED(NS_DispatchToMainThread(new SetupAfterEnabledTask()))) {
BT_WARNING("Failed to dispatch to main thread!");
return;
}
// Redirect to main thread to avoid racing problem
NS_DispatchToMainThread(new AdapterStateChangedCallbackTask());
}
/**
* AdapterPropertiesNotification will be called after enable() but
* before AdapterStateChangeNotification is called. At that moment,
* BluetoothManager and BluetoothAdapter, do not register observer
* yet.
*/
void
BluetoothServiceBluedroid::AdapterPropertiesNotification(
BluetoothStatus aStatus, int aNumProperties,
const BluetoothProperty* aProperties)
{
MOZ_ASSERT(NS_IsMainThread());
InfallibleTArray<BluetoothNamedValue> propertiesArray;
for (int i = 0; i < aNumProperties; i++) {
const BluetoothProperty& p = aProperties[i];
if (p.mType == PROPERTY_BDADDR) {
sAdapterBdAddress = p.mString;
BT_APPEND_NAMED_VALUE(propertiesArray, "Address", sAdapterBdAddress);
} else if (p.mType == PROPERTY_BDNAME) {
sAdapterBdName = p.mString;
BT_APPEND_NAMED_VALUE(propertiesArray, "Name", sAdapterBdName);
} else if (p.mType == PROPERTY_ADAPTER_SCAN_MODE) {
sAdapterDiscoverable =
(p.mScanMode == SCAN_MODE_CONNECTABLE_DISCOVERABLE);
BT_APPEND_NAMED_VALUE(propertiesArray, "Discoverable",
sAdapterDiscoverable);
} else if (p.mType == PROPERTY_ADAPTER_BONDED_DEVICES) {
// We have to cache addresses of bonded devices. Unlike BlueZ,
// Bluedroid would not send another PROPERTY_ADAPTER_BONDED_DEVICES
// event after bond completed.
BT_LOGD("Adapter property: BONDED_DEVICES. Count: %d",
p.mStringArray.Length());
nsTArray<nsString> pairedDeviceAddresses;
for (size_t index = 0; index < p.mStringArray.Length(); index++) {
pairedDeviceAddresses.AppendElement(p.mStringArray[index]);
}
BT_APPEND_NAMED_VALUE(propertiesArray, "PairedDevices", pairedDeviceAddresses);
} else {
BT_LOGD("Unhandled adapter property type: %d", p.mType);
continue;
}
}
NS_ENSURE_TRUE_VOID(propertiesArray.Length() > 0);
BluetoothValue value(propertiesArray);
BluetoothSignal signal(NS_LITERAL_STRING("PropertyChanged"),
NS_LITERAL_STRING(KEY_ADAPTER), value);
nsRefPtr<DistributeBluetoothSignalTask>
t = new DistributeBluetoothSignalTask(signal);
if (NS_FAILED(NS_DispatchToMainThread(t))) {
BT_WARNING("Failed to dispatch to main thread!");
}
// Redirect to main thread to avoid racing problem
NS_DispatchToMainThread(new AdapterPropertiesCallbackTask());
}
/**
* RemoteDevicePropertiesNotification will be called
*
* (1) automatically by Bluedroid when BT is turning on,
* (2) as result of GetRemoteDeviceProperties, or
* (3) as result of GetRemoteServices.
*/
void
BluetoothServiceBluedroid::RemoteDevicePropertiesNotification(
BluetoothStatus aStatus, const nsAString& aBdAddr,
int aNumProperties, const BluetoothProperty* aProperties)
{
MOZ_ASSERT(NS_IsMainThread());
InfallibleTArray<BluetoothNamedValue> propertiesArray;
BT_APPEND_NAMED_VALUE(propertiesArray, "Address", nsString(aBdAddr));
for (int i = 0; i < aNumProperties; ++i) {
const BluetoothProperty& p = aProperties[i];
if (p.mType == PROPERTY_BDNAME) {
BT_APPEND_NAMED_VALUE(propertiesArray, "Name", p.mString);
} else if (p.mType == PROPERTY_CLASS_OF_DEVICE) {
uint32_t cod = p.mUint32;
BT_APPEND_NAMED_VALUE(propertiesArray, "Cod", cod);
} else if (p.mType == PROPERTY_UUIDS) {
nsTArray<nsString> uuids;
// Construct a sorted uuid set
for (uint32_t index = 0; index < p.mUuidArray.Length(); ++index) {
nsAutoString uuid;
UuidToString(p.mUuidArray[index], uuid);
if (!uuids.Contains(uuid)) { // filter out duplicate uuids
uuids.InsertElementSorted(uuid);
}
}
BT_APPEND_NAMED_VALUE(propertiesArray, "UUIDs", uuids);
} else {
BT_LOGD("Other non-handled device properties. Type: %d", p.mType);
}
}
// Redirect to main thread to avoid racing problem
NS_DispatchToMainThread(
new RemoteDevicePropertiesCallbackTask(propertiesArray, aBdAddr));
}
void
BluetoothServiceBluedroid::DeviceFoundNotification(
int aNumProperties, const BluetoothProperty* aProperties)
{
MOZ_ASSERT(NS_IsMainThread());
BluetoothValue propertyValue;
InfallibleTArray<BluetoothNamedValue> propertiesArray;
for (int i = 0; i < aNumProperties; i++) {
const BluetoothProperty& p = aProperties[i];
if (p.mType == PROPERTY_BDADDR) {
BT_APPEND_NAMED_VALUE(propertiesArray, "Address", p.mString);
} else if (p.mType == PROPERTY_BDNAME) {
BT_APPEND_NAMED_VALUE(propertiesArray, "Name", p.mString);
} else if (p.mType == PROPERTY_CLASS_OF_DEVICE) {
BT_APPEND_NAMED_VALUE(propertiesArray, "Cod", p.mUint32);
} else if (p.mType == PROPERTY_UUIDS) {
nsTArray<nsString> uuids;
// Construct a sorted uuid set
for (uint32_t index = 0; index < p.mUuidArray.Length(); ++index) {
nsAutoString uuid;
UuidToString(p.mUuidArray[index], uuid);
if (!uuids.Contains(uuid)) { // filter out duplicate uuids
uuids.InsertElementSorted(uuid);
}
}
BT_APPEND_NAMED_VALUE(propertiesArray, "UUIDs", uuids);
} else {
BT_LOGD("Not handled remote device property: %d", p.mType);
}
}
BluetoothValue value = propertiesArray;
BluetoothSignal signal(NS_LITERAL_STRING("DeviceFound"),
NS_LITERAL_STRING(KEY_ADAPTER), value);
nsRefPtr<DistributeBluetoothSignalTask>
t = new DistributeBluetoothSignalTask(signal);
if (NS_FAILED(NS_DispatchToMainThread(t))) {
BT_WARNING("Failed to dispatch to main thread!");
}
}
void
BluetoothServiceBluedroid::DiscoveryStateChangedNotification(bool aState)
{
MOZ_ASSERT(NS_IsMainThread());
sAdapterDiscovering = aState;
// Redirect to main thread to avoid racing problem
NS_DispatchToMainThread(new DiscoveryStateChangedCallbackTask());
}
void
BluetoothServiceBluedroid::PinRequestNotification(const nsAString& aRemoteBdAddr,
const nsAString& aBdName,
uint32_t aCod)
{
MOZ_ASSERT(NS_IsMainThread());
InfallibleTArray<BluetoothNamedValue> propertiesArray;
BT_APPEND_NAMED_VALUE(propertiesArray, "address", nsString(aRemoteBdAddr));
BT_APPEND_NAMED_VALUE(propertiesArray, "passkey", EmptyString());
BT_APPEND_NAMED_VALUE(propertiesArray, "type",
NS_LITERAL_STRING(PAIRING_REQ_TYPE_ENTERPINCODE));
BluetoothSignal signal(NS_LITERAL_STRING("PairingRequest"),
NS_LITERAL_STRING(KEY_ADAPTER),
BluetoothValue(propertiesArray));
nsRefPtr<DistributeBluetoothSignalTask> task =
new DistributeBluetoothSignalTask(signal);
if (NS_FAILED(NS_DispatchToMainThread(task))) {
BT_WARNING("Failed to dispatch to main thread!");
}
}
void
BluetoothServiceBluedroid::SspRequestNotification(
const nsAString& aRemoteBdAddr, const nsAString& aBdName, uint32_t aCod,
BluetoothSspVariant aPairingVariant, uint32_t aPasskey)
{
MOZ_ASSERT(NS_IsMainThread());
InfallibleTArray<BluetoothNamedValue> propertiesArray;
nsAutoString passkey;
nsAutoString pairingType;
/**
* Assign pairing request type and passkey based on the pairing variant.
*
* passkey value based on pairing request type:
* 1) aPasskey: PAIRING_REQ_TYPE_CONFIRMATION and
* PAIRING_REQ_TYPE_DISPLAYPASSKEY
* 2) empty string: PAIRING_REQ_TYPE_CONSENT
*/
switch (aPairingVariant) {
case SSP_VARIANT_PASSKEY_CONFIRMATION:
pairingType.AssignLiteral(PAIRING_REQ_TYPE_CONFIRMATION);
passkey.AppendInt(aPasskey);
break;
case SSP_VARIANT_PASSKEY_NOTIFICATION:
pairingType.AssignLiteral(PAIRING_REQ_TYPE_DISPLAYPASSKEY);
passkey.AppendInt(aPasskey);
break;
case SSP_VARIANT_CONSENT:
pairingType.AssignLiteral(PAIRING_REQ_TYPE_CONSENT);
break;
default:
BT_WARNING("Unhandled SSP Bonding Variant: %d", aPairingVariant);
return;
}
BT_APPEND_NAMED_VALUE(propertiesArray, "address", nsString(aRemoteBdAddr));
BT_APPEND_NAMED_VALUE(propertiesArray, "passkey", passkey);
BT_APPEND_NAMED_VALUE(propertiesArray, "type", pairingType);
BluetoothSignal signal(NS_LITERAL_STRING("PairingRequest"),
NS_LITERAL_STRING(KEY_ADAPTER),
BluetoothValue(propertiesArray));
nsRefPtr<DistributeBluetoothSignalTask> task =
new DistributeBluetoothSignalTask(signal);
if (NS_FAILED(NS_DispatchToMainThread(task))) {
BT_WARNING("Failed to dispatch to main thread!");
}
}
void
BluetoothServiceBluedroid::BondStateChangedNotification(
BluetoothStatus aStatus, const nsAString& aRemoteBdAddr,
BluetoothBondState aState)
{
MOZ_ASSERT(NS_IsMainThread());
if (aState == BOND_STATE_BONDING) {
// No need to handle bonding state
return;
}
bool bonded = (aState == BOND_STATE_BONDED);
// Update attribute BluetoothDevice.paired
InfallibleTArray<BluetoothNamedValue> propertiesArray;
BT_APPEND_NAMED_VALUE(propertiesArray, "Paired", bonded);
BluetoothSignal deviceSignal(NS_LITERAL_STRING("PropertyChanged"),
nsString(aRemoteBdAddr),
BluetoothValue(propertiesArray));
NS_DispatchToMainThread(new DistributeBluetoothSignalTask(deviceSignal));
propertiesArray.Clear();
// Append signal properties and notify adapter.
BT_APPEND_NAMED_VALUE(propertiesArray, "Address", nsString(aRemoteBdAddr));
BT_APPEND_NAMED_VALUE(propertiesArray, "Paired", bonded);
nsString signalName = bonded ? NS_LITERAL_STRING(DEVICE_PAIRED_ID)
: NS_LITERAL_STRING(DEVICE_UNPAIRED_ID);
BluetoothSignal adapterSignal(signalName,
NS_LITERAL_STRING(KEY_ADAPTER),
BluetoothValue(propertiesArray));
NS_DispatchToMainThread(new DistributeBluetoothSignalTask(adapterSignal));
// Redirect to main thread to avoid racing problem
NS_DispatchToMainThread(new BondStateChangedCallbackTask(bonded));
}
void
BluetoothServiceBluedroid::AclStateChangedNotification(
BluetoothStatus aStatus, const nsAString& aRemoteBdAddr, bool aState)
{
MOZ_ASSERT(NS_IsMainThread());
// FIXME: This will be implemented in the later patchset
}
void
BluetoothServiceBluedroid::DutModeRecvNotification(uint16_t aOpcode,
const uint8_t* aBuf,
uint8_t aLen)
{
MOZ_ASSERT(NS_IsMainThread());
// FIXME: This will be implemented in the later patchset
}
void
BluetoothServiceBluedroid::LeTestModeNotification(BluetoothStatus aStatus,
uint16_t aNumPackets)
{
MOZ_ASSERT(NS_IsMainThread());
// FIXME: This will be implemented in the later patchset
}

View File

@ -10,11 +10,13 @@
#include <hardware/bluetooth.h>
#include "BluetoothCommon.h"
#include "BluetoothInterface.h"
#include "BluetoothService.h"
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothServiceBluedroid : public BluetoothService
, public BluetoothNotificationHandler
{
public:
static const bt_interface_t* GetBluetoothInterface();
@ -155,6 +157,46 @@ public:
virtual nsresult
SendInputMessage(const nsAString& aDeviceAddresses,
const nsAString& aMessage) MOZ_OVERRIDE;
//
// Bluetooth notifications
//
virtual void AdapterStateChangedNotification(bool aState) MOZ_OVERRIDE;
virtual void AdapterPropertiesNotification(
BluetoothStatus aStatus, int aNumProperties,
const BluetoothProperty* aProperties) MOZ_OVERRIDE;
virtual void RemoteDevicePropertiesNotification(
BluetoothStatus aStatus, const nsAString& aBdAddr,
int aNumProperties, const BluetoothProperty* aProperties) MOZ_OVERRIDE;
virtual void DeviceFoundNotification(
int aNumProperties, const BluetoothProperty* aProperties) MOZ_OVERRIDE;
virtual void DiscoveryStateChangedNotification(bool aState) MOZ_OVERRIDE;
virtual void PinRequestNotification(const nsAString& aRemoteBdAddr,
const nsAString& aBdName,
uint32_t aCod) MOZ_OVERRIDE;
virtual void SspRequestNotification(const nsAString& aRemoteBdAddr,
const nsAString& aBdName,
uint32_t aCod,
BluetoothSspVariant aPairingVariant,
uint32_t aPasskey) MOZ_OVERRIDE;
virtual void BondStateChangedNotification(
BluetoothStatus aStatus, const nsAString& aRemoteBdAddr,
BluetoothBondState aState) MOZ_OVERRIDE;
virtual void AclStateChangedNotification(BluetoothStatus aStatus,
const nsAString& aRemoteBdAddr,
bool aState) MOZ_OVERRIDE;
virtual void DutModeRecvNotification(uint16_t aOpcode,
const uint8_t* aBuf,
uint8_t aLen) MOZ_OVERRIDE;
virtual void LeTestModeNotification(BluetoothStatus aStatus,
uint16_t aNumPackets) MOZ_OVERRIDE;
};
END_BLUETOOTH_NAMESPACE

View File

@ -72,6 +72,29 @@ UuidToString(bt_uuid_t* aUuid, nsAString& aString) {
aString.AssignLiteral(uuidStr);
}
void
UuidToString(const BluetoothUuid& aUuid, nsAString& aString)
{
char uuidStr[37];
uint32_t uuid0, uuid4;
uint16_t uuid1, uuid2, uuid3, uuid5;
memcpy(&uuid0, &aUuid.mUuid[0], sizeof(uint32_t));
memcpy(&uuid1, &aUuid.mUuid[4], sizeof(uint16_t));
memcpy(&uuid2, &aUuid.mUuid[6], sizeof(uint16_t));
memcpy(&uuid3, &aUuid.mUuid[8], sizeof(uint16_t));
memcpy(&uuid4, &aUuid.mUuid[10], sizeof(uint32_t));
memcpy(&uuid5, &aUuid.mUuid[14], sizeof(uint16_t));
sprintf(uuidStr, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x",
ntohl(uuid0), ntohs(uuid1),
ntohs(uuid2), ntohs(uuid3),
ntohl(uuid4), ntohs(uuid5));
aString.Truncate();
aString.AssignLiteral(uuidStr);
}
bool
SetJsObject(JSContext* aContext,
const BluetoothValue& aValue,

View File

@ -29,6 +29,9 @@ BdAddressTypeToString(bt_bdaddr_t* aBdAddressType,
void
UuidToString(bt_uuid_t* aUuid, nsAString& aString);
void
UuidToString(const BluetoothUuid& aUuid, nsAString& aString);
bool
SetJsObject(JSContext* aContext,
const BluetoothValue& aValue,