Bug 1152653 - Implement BluetoothGatt.oncharacteristicchanged. r=jocelyn, r=mrbkap

This commit is contained in:
Bruce Sun 2015-04-16 16:47:01 +08:00
parent b4c3f4ce16
commit 20b4932a5e
12 changed files with 174 additions and 3 deletions

View File

@ -692,6 +692,7 @@ GK_ATOM(oncallschanged, "oncallschanged")
GK_ATOM(oncardstatechange, "oncardstatechange")
GK_ATOM(oncfstatechange, "oncfstatechange")
GK_ATOM(onchange, "onchange")
GK_ATOM(oncharacteristicchanged, "oncharacteristicchanged")
GK_ATOM(onchargingchange, "onchargingchange")
GK_ATOM(onchargingtimechange, "onchargingtimechange")
GK_ATOM(onchecking, "onchecking")

View File

@ -227,6 +227,12 @@ extern bool gBluetoothDebugFlag;
*/
#define REQUEST_MEDIA_PLAYSTATUS_ID "requestmediaplaystatus"
/**
* When the value of a characteristic of a remote BLE device changes, we'll
* dispatch an event
*/
#define GATT_CHARACTERISTIC_CHANGED_ID "characteristicchanged"
/**
* When a remote BLE device gets connected / disconnected, we'll dispatch an
* event
@ -722,7 +728,7 @@ struct BluetoothGattNotifyParam {
BluetoothGattServiceId mServiceId;
BluetoothGattId mCharId;
uint16_t mLength;
uint8_t mIsNotify;
bool mIsNotify;
};
END_BLUETOOTH_NAMESPACE

View File

@ -1607,7 +1607,39 @@ BluetoothGattManager::RegisterNotificationNotification(
void
BluetoothGattManager::NotifyNotification(
int aConnId, const BluetoothGattNotifyParam& aNotifyParam)
{ }
{
MOZ_ASSERT(NS_IsMainThread());
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE_VOID(bs);
size_t index = sClients->IndexOf(aConnId, 0 /* Start */, ConnIdComparator());
NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
// Notify BluetoothGattCharacteristic to update characteristic value
nsString path;
GeneratePathFromGattId(aNotifyParam.mCharId, path);
nsTArray<uint8_t> value;
value.AppendElements(aNotifyParam.mValue, aNotifyParam.mLength);
bs->DistributeSignal(NS_LITERAL_STRING("CharacteristicValueUpdated"),
path,
BluetoothValue(value));
// Notify BluetoothGatt for characteristic changed
nsTArray<BluetoothNamedValue> ids;
ids.AppendElement(BluetoothNamedValue(NS_LITERAL_STRING("serviceId"),
aNotifyParam.mServiceId));
ids.AppendElement(BluetoothNamedValue(NS_LITERAL_STRING("charId"),
aNotifyParam.mCharId));
bs->DistributeSignal(NS_LITERAL_STRING(GATT_CHARACTERISTIC_CHANGED_ID),
client->mAppUuid,
BluetoothValue(ids));
}
void
BluetoothGattManager::ReadCharacteristicNotification(
@ -1641,6 +1673,17 @@ BluetoothGattManager::ReadCharacteristicNotification(
path,
BluetoothValue(value));
// Notify BluetoothGatt for characteristic changed
nsTArray<BluetoothNamedValue> ids;
ids.AppendElement(BluetoothNamedValue(NS_LITERAL_STRING("serviceId"),
aReadParam.mServiceId));
ids.AppendElement(BluetoothNamedValue(NS_LITERAL_STRING("charId"),
aReadParam.mCharId));
bs->DistributeSignal(NS_LITERAL_STRING(GATT_CHARACTERISTIC_CHANGED_ID),
client->mAppUuid,
BluetoothValue(ids));
// Resolve the promise
DispatchReplySuccess(runnable, BluetoothValue(value));
} else if (!client->mReadCharacteristicState.mAuthRetry &&

View File

@ -321,7 +321,7 @@ Convert(const btgatt_notify_params_t& aIn, BluetoothGattNotifyParam& aOut)
memcpy(aOut.mValue, aIn.value, aIn.len);
aOut.mLength = aIn.len;
aOut.mIsNotify = aIn.is_notify;
aOut.mIsNotify = (aIn.is_notify != 0);
return NS_OK;
}

View File

@ -11,6 +11,7 @@
#include "mozilla/dom/bluetooth/BluetoothGatt.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
#include "mozilla/dom/BluetoothGattBinding.h"
#include "mozilla/dom/BluetoothGattCharacteristicEvent.h"
#include "mozilla/dom/Promise.h"
#include "nsIUUIDGenerator.h"
#include "nsServiceManagerUtils.h"
@ -277,6 +278,42 @@ BluetoothGatt::HandleServicesDiscovered(const BluetoothValue& aValue)
BluetoothGattBinding::ClearCachedServicesValue(this);
}
void
BluetoothGatt::HandleCharacteristicChanged(const BluetoothValue& aValue)
{
MOZ_ASSERT(aValue.type() == BluetoothValue::TArrayOfBluetoothNamedValue);
const InfallibleTArray<BluetoothNamedValue>& ids =
aValue.get_ArrayOfBluetoothNamedValue();
MOZ_ASSERT(ids.Length() == 2); // ServiceId, CharId
MOZ_ASSERT(ids[0].name().EqualsLiteral("serviceId"));
MOZ_ASSERT(ids[0].value().type() == BluetoothValue::TBluetoothGattServiceId);
MOZ_ASSERT(ids[1].name().EqualsLiteral("charId"));
MOZ_ASSERT(ids[1].value().type() == BluetoothValue::TBluetoothGattId);
size_t index = mServices.IndexOf(ids[0].value().get_BluetoothGattServiceId());
NS_ENSURE_TRUE_VOID(index != mServices.NoIndex);
nsRefPtr<BluetoothGattService> service = mServices.ElementAt(index);
nsTArray<nsRefPtr<BluetoothGattCharacteristic>> chars;
service->GetCharacteristics(chars);
index = chars.IndexOf(ids[1].value().get_BluetoothGattId());
NS_ENSURE_TRUE_VOID(index != chars.NoIndex);
nsRefPtr<BluetoothGattCharacteristic> characteristic = chars.ElementAt(index);
// Dispatch characteristicchanged event to application
BluetoothGattCharacteristicEventInit init;
init.mCharacteristic = characteristic;
nsRefPtr<BluetoothGattCharacteristicEvent> event =
BluetoothGattCharacteristicEvent::Constructor(
this,
NS_LITERAL_STRING(GATT_CHARACTERISTIC_CHANGED_ID),
init);
DispatchTrustedEvent(event);
}
void
BluetoothGatt::Notify(const BluetoothSignal& aData)
{
@ -307,6 +344,8 @@ BluetoothGatt::Notify(const BluetoothSignal& aData)
}
mDiscoveringServices = false;
} else if (aData.name().EqualsLiteral(GATT_CHARACTERISTIC_CHANGED_ID)) {
HandleCharacteristicChanged(v);
} else {
BT_WARNING("Not handling GATT signal: %s",
NS_ConvertUTF16toUTF8(aData.name()).get());

View File

@ -50,6 +50,7 @@ public:
/****************************************************************************
* Event Handlers
***************************************************************************/
IMPL_EVENT_HANDLER(characteristicchanged);
IMPL_EVENT_HANDLER(connectionstatechanged);
/****************************************************************************
@ -104,6 +105,20 @@ private:
*/
void HandleServicesDiscovered(const BluetoothValue& aValue);
/**
* The value of a GATT characteristic has changed. In the mean time, the
* cached value of this GATT characteristic has already been updated. An
* 'characteristicchanged' event will be fired by this function.
*
* @param aValue [in] BluetoothValue which contains an array of
* BluetoothNamedValue. There are exact two elements in
* the array. The first element uses 'serviceId' as the
* name and uses BluetoothGattServiceId as the value. The
* second element uses 'charId' as the name and uses
* BluetoothGattId as the value.
*/
void HandleCharacteristicChanged(const BluetoothValue& aValue);
/****************************************************************************
* Variables
***************************************************************************/

View File

@ -163,4 +163,25 @@ private:
END_BLUETOOTH_NAMESPACE
/**
* Explicit Specialization of Function Templates
*
* Allows customizing the template code for a given set of template arguments.
* With this function template, nsTArray can handle comparison between
* 'nsRefPtr<BluetoothGattCharacteristic>' and 'BluetoothGattId' properly,
* including IndexOf() and Contains();
*/
template <>
class nsDefaultComparator <
nsRefPtr<mozilla::dom::bluetooth::BluetoothGattCharacteristic>,
mozilla::dom::bluetooth::BluetoothGattId> {
public:
bool Equals(
const nsRefPtr<mozilla::dom::bluetooth::BluetoothGattCharacteristic>& aChar,
const mozilla::dom::bluetooth::BluetoothGattId& aCharId) const
{
return aChar->GetCharacteristicId() == aCharId;
}
};
#endif

View File

@ -143,4 +143,25 @@ private:
END_BLUETOOTH_NAMESPACE
/**
* Explicit Specialization of Function Templates
*
* Allows customizing the template code for a given set of template arguments.
* With this function template, nsTArray can handle comparison between
* 'nsRefPtr<BluetoothGattService>' and 'BluetoothGattServiceId' properly,
* including IndexOf() and Contains();
*/
template <>
class nsDefaultComparator <
nsRefPtr<mozilla::dom::bluetooth::BluetoothGattService>,
mozilla::dom::bluetooth::BluetoothGattServiceId> {
public:
bool Equals(
const nsRefPtr<mozilla::dom::bluetooth::BluetoothGattService>& aService,
const mozilla::dom::bluetooth::BluetoothGattServiceId& aServiceId) const
{
return aService->GetServiceId() == aServiceId;
}
};
#endif

View File

@ -64,6 +64,10 @@ const kEventConstructors = {
return new BluetoothDiscoveryStateChangedEvent(aName, aProps);
},
},
BluetoothGattCharacteristicEvent: { create: function (aName, aProps) {
return new BluetoothGattCharacteristicEvent(aName, aProps);
},
},
BluetoothPairingEvent: { create: function (aName, aProps) {
return new BluetoothPairingEvent(aName, aProps);
},

View File

@ -11,6 +11,8 @@ interface BluetoothGatt : EventTarget
readonly attribute sequence<BluetoothGattService> services;
readonly attribute BluetoothConnectionState connectionState;
// Fired when the value of any characteristic changed
attribute EventHandler oncharacteristicchanged;
// Fired when attribute connectionState changed
attribute EventHandler onconnectionstatechanged;

View File

@ -0,0 +1,18 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
[CheckPermissions="bluetooth",
Constructor(DOMString type,
optional BluetoothGattCharacteristicEventInit eventInitDict)]
interface BluetoothGattCharacteristicEvent : Event
{
readonly attribute BluetoothGattCharacteristic characteristic;
};
dictionary BluetoothGattCharacteristicEventInit : EventInit
{
required BluetoothGattCharacteristic characteristic;
};

View File

@ -792,6 +792,7 @@ if CONFIG['MOZ_B2G_BT']:
GENERATED_EVENTS_WEBIDL_FILES += [
'BluetoothAdapterEvent.webidl',
'BluetoothAttributeEvent.webidl',
'BluetoothGattCharacteristicEvent.webidl',
'BluetoothPairingEvent.webidl',
]
else: