Merge b2g-inbound to m-c a=merge CLOSED TREE

This commit is contained in:
Wes Kocher 2015-03-23 16:47:58 -07:00
commit e62ecec712
51 changed files with 1467 additions and 95 deletions

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="8eac260ee81a8aca05770d18c5736536d44ee7a7"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="efebbafd12fc42ddcd378948b683a51106517660"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8eac260ee81a8aca05770d18c5736536d44ee7a7"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="efebbafd12fc42ddcd378948b683a51106517660"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="8eac260ee81a8aca05770d18c5736536d44ee7a7"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="efebbafd12fc42ddcd378948b683a51106517660"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="b685e3aab4fde7624d78993877a8f7910f2a5f06"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="8eac260ee81a8aca05770d18c5736536d44ee7a7"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="efebbafd12fc42ddcd378948b683a51106517660"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="52775e03a2d8532429dff579cb2cd56718e488c3">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="8eac260ee81a8aca05770d18c5736536d44ee7a7"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="efebbafd12fc42ddcd378948b683a51106517660"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8eac260ee81a8aca05770d18c5736536d44ee7a7"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="efebbafd12fc42ddcd378948b683a51106517660"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="8eac260ee81a8aca05770d18c5736536d44ee7a7"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="efebbafd12fc42ddcd378948b683a51106517660"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="8eac260ee81a8aca05770d18c5736536d44ee7a7"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="efebbafd12fc42ddcd378948b683a51106517660"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="b685e3aab4fde7624d78993877a8f7910f2a5f06"/>

View File

@ -1,9 +1,9 @@
{
"git": {
"git_revision": "8eac260ee81a8aca05770d18c5736536d44ee7a7",
"git_revision": "efebbafd12fc42ddcd378948b683a51106517660",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
"revision": "1400d176ecef76d06b012fb082c246eb17d1d30f",
"revision": "d8e53e5d917b1ce79aea842e8340ce82799cac3e",
"repo_path": "integration/gaia-central"
}

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="8eac260ee81a8aca05770d18c5736536d44ee7a7"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="efebbafd12fc42ddcd378948b683a51106517660"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="b685e3aab4fde7624d78993877a8f7910f2a5f06"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="52775e03a2d8532429dff579cb2cd56718e488c3">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="8eac260ee81a8aca05770d18c5736536d44ee7a7"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="efebbafd12fc42ddcd378948b683a51106517660"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -159,6 +159,18 @@ DOMInterfaces = {
'nativeType': 'mozilla::dom::bluetooth::BluetoothGatt',
},
'BluetoothGattCharacteristic': {
'nativeType': 'mozilla::dom::bluetooth::BluetoothGattCharacteristic',
},
'BluetoothGattDescriptor': {
'nativeType': 'mozilla::dom::bluetooth::BluetoothGattDescriptor',
},
'BluetoothGattService': {
'nativeType': 'mozilla::dom::bluetooth::BluetoothGattService',
},
'BluetoothManager': {
'nativeType': 'mozilla::dom::bluetooth::BluetoothManager',
},

View File

@ -285,6 +285,16 @@ enum BluetoothSspVariant {
struct BluetoothUuid {
uint8_t mUuid[16];
bool operator==(const BluetoothUuid& aOther) const
{
for (uint8_t i = 0; i < sizeof(mUuid); i++) {
if (mUuid[i] != aOther.mUuid[i]) {
return false;
}
}
return true;
}
};
struct BluetoothServiceRecord {
@ -547,11 +557,21 @@ struct BluetoothGattAdvData {
struct BluetoothGattId {
BluetoothUuid mUuid;
uint8_t mInstanceId;
bool operator==(const BluetoothGattId& aOther) const
{
return mUuid == aOther.mUuid && mInstanceId == aOther.mInstanceId;
}
};
struct BluetoothGattServiceId {
BluetoothGattId mId;
uint8_t mIsPrimary;
bool operator==(const BluetoothGattServiceId& aOther) const
{
return mId == aOther.mId && mIsPrimary == aOther.mIsPrimary;
}
};
struct BluetoothGattReadParam {

View File

@ -4,10 +4,10 @@
* 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/. */
#include "BluetoothReplyRunnable.h"
#include "BluetoothService.h"
#include "BluetoothUtils.h"
#include "mozilla/dom/bluetooth/BluetoothCommon.h"
#include "mozilla/dom/bluetooth/BluetoothGatt.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
#include "mozilla/dom/BluetoothGattBinding.h"
@ -20,14 +20,9 @@ using namespace mozilla::dom;
USING_BLUETOOTH_NAMESPACE
NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothGatt)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothGatt,
DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothGatt,
DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_INHERITED(BluetoothGatt,
DOMEventTargetHelper,
mServices)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothGatt)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
@ -42,6 +37,7 @@ BluetoothGatt::BluetoothGatt(nsPIDOMWindow* aWindow,
, mClientIf(0)
, mConnectionState(BluetoothConnectionState::Disconnected)
, mDeviceAddr(aDeviceAddr)
, mDiscoveringServices(false)
{
MOZ_ASSERT(aWindow);
MOZ_ASSERT(!mDeviceAddr.IsEmpty());
@ -216,6 +212,36 @@ BluetoothGatt::ReadRemoteRssi(ErrorResult& aRv)
return promise.forget();
}
already_AddRefed<Promise>
BluetoothGatt::DiscoverServices(ErrorResult& aRv)
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
if (!global) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
BT_ENSURE_TRUE_REJECT(
mConnectionState == BluetoothConnectionState::Connected &&
!mDiscoveringServices,
NS_ERROR_DOM_INVALID_STATE_ERR);
BluetoothService* bs = BluetoothService::Get();
BT_ENSURE_TRUE_REJECT(bs, NS_ERROR_NOT_AVAILABLE);
mDiscoveringServices = true;
nsRefPtr<BluetoothReplyRunnable> result =
new BluetoothVoidReplyRunnable(nullptr /* DOMRequest */,
promise,
NS_LITERAL_STRING("DiscoverGattServices"));
bs->DiscoverGattServicesInternal(mAppUuid, result);
return promise.forget();
}
void
BluetoothGatt::UpdateConnectionState(BluetoothConnectionState aState)
{
@ -235,6 +261,22 @@ BluetoothGatt::UpdateConnectionState(BluetoothConnectionState aState)
DispatchTrustedEvent(event);
}
void
BluetoothGatt::HandleServicesDiscovered(const BluetoothValue& aValue)
{
MOZ_ASSERT(aValue.type() == BluetoothValue::TArrayOfBluetoothGattServiceId);
const InfallibleTArray<BluetoothGattServiceId>& serviceIds =
aValue.get_ArrayOfBluetoothGattServiceId();
for (uint32_t i = 0; i < serviceIds.Length(); i++) {
mServices.AppendElement(new BluetoothGattService(
GetParentObject(), mAppUuid, serviceIds[i]));
}
BluetoothGattBinding::ClearCachedServicesValue(this);
}
void
BluetoothGatt::Notify(const BluetoothSignal& aData)
{
@ -253,6 +295,18 @@ BluetoothGatt::Notify(const BluetoothSignal& aData)
v.get_bool() ? BluetoothConnectionState::Connected
: BluetoothConnectionState::Disconnected;
UpdateConnectionState(state);
} else if (aData.name().EqualsLiteral("ServicesDiscovered")) {
HandleServicesDiscovered(v);
} else if (aData.name().EqualsLiteral("DiscoverCompleted")) {
MOZ_ASSERT(v.type() == BluetoothValue::Tbool);
bool isDiscoverSuccess = v.get_bool();
if (!isDiscoverSuccess) { // Clean all discovered attributes if failed
mServices.Clear();
BluetoothGattBinding::ClearCachedServicesValue(this);
}
mDiscoveringServices = false;
} else {
BT_WARNING("Not handling GATT signal: %s",
NS_ConvertUTF16toUTF8(aData.name()).get());

View File

@ -11,6 +11,7 @@
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/dom/BluetoothGattBinding.h"
#include "mozilla/dom/bluetooth/BluetoothCommon.h"
#include "mozilla/dom/bluetooth/BluetoothGattService.h"
#include "nsCOMPtr.h"
namespace mozilla {
@ -41,6 +42,11 @@ public:
return mConnectionState;
}
void GetServices(nsTArray<nsRefPtr<BluetoothGattService>>& aServices) const
{
aServices = mServices;
}
/****************************************************************************
* Event Handlers
***************************************************************************/
@ -51,6 +57,7 @@ public:
***************************************************************************/
already_AddRefed<Promise> Connect(ErrorResult& aRv);
already_AddRefed<Promise> Disconnect(ErrorResult& aRv);
already_AddRefed<Promise> DiscoverServices(ErrorResult& aRv);
already_AddRefed<Promise> ReadRemoteRssi(ErrorResult& aRv);
/****************************************************************************
@ -87,6 +94,15 @@ private:
*/
void GenerateUuid(nsAString &aUuidString);
/**
* Add newly discovered GATT services into mServices and update the cache
* value of mServices.
*
* @param aValue [in] BluetoothValue which contains an array of
* BluetoothGattServiceId of all discovered services.
*/
void HandleServicesDiscovered(const BluetoothValue& aValue);
/****************************************************************************
* Variables
***************************************************************************/
@ -110,6 +126,16 @@ private:
* Address of the remote device.
*/
nsString mDeviceAddr;
/**
* Array of discovered services from the remote GATT server.
*/
nsTArray<nsRefPtr<BluetoothGattService>> mServices;
/**
* Indicate whether there is ongoing discoverServices request or not.
*/
bool mDiscoveringServices;
};
END_BLUETOOTH_NAMESPACE

View File

@ -0,0 +1,97 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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/. */
#include "BluetoothService.h"
#include "BluetoothUtils.h"
#include "mozilla/dom/BluetoothGattCharacteristicBinding.h"
#include "mozilla/dom/bluetooth/BluetoothCommon.h"
#include "mozilla/dom/bluetooth/BluetoothGattCharacteristic.h"
#include "mozilla/dom/bluetooth/BluetoothGattDescriptor.h"
#include "mozilla/dom/bluetooth/BluetoothGattService.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
using namespace mozilla;
using namespace mozilla::dom;
USING_BLUETOOTH_NAMESPACE
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(
BluetoothGattCharacteristic, mOwner, mService, mDescriptors)
NS_IMPL_CYCLE_COLLECTING_ADDREF(BluetoothGattCharacteristic)
NS_IMPL_CYCLE_COLLECTING_RELEASE(BluetoothGattCharacteristic)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BluetoothGattCharacteristic)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
BluetoothGattCharacteristic::BluetoothGattCharacteristic(
nsPIDOMWindow* aOwner,
BluetoothGattService* aService,
const BluetoothGattId& aCharId)
: mOwner(aOwner)
, mService(aService)
, mCharId(aCharId)
{
MOZ_ASSERT(aOwner);
MOZ_ASSERT(mService);
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE_VOID(bs);
// Generate bluetooth signal path and a string representation to provide uuid
// of this characteristic to applications
nsString path;
GeneratePathFromGattId(mCharId, path, mUuidStr);
bs->RegisterBluetoothSignalHandler(path, this);
}
BluetoothGattCharacteristic::~BluetoothGattCharacteristic()
{
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE_VOID(bs);
nsString path;
GeneratePathFromGattId(mCharId, path);
bs->UnregisterBluetoothSignalHandler(path, this);
}
void
BluetoothGattCharacteristic::HandleDescriptorsDiscovered(
const BluetoothValue& aValue)
{
MOZ_ASSERT(aValue.type() == BluetoothValue::TArrayOfBluetoothGattId);
const InfallibleTArray<BluetoothGattId>& descriptorIds =
aValue.get_ArrayOfBluetoothGattId();
for (uint32_t i = 0; i < descriptorIds.Length(); i++) {
mDescriptors.AppendElement(new BluetoothGattDescriptor(
GetParentObject(), this, descriptorIds[i]));
}
BluetoothGattCharacteristicBinding::ClearCachedDescriptorsValue(this);
}
void
BluetoothGattCharacteristic::Notify(const BluetoothSignal& aData)
{
BT_LOGD("[D] %s", NS_ConvertUTF16toUTF8(aData.name()).get());
BluetoothValue v = aData.value();
if (aData.name().EqualsLiteral("DescriptorsDiscovered")) {
HandleDescriptorsDiscovered(v);
} else {
BT_WARNING("Not handling GATT Characteristic signal: %s",
NS_ConvertUTF16toUTF8(aData.name()).get());
}
}
JSObject*
BluetoothGattCharacteristic::WrapObject(JSContext* aContext,
JS::Handle<JSObject*> aGivenProto)
{
return BluetoothGattCharacteristicBinding::Wrap(aContext, this, aGivenProto);
}

View File

@ -0,0 +1,120 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef mozilla_dom_bluetooth_bluetoothgattcharacteristic_h__
#define mozilla_dom_bluetooth_bluetoothgattcharacteristic_h__
#include "mozilla/Attributes.h"
#include "mozilla/dom/BluetoothGattCharacteristicBinding.h"
#include "mozilla/dom/bluetooth/BluetoothCommon.h"
#include "mozilla/dom/bluetooth/BluetoothGattDescriptor.h"
#include "nsCOMPtr.h"
#include "nsWrapperCache.h"
#include "nsPIDOMWindow.h"
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothGattService;
class BluetoothSignal;
class BluetoothValue;
class BluetoothGattCharacteristic final : public nsISupports
, public nsWrapperCache
, public BluetoothSignalObserver
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(BluetoothGattCharacteristic)
/****************************************************************************
* Attribute Getters
***************************************************************************/
BluetoothGattService* Service() const
{
return mService;
}
void GetDescriptors(
nsTArray<nsRefPtr<BluetoothGattDescriptor>>& aDescriptors) const
{
aDescriptors = mDescriptors;
}
void GetUuid(nsString& aUuidStr) const
{
aUuidStr = mUuidStr;
}
int InstanceId() const
{
return mCharId.mInstanceId;
}
/****************************************************************************
* Others
***************************************************************************/
const BluetoothGattId& GetCharacteristicId() const
{
return mCharId;
}
void Notify(const BluetoothSignal& aData); // BluetoothSignalObserver
nsPIDOMWindow* GetParentObject() const
{
return mOwner;
}
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
BluetoothGattCharacteristic(nsPIDOMWindow* aOwner,
BluetoothGattService* aService,
const BluetoothGattId& aCharId);
private:
~BluetoothGattCharacteristic();
/**
* Add newly discovered GATT descriptors into mDescriptors and update the
* cache value of mDescriptors.
*
* @param aValue [in] BluetoothValue which contains an array of
* BluetoothGattId of all discovered descriptors.
*/
void HandleDescriptorsDiscovered(const BluetoothValue& aValue);
/****************************************************************************
* Variables
***************************************************************************/
nsCOMPtr<nsPIDOMWindow> mOwner;
/**
* Service that this characteristic belongs to.
*/
nsRefPtr<BluetoothGattService> mService;
/**
* Array of discovered descriptors for this characteristic.
*/
nsTArray<nsRefPtr<BluetoothGattDescriptor>> mDescriptors;
/**
* GattId of this GATT characteristic which contains
* 1) mUuid: UUID of this characteristic in byte array format.
* 2) mInstanceId: Instance id of this characteristic.
*/
BluetoothGattId mCharId;
/**
* UUID string of this GATT characteristic.
*/
nsString mUuidStr;
};
END_BLUETOOTH_NAMESPACE
#endif

View File

@ -0,0 +1,54 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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/. */
#include "BluetoothService.h"
#include "BluetoothUtils.h"
#include "mozilla/dom/BluetoothGattDescriptorBinding.h"
#include "mozilla/dom/bluetooth/BluetoothCommon.h"
#include "mozilla/dom/bluetooth/BluetoothGattCharacteristic.h"
#include "mozilla/dom/bluetooth/BluetoothGattDescriptor.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
using namespace mozilla;
using namespace mozilla::dom;
USING_BLUETOOTH_NAMESPACE
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(
BluetoothGattDescriptor, mOwner, mCharacteristic)
NS_IMPL_CYCLE_COLLECTING_ADDREF(BluetoothGattDescriptor)
NS_IMPL_CYCLE_COLLECTING_RELEASE(BluetoothGattDescriptor)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BluetoothGattDescriptor)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
BluetoothGattDescriptor::BluetoothGattDescriptor(
nsPIDOMWindow* aOwner,
BluetoothGattCharacteristic* aCharacteristic,
const BluetoothGattId& aDescriptorId)
: mOwner(aOwner)
, mCharacteristic(aCharacteristic)
, mDescriptorId(aDescriptorId)
{
MOZ_ASSERT(aOwner);
MOZ_ASSERT(aCharacteristic);
// Generate a string representation to provide uuid of this descriptor to
// applications
ReversedUuidToString(aDescriptorId.mUuid, mUuidStr);
}
BluetoothGattDescriptor::~BluetoothGattDescriptor()
{
}
JSObject*
BluetoothGattDescriptor::WrapObject(JSContext* aContext,
JS::Handle<JSObject*> aGivenProto)
{
return BluetoothGattDescriptorBinding::Wrap(aContext, this, aGivenProto);
}

View File

@ -0,0 +1,88 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef mozilla_dom_bluetooth_bluetoothgattdescriptor_h__
#define mozilla_dom_bluetooth_bluetoothgattdescriptor_h__
#include "mozilla/Attributes.h"
#include "mozilla/dom/BluetoothGattDescriptorBinding.h"
#include "mozilla/dom/bluetooth/BluetoothCommon.h"
#include "nsCOMPtr.h"
#include "nsWrapperCache.h"
#include "nsPIDOMWindow.h"
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothGattCharacteristic;
class BluetoothSignal;
class BluetoothValue;
class BluetoothGattDescriptor final : public nsISupports
, public nsWrapperCache
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(BluetoothGattDescriptor)
/****************************************************************************
* Attribute Getters
***************************************************************************/
BluetoothGattCharacteristic* Characteristic() const
{
return mCharacteristic;
}
void GetUuid(nsString& aUuidStr) const
{
aUuidStr = mUuidStr;
}
/****************************************************************************
* Others
***************************************************************************/
void Notify(const BluetoothSignal& aData); // BluetoothSignalObserver
nsPIDOMWindow* GetParentObject() const
{
return mOwner;
}
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
BluetoothGattDescriptor(nsPIDOMWindow* aOwner,
BluetoothGattCharacteristic* aCharacteristic,
const BluetoothGattId& aDescriptorId);
private:
~BluetoothGattDescriptor();
/****************************************************************************
* Variables
***************************************************************************/
nsCOMPtr<nsPIDOMWindow> mOwner;
/**
* Characteristic that this descriptor belongs to.
*/
nsRefPtr<BluetoothGattCharacteristic> mCharacteristic;
/**
* GattId of this GATT descriptor which contains
* 1) mUuid: UUID of this descriptor in byte array format.
* 2) mInstanceId: Instance id of this descriptor.
*/
BluetoothGattId mDescriptorId;
/**
* UUID string of this GATT descriptor.
*/
nsString mUuidStr;
};
END_BLUETOOTH_NAMESPACE
#endif

View File

@ -0,0 +1,114 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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/. */
#include "BluetoothService.h"
#include "BluetoothUtils.h"
#include "mozilla/dom/BluetoothGattServiceBinding.h"
#include "mozilla/dom/bluetooth/BluetoothCommon.h"
#include "mozilla/dom/bluetooth/BluetoothGattCharacteristic.h"
#include "mozilla/dom/bluetooth/BluetoothGattService.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
using namespace mozilla;
using namespace mozilla::dom;
USING_BLUETOOTH_NAMESPACE
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(
BluetoothGattService, mOwner, mIncludedServices, mCharacteristics)
NS_IMPL_CYCLE_COLLECTING_ADDREF(BluetoothGattService)
NS_IMPL_CYCLE_COLLECTING_RELEASE(BluetoothGattService)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BluetoothGattService)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
BluetoothGattService::BluetoothGattService(
nsPIDOMWindow* aOwner, const nsAString& aAppUuid,
const BluetoothGattServiceId& aServiceId)
: mOwner(aOwner)
, mAppUuid(aAppUuid)
, mServiceId(aServiceId)
{
MOZ_ASSERT(aOwner);
MOZ_ASSERT(!mAppUuid.IsEmpty());
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE_VOID(bs);
// Generate bluetooth signal path and a string representation to provide
// uuid of this service to applications
nsString path;
GeneratePathFromGattId(mServiceId.mId, path, mUuidStr);
bs->RegisterBluetoothSignalHandler(path, this);
}
BluetoothGattService::~BluetoothGattService()
{
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE_VOID(bs);
nsString path;
GeneratePathFromGattId(mServiceId.mId, path);
bs->UnregisterBluetoothSignalHandler(path, this);
}
void
BluetoothGattService::HandleIncludedServicesDiscovered(
const BluetoothValue& aValue)
{
MOZ_ASSERT(aValue.type() == BluetoothValue::TArrayOfBluetoothGattServiceId);
const InfallibleTArray<BluetoothGattServiceId>& includedServIds =
aValue.get_ArrayOfBluetoothGattServiceId();
for (uint32_t i = 0; i < includedServIds.Length(); i++) {
mIncludedServices.AppendElement(new BluetoothGattService(
GetParentObject(), mAppUuid, includedServIds[i]));
}
BluetoothGattServiceBinding::ClearCachedIncludedServicesValue(this);
}
void
BluetoothGattService::HandleCharacteristicsDiscovered(
const BluetoothValue& aValue)
{
MOZ_ASSERT(aValue.type() == BluetoothValue::TArrayOfBluetoothGattId);
const InfallibleTArray<BluetoothGattId>& characteristicIds =
aValue.get_ArrayOfBluetoothGattId();
for (uint32_t i = 0; i < characteristicIds.Length(); i++) {
mCharacteristics.AppendElement(new BluetoothGattCharacteristic(
GetParentObject(), this, characteristicIds[i]));
}
BluetoothGattServiceBinding::ClearCachedCharacteristicsValue(this);
}
void
BluetoothGattService::Notify(const BluetoothSignal& aData)
{
BT_LOGD("[D] %s", NS_ConvertUTF16toUTF8(aData.name()).get());
BluetoothValue v = aData.value();
if (aData.name().EqualsLiteral("IncludedServicesDiscovered")) {
HandleIncludedServicesDiscovered(v);
} else if (aData.name().EqualsLiteral("CharacteristicsDiscovered")) {
HandleCharacteristicsDiscovered(v);
} else {
BT_WARNING("Not handling GATT Service signal: %s",
NS_ConvertUTF16toUTF8(aData.name()).get());
}
}
JSObject*
BluetoothGattService::WrapObject(JSContext* aContext,
JS::Handle<JSObject*> aGivenProto)
{
return BluetoothGattServiceBinding::Wrap(aContext, this, aGivenProto);
}

View File

@ -0,0 +1,146 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef mozilla_dom_bluetooth_bluetoothgattservice_h__
#define mozilla_dom_bluetooth_bluetoothgattservice_h__
#include "mozilla/Attributes.h"
#include "mozilla/dom/BluetoothGattServiceBinding.h"
#include "mozilla/dom/bluetooth/BluetoothCommon.h"
#include "mozilla/dom/bluetooth/BluetoothGattCharacteristic.h"
#include "nsCOMPtr.h"
#include "nsWrapperCache.h"
#include "nsPIDOMWindow.h"
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothSignal;
class BluetoothValue;
class BluetoothGattService final : public nsISupports
, public nsWrapperCache
, public BluetoothSignalObserver
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(BluetoothGattService)
/****************************************************************************
* Attribute Getters
***************************************************************************/
bool IsPrimary() const
{
return mServiceId.mIsPrimary;
}
void GetUuid(nsString& aUuidStr) const
{
aUuidStr = mUuidStr;
}
int InstanceId() const
{
return mServiceId.mId.mInstanceId;
}
void GetIncludedServices(
nsTArray<nsRefPtr<BluetoothGattService>>& aIncludedServices) const
{
aIncludedServices = mIncludedServices;
}
void GetCharacteristics(
nsTArray<nsRefPtr<BluetoothGattCharacteristic>>& aCharacteristics) const
{
aCharacteristics = mCharacteristics;
}
/****************************************************************************
* Others
***************************************************************************/
const nsAString& GetAppUuid() const
{
return mAppUuid;
}
const BluetoothGattServiceId& GetServiceId() const
{
return mServiceId;
}
void Notify(const BluetoothSignal& aData); // BluetoothSignalObserver
nsPIDOMWindow* GetParentObject() const
{
return mOwner;
}
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
BluetoothGattService(nsPIDOMWindow* aOwner,
const nsAString& aAppUuid,
const BluetoothGattServiceId& aServiceId);
private:
~BluetoothGattService();
/**
* Add newly discovered GATT included services into mIncludedServices and
* update the cache value of mIncludedServices.
*
* @param aValue [in] BluetoothValue which contains an array of
* BluetoothGattServiceId of all discovered included
* services.
*/
void HandleIncludedServicesDiscovered(const BluetoothValue& aValue);
/**
* Add newly discovered GATT characteristics into mCharacteristics and
* update the cache value of mCharacteristics.
*
* @param aValue [in] BluetoothValue which contains an array of
* BluetoothGattId of all discovered characteristics.
*/
void HandleCharacteristicsDiscovered(const BluetoothValue& aValue);
/****************************************************************************
* Variables
***************************************************************************/
nsCOMPtr<nsPIDOMWindow> mOwner;
/**
* UUID of the GATT client.
*/
nsString mAppUuid;
/**
* ServiceId of this GATT service which contains
* 1) mId.mUuid: UUID of this service in byte array format.
* 2) mId.mInstanceId: Instance id of this service.
* 3) mIsPrimary: Indicate whether this is a primary service or not.
*/
BluetoothGattServiceId mServiceId;
/**
* UUID string of this GATT service.
*/
nsString mUuidStr;
/**
* Array of discovered included services for this service.
*/
nsTArray<nsRefPtr<BluetoothGattService>> mIncludedServices;
/**
* Array of discovered characteristics for this service.
*/
nsTArray<nsRefPtr<BluetoothGattCharacteristic>> mCharacteristics;
};
END_BLUETOOTH_NAMESPACE
#endif

View File

@ -691,20 +691,24 @@ public:
/* Enumerate Attributes */
virtual void SearchService(int aConnId,
bool aSearchAll,
const BluetoothUuid& aUuid,
BluetoothGattClientResultHandler* aRes) = 0;
virtual void GetIncludedService(
int aConnId,
const BluetoothGattServiceId& aServiceId,
bool aFirst,
const BluetoothGattServiceId& aStartServiceId,
BluetoothGattClientResultHandler* aRes) = 0;
virtual void GetCharacteristic(int aConnId,
const BluetoothGattServiceId& aServiceId,
bool aFirst,
const BluetoothGattId& aStartCharId,
BluetoothGattClientResultHandler* aRes) = 0;
virtual void GetDescriptor(int aConnId,
const BluetoothGattServiceId& aServiceId,
const BluetoothGattId& aCharId,
bool aFirst,
const BluetoothGattId& aDescriptorId,
BluetoothGattClientResultHandler* aRes) = 0;

View File

@ -342,6 +342,14 @@ public:
const nsAString& aDeviceAddress,
BluetoothReplyRunnable* aRunnable) = 0;
/**
* Discover GATT services, characteristic, descriptors from a remote GATT
* server. (platform specific implementation)
*/
virtual void
DiscoverGattServicesInternal(const nsAString& aAppUuid,
BluetoothReplyRunnable* aRunnable) = 0;
/**
* Unregister a GATT client. (platform specific implementation)
*/

View File

@ -40,6 +40,17 @@ UuidToString(const BluetoothUuid& aUuid, nsAString& aString)
aString.AssignLiteral(uuidStr);
}
void
ReversedUuidToString(const BluetoothUuid& aUuid, nsAString& aString)
{
BluetoothUuid uuid;
for (uint8_t i = 0; i < 16; i++) {
uuid.mUuid[i] = aUuid.mUuid[15 - i];
}
UuidToString(uuid, aString);
}
void
StringToUuid(const char* aString, BluetoothUuid& aUuid)
{
@ -64,6 +75,26 @@ StringToUuid(const char* aString, BluetoothUuid& aUuid)
memcpy(&aUuid.mUuid[14], &uuid5, sizeof(uint16_t));
}
void
GeneratePathFromGattId(const BluetoothGattId& aId,
nsAString& aPath,
nsAString& aUuidStr)
{
ReversedUuidToString(aId.mUuid, aUuidStr);
aPath.Assign(aUuidStr);
aPath.AppendLiteral("_");
aPath.AppendInt(aId.mInstanceId);
}
void
GeneratePathFromGattId(const BluetoothGattId& aId,
nsAString& aPath)
{
nsString uuidStr;
GeneratePathFromGattId(aId, aPath, uuidStr);
}
/**
* |SetJsObject| is an internal function used by |BroadcastSystemMessage| only
*/

View File

@ -22,20 +22,61 @@ class BluetoothValue;
/**
* Convert BluetoothUuid object to xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx uuid string.
* This utility function is used by gecko internal only to convert BluetoothUuid
* created by bluetooth stack to uuid string representation.
*
* Note: This utility function is used by gecko internal only to convert
* BluetoothUuid created by bluetooth stack to uuid string representation.
*/
void
UuidToString(const BluetoothUuid& aUuid, nsAString& aString);
/**
* Convert BluetoothUuid object in a reversed byte order to
* xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx uuid string.
* Bluedroid stack reports the BluetoothUuid in a reversed byte order for
* GATT service, characteristic, descriptor uuids.
*
* Note: This utility function is used by gecko internal only to convert
* BluetoothUuid in a reversed byte order created by bluetooth stack to uuid
* string representation.
*/
void
ReversedUuidToString(const BluetoothUuid& aUuid, nsAString& aString);
/**
* Convert xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx uuid string to BluetoothUuid object.
* This utility function is used by gecko internal only to convert uuid string
* created by gecko back to BluetoothUuid representation.
*
* Note: This utility function is used by gecko internal only to convert uuid
* string created by gecko back to BluetoothUuid representation.
*/
void
StringToUuid(const char* aString, BluetoothUuid& aUuid);
//
// Generate bluetooth signal path from GattId
//
/**
* Generate bluetooth signal path and UUID string from a GattId.
*
* @param aId [in] GattId value to convert.
* @param aPath [out] Bluetooth signal path generated from aId.
* @param aUuidStr [out] UUID string generated from aId.
*/
void
GeneratePathFromGattId(const BluetoothGattId& aId,
nsAString& aPath,
nsAString& aUuidStr);
/**
* Generate bluetooth signal path from a GattId.
*
* @param aId [in] GattId value to convert.
* @param aPath [out] Bluetooth signal path generated from aId.
*/
void
GeneratePathFromGattId(const BluetoothGattId& aId,
nsAString& aPath);
//
// Broadcast system message
//

View File

@ -621,14 +621,16 @@ BluetoothGattClientHALInterface::Refresh(
void
BluetoothGattClientHALInterface::SearchService(
int aConnId, const BluetoothUuid& aUuid,
int aConnId, bool aSearchAll, const BluetoothUuid& aUuid,
BluetoothGattClientResultHandler* aRes)
{
bt_status_t status;
#if ANDROID_VERSION >= 19
bt_uuid_t uuid;
if (NS_SUCCEEDED(Convert(aUuid, uuid))) {
if (aSearchAll) {
status = mInterface->search_service(aConnId, 0);
} else if (NS_SUCCEEDED(Convert(aUuid, uuid))) {
status = mInterface->search_service(aConnId, &uuid);
} else {
status = BT_STATUS_PARM_INVALID;
@ -647,7 +649,7 @@ BluetoothGattClientHALInterface::SearchService(
void
BluetoothGattClientHALInterface::GetIncludedService(
int aConnId, const BluetoothGattServiceId& aServiceId,
const BluetoothGattServiceId& aStartServiceId,
bool aFirst, const BluetoothGattServiceId& aStartServiceId,
BluetoothGattClientResultHandler* aRes)
{
bt_status_t status;
@ -655,8 +657,10 @@ BluetoothGattClientHALInterface::GetIncludedService(
btgatt_srvc_id_t serviceId;
btgatt_srvc_id_t startServiceId;
if (NS_SUCCEEDED(Convert(aServiceId, serviceId)) &&
NS_SUCCEEDED(Convert(aStartServiceId, startServiceId))) {
if (aFirst && NS_SUCCEEDED(Convert(aServiceId, serviceId))) {
status = mInterface->get_included_service(aConnId, &serviceId, 0);
} else if (NS_SUCCEEDED(Convert(aServiceId, serviceId)) &&
NS_SUCCEEDED(Convert(aStartServiceId, startServiceId))) {
status = mInterface->get_included_service(aConnId, &serviceId,
&startServiceId);
} else {
@ -676,7 +680,7 @@ BluetoothGattClientHALInterface::GetIncludedService(
void
BluetoothGattClientHALInterface::GetCharacteristic(
int aConnId, const BluetoothGattServiceId& aServiceId,
const BluetoothGattId& aStartCharId,
bool aFirst, const BluetoothGattId& aStartCharId,
BluetoothGattClientResultHandler* aRes)
{
bt_status_t status;
@ -684,8 +688,10 @@ BluetoothGattClientHALInterface::GetCharacteristic(
btgatt_srvc_id_t serviceId;
btgatt_gatt_id_t startCharId;
if (NS_SUCCEEDED(Convert(aServiceId, serviceId)) &&
NS_SUCCEEDED(Convert(aStartCharId, startCharId))) {
if (aFirst && NS_SUCCEEDED(Convert(aServiceId, serviceId))) {
status = mInterface->get_characteristic(aConnId, &serviceId, 0);
} else if (NS_SUCCEEDED(Convert(aServiceId, serviceId)) &&
NS_SUCCEEDED(Convert(aStartCharId, startCharId))) {
status = mInterface->get_characteristic(aConnId, &serviceId, &startCharId);
} else {
status = BT_STATUS_PARM_INVALID;
@ -704,9 +710,8 @@ BluetoothGattClientHALInterface::GetCharacteristic(
void
BluetoothGattClientHALInterface::GetDescriptor(
int aConnId, const BluetoothGattServiceId& aServiceId,
const BluetoothGattId& aCharId,
const BluetoothGattId& aDescriptorId,
BluetoothGattClientResultHandler* aRes)
const BluetoothGattId& aCharId, bool aFirst,
const BluetoothGattId& aDescriptorId, BluetoothGattClientResultHandler* aRes)
{
bt_status_t status;
#if ANDROID_VERSION >= 19
@ -714,9 +719,13 @@ BluetoothGattClientHALInterface::GetDescriptor(
btgatt_gatt_id_t charId;
btgatt_gatt_id_t descriptorId;
if (NS_SUCCEEDED(Convert(aServiceId, serviceId)) &&
NS_SUCCEEDED(Convert(aCharId, charId)) &&
NS_SUCCEEDED(Convert(aDescriptorId, descriptorId))) {
if (aFirst &&
NS_SUCCEEDED(Convert(aServiceId, serviceId)) &&
NS_SUCCEEDED(Convert(aCharId, charId))) {
status = mInterface->get_descriptor(aConnId, &serviceId, &charId, 0);
} else if (NS_SUCCEEDED(Convert(aServiceId, serviceId)) &&
NS_SUCCEEDED(Convert(aCharId, charId)) &&
NS_SUCCEEDED(Convert(aDescriptorId, descriptorId))) {
status = mInterface->get_descriptor(aConnId, &serviceId, &charId,
&descriptorId);
} else {

View File

@ -56,19 +56,23 @@ public:
/* Enumerate Attributes */
void SearchService(int aConnId,
bool aSearchAll,
const BluetoothUuid& aUuid,
BluetoothGattClientResultHandler* aRes);
void GetIncludedService(int aConnId,
const BluetoothGattServiceId& aServiceId,
bool aFirst,
const BluetoothGattServiceId& aStartServiceId,
BluetoothGattClientResultHandler* aRes);
void GetCharacteristic(int aConnId,
const BluetoothGattServiceId& aServiceId,
bool aFirst,
const BluetoothGattId& aStartCharId,
BluetoothGattClientResultHandler* aRes);
void GetDescriptor(int aConnId,
const BluetoothGattServiceId& aServiceId,
const BluetoothGattId& aCharId,
bool aFirst,
const BluetoothGattId& aDescriptorId,
BluetoothGattClientResultHandler* aRes);

View File

@ -6,12 +6,12 @@
#include "BluetoothGattManager.h"
#include "BluetoothCommon.h"
#include "BluetoothInterface.h"
#include "BluetoothReplyRunnable.h"
#include "BluetoothService.h"
#include "BluetoothUtils.h"
#include "MainThreadUtils.h"
#include "mozilla/dom/bluetooth/BluetoothCommon.h"
#include "mozilla/Services.h"
#include "mozilla/StaticPtr.h"
#include "nsIObserverService.h"
@ -37,10 +37,9 @@ namespace {
bool BluetoothGattManager::mInShutdown = false;
class BluetoothGattClient;
static StaticAutoPtr<nsTArray<nsRefPtr<BluetoothGattClient> > > sClients;
class BluetoothGattClient final : public nsISupports
class mozilla::dom::bluetooth::BluetoothGattClient final : public nsISupports
{
public:
NS_DECL_ISUPPORTS
@ -56,18 +55,59 @@ public:
{
mConnectRunnable = nullptr;
mDisconnectRunnable = nullptr;
mDiscoverRunnable = nullptr;
mUnregisterClientRunnable = nullptr;
mReadRemoteRssiRunnable = nullptr;
}
void NotifyDiscoverCompleted(bool aSuccess)
{
MOZ_ASSERT(!mAppUuid.IsEmpty());
MOZ_ASSERT(mDiscoverRunnable);
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE_VOID(bs);
// Notify application to clear the cache values of
// service/characteristic/descriptor.
bs->DistributeSignal(NS_LITERAL_STRING("DiscoverCompleted"),
mAppUuid,
BluetoothValue(aSuccess));
// Resolve/Reject the Promise.
if (aSuccess) {
DispatchReplySuccess(mDiscoverRunnable);
} else {
DispatchReplyError(mDiscoverRunnable,
NS_LITERAL_STRING("Discover failed"));
}
// Cleanup
mServices.Clear();
mIncludedServices.Clear();
mCharacteristics.Clear();
mDescriptors.Clear();
mDiscoverRunnable = nullptr;
}
nsString mAppUuid;
nsString mDeviceAddr;
int mClientIf;
int mConnId;
nsRefPtr<BluetoothReplyRunnable> mConnectRunnable;
nsRefPtr<BluetoothReplyRunnable> mDisconnectRunnable;
nsRefPtr<BluetoothReplyRunnable> mUnregisterClientRunnable;
nsRefPtr<BluetoothReplyRunnable> mDiscoverRunnable;
nsRefPtr<BluetoothReplyRunnable> mReadRemoteRssiRunnable;
nsRefPtr<BluetoothReplyRunnable> mUnregisterClientRunnable;
/**
* These temporary arrays are used only during discover operations.
* All of them are empty if there are no ongoing discover operations.
*/
nsTArray<BluetoothGattServiceId> mServices;
nsTArray<BluetoothGattServiceId> mIncludedServices;
nsTArray<BluetoothGattId> mCharacteristics;
nsTArray<BluetoothGattId> mDescriptors;
};
NS_IMPL_ISUPPORTS0(BluetoothGattClient)
@ -92,6 +132,16 @@ public:
}
};
class ConnIdComparator
{
public:
bool Equals(const nsRefPtr<BluetoothGattClient>& aClient,
int aConnId) const
{
return aClient->mConnId == aConnId;
}
};
BluetoothGattManager*
BluetoothGattManager::Get()
{
@ -338,13 +388,7 @@ BluetoothGattManager::UnregisterClient(int aClientIf,
size_t index = sClients->IndexOf(aClientIf, 0 /* Start */,
ClientIfComparator());
// Reject the unregister request if the client is not found
if (index == sClients->NoIndex) {
DispatchReplyError(aRunnable,
NS_LITERAL_STRING("Unregister GATT client failed"));
return;
}
MOZ_ASSERT(index != sClients->NoIndex);
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
client->mUnregisterClientRunnable = aRunnable;
@ -469,12 +513,7 @@ BluetoothGattManager::Disconnect(const nsAString& aAppUuid,
ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable);
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
// Reject the disconnect request if the client is not found
if (index == sClients->NoIndex) {
DispatchReplyError(aRunnable, NS_LITERAL_STRING("Disconnect failed"));
return;
}
MOZ_ASSERT(index != sClients->NoIndex);
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
client->mDisconnectRunnable = aRunnable;
@ -486,6 +525,66 @@ BluetoothGattManager::Disconnect(const nsAString& aAppUuid,
new DisconnectResultHandler(client));
}
class BluetoothGattManager::DiscoverResultHandler final
: public BluetoothGattClientResultHandler
{
public:
DiscoverResultHandler(BluetoothGattClient* aClient)
: mClient(aClient)
{
MOZ_ASSERT(mClient);
}
void OnError(BluetoothStatus aStatus) override
{
BT_WARNING("BluetoothGattClientInterface::Discover failed: %d",
(int)aStatus);
mClient->NotifyDiscoverCompleted(false);
}
private:
nsRefPtr<BluetoothGattClient> mClient;
};
void
BluetoothGattManager::Discover(const nsAString& aAppUuid,
BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aRunnable);
ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable);
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
MOZ_ASSERT(index != sClients->NoIndex);
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
MOZ_ASSERT(client->mConnId > 0);
MOZ_ASSERT(!client->mDiscoverRunnable);
client->mDiscoverRunnable = aRunnable;
/**
* Discover all services/characteristics/descriptors offered by the remote
* GATT server.
*
* The discover procesure includes following steps.
* 1) Discover all services.
* 2) After all services are discovered, for each service S, we will do
* following actions.
* 2-1) Discover all included services of service S.
* 2-2) Discover all characteristics of service S.
* 2-3) Discover all descriptors of those characteristics discovered in
* 2-2).
*/
sBluetoothGattClientInterface->SearchService(
client->mConnId,
true, // search all services
BluetoothUuid(),
new DiscoverResultHandler(client));
}
class BluetoothGattManager::ReadRemoteRssiResultHandler final
: public BluetoothGattClientResultHandler
{
@ -527,13 +626,7 @@ BluetoothGattManager::ReadRemoteRssi(int aClientIf,
size_t index = sClients->IndexOf(aClientIf, 0 /* Start */,
ClientIfComparator());
// Reject the read remote rssi request if the client is not found
if (index == sClients->NoIndex) {
DispatchReplyError(aRunnable,
NS_LITERAL_STRING("Read remote RSSI failed"));
return;
}
MOZ_ASSERT(index != sClients->NoIndex);
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
client->mReadRemoteRssiRunnable = aRunnable;
@ -558,7 +651,7 @@ BluetoothGattManager::RegisterClientNotification(BluetoothGattStatus aStatus,
UuidToString(aAppUuid, uuid);
size_t index = sClients->IndexOf(uuid, 0 /* Start */, UuidComparator());
NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
MOZ_ASSERT(index != sClients->NoIndex);
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
BluetoothService* bs = BluetoothService::Get();
@ -621,7 +714,7 @@ BluetoothGattManager::ConnectNotification(int aConnId,
size_t index = sClients->IndexOf(aClientIf, 0 /* Start */,
ClientIfComparator());
NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
MOZ_ASSERT(index != sClients->NoIndex);
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
if (aStatus != GATT_STATUS_SUCCESS) {
@ -673,7 +766,7 @@ BluetoothGattManager::DisconnectNotification(int aConnId,
size_t index = sClients->IndexOf(aClientIf, 0 /* Start */,
ClientIfComparator());
NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
MOZ_ASSERT(index != sClients->NoIndex);
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
if (aStatus != GATT_STATUS_SUCCESS) {
@ -711,12 +804,57 @@ BluetoothGattManager::DisconnectNotification(int aConnId,
void
BluetoothGattManager::SearchCompleteNotification(int aConnId,
BluetoothGattStatus aStatus)
{ }
{
MOZ_ASSERT(NS_IsMainThread());
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE_VOID(bs);
size_t index = sClients->IndexOf(aConnId, 0 /* Start */,
ConnIdComparator());
MOZ_ASSERT(index != sClients->NoIndex);
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
MOZ_ASSERT(client->mDiscoverRunnable);
if (aStatus != GATT_STATUS_SUCCESS) {
client->NotifyDiscoverCompleted(false);
return;
}
// Notify BluetoothGatt to create all services
bs->DistributeSignal(NS_LITERAL_STRING("ServicesDiscovered"),
client->mAppUuid,
BluetoothValue(client->mServices));
// All services are discovered, continue to search included services of each
// service if existed, otherwise, notify application that discover completed
if (!client->mServices.IsEmpty()) {
sBluetoothGattClientInterface->GetIncludedService(
aConnId,
client->mServices[0], // start from first service
true, // first included service
BluetoothGattServiceId(),
new DiscoverResultHandler(client));
} else {
client->NotifyDiscoverCompleted(true);
}
}
void
BluetoothGattManager::SearchResultNotification(
int aConnId, const BluetoothGattServiceId& aServiceId)
{ }
{
MOZ_ASSERT(NS_IsMainThread());
size_t index = sClients->IndexOf(aConnId, 0 /* Start */,
ConnIdComparator());
MOZ_ASSERT(index != sClients->NoIndex);
// Save to mServices for distributing to application and discovering
// included services, characteristics of this service later
sClients->ElementAt(index)->mServices.AppendElement(aServiceId);
}
void
BluetoothGattManager::GetCharacteristicNotification(
@ -724,7 +862,43 @@ BluetoothGattManager::GetCharacteristicNotification(
const BluetoothGattServiceId& aServiceId,
const BluetoothGattId& aCharId,
int aCharProperty)
{ }
{
MOZ_ASSERT(NS_IsMainThread());
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE_VOID(bs);
size_t index = sClients->IndexOf(aConnId, 0 /* Start */,
ConnIdComparator());
MOZ_ASSERT(index != sClients->NoIndex);
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
MOZ_ASSERT(client->mDiscoverRunnable);
if (aStatus == GATT_STATUS_SUCCESS) {
// Save to mCharacteristics for distributing to applications and
// discovering descriptors of this characteristic later
client->mCharacteristics.AppendElement(aCharId);
// Get next characteristic of this service
sBluetoothGattClientInterface->GetCharacteristic(
aConnId,
aServiceId,
false,
aCharId,
new DiscoverResultHandler(client));
} else { // all characteristics of this service are discovered
// Notify BluetoothGattService to create characteristics then proceed
nsString path;
GeneratePathFromGattId(aServiceId.mId, path);
bs->DistributeSignal(NS_LITERAL_STRING("CharacteristicsDiscovered"),
path,
BluetoothValue(client->mCharacteristics));
ProceedDiscoverProcess(client, aServiceId);
}
}
void
BluetoothGattManager::GetDescriptorNotification(
@ -732,14 +906,93 @@ BluetoothGattManager::GetDescriptorNotification(
const BluetoothGattServiceId& aServiceId,
const BluetoothGattId& aCharId,
const BluetoothGattId& aDescriptorId)
{ }
{
MOZ_ASSERT(NS_IsMainThread());
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE_VOID(bs);
size_t index = sClients->IndexOf(aConnId, 0 /* Start */,
ConnIdComparator());
MOZ_ASSERT(index != sClients->NoIndex);
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
MOZ_ASSERT(client->mDiscoverRunnable);
if (aStatus == GATT_STATUS_SUCCESS) {
// Save to mDescriptors for distributing to applications
client->mDescriptors.AppendElement(aDescriptorId);
// Get next descriptor of this characteristic
sBluetoothGattClientInterface->GetDescriptor(
aConnId,
aServiceId,
aCharId,
false,
aDescriptorId,
new DiscoverResultHandler(client));
} else { // all descriptors of this characteristic are discovered
// Notify BluetoothGattCharacteristic to create descriptors then proceed
nsString path;
GeneratePathFromGattId(aCharId, path);
bs->DistributeSignal(NS_LITERAL_STRING("DescriptorsDiscovered"),
path,
BluetoothValue(client->mDescriptors));
client->mDescriptors.Clear();
ProceedDiscoverProcess(client, aServiceId);
}
}
void
BluetoothGattManager::GetIncludedServiceNotification(
int aConnId, BluetoothGattStatus aStatus,
const BluetoothGattServiceId& aServiceId,
const BluetoothGattServiceId& aIncludedServId)
{ }
{
MOZ_ASSERT(NS_IsMainThread());
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE_VOID(bs);
size_t index = sClients->IndexOf(aConnId, 0 /* Start */,
ConnIdComparator());
MOZ_ASSERT(index != sClients->NoIndex);
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
MOZ_ASSERT(client->mDiscoverRunnable);
if (aStatus == GATT_STATUS_SUCCESS) {
// Save to mIncludedServices for distributing to applications
client->mIncludedServices.AppendElement(aIncludedServId);
// Get next included service of this service
sBluetoothGattClientInterface->GetIncludedService(
aConnId,
aServiceId,
false,
aIncludedServId,
new DiscoverResultHandler(client));
} else { // all included services of this service are discovered
// Notify BluetoothGattService to create included services
nsString path;
GeneratePathFromGattId(aServiceId.mId, path);
bs->DistributeSignal(NS_LITERAL_STRING("IncludedServicesDiscovered"),
path,
BluetoothValue(client->mIncludedServices));
client->mIncludedServices.Clear();
// Start to discover characteristics of this service
sBluetoothGattClientInterface->GetCharacteristic(
aConnId,
aServiceId,
true, // first characteristic
BluetoothGattId(),
new DiscoverResultHandler(client));
}
}
void
BluetoothGattManager::RegisterNotificationNotification(
@ -863,4 +1116,45 @@ BluetoothGattManager::HandleShutdown()
sBluetoothGattManager = nullptr;
}
void
BluetoothGattManager::ProceedDiscoverProcess(
BluetoothGattClient* aClient,
const BluetoothGattServiceId& aServiceId)
{
/**
* This function will be called to decide how to proceed the discover process
* after discovering all characteristics of a given service, or after
* discovering all descriptors of a given characteristic.
*
* There are three cases here,
* 1) mCharacteristics is not empty:
* Proceed to discover descriptors of the first saved characteristic.
* 2) mCharacteristics is empty but mServices is not empty:
* This service does not have any saved characteristics left, proceed to
* discover included services of the next service.
* 3) Both arrays are already empty:
* Discover is done, notify application.
*/
if (!aClient->mCharacteristics.IsEmpty()) {
sBluetoothGattClientInterface->GetDescriptor(
aClient->mConnId,
aServiceId,
aClient->mCharacteristics[0],
true, // first descriptor
BluetoothGattId(),
new DiscoverResultHandler(aClient));
aClient->mCharacteristics.RemoveElementAt(0);
} else if (!aClient->mServices.IsEmpty()) {
sBluetoothGattClientInterface->GetIncludedService(
aClient->mConnId,
aClient->mServices[0],
true, // first included service
BluetoothGattServiceId(),
new DiscoverResultHandler(aClient));
aClient->mServices.RemoveElementAt(0);
} else {
aClient->NotifyDiscoverCompleted(true);
}
}
NS_IMPL_ISUPPORTS(BluetoothGattManager, nsIObserver)

View File

@ -13,6 +13,7 @@
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothGattClient;
class BluetoothReplyRunnable;
class BluetoothGattManager final : public nsIObserver
@ -35,6 +36,9 @@ public:
const nsAString& aDeviceAddr,
BluetoothReplyRunnable* aRunnable);
void Discover(const nsAString& aAppUuid,
BluetoothReplyRunnable* aRunnable);
void UnregisterClient(int aClientIf,
BluetoothReplyRunnable* aRunnable);
@ -50,6 +54,7 @@ private:
class UnregisterClientResultHandler;
class ConnectResultHandler;
class DisconnectResultHandler;
class DiscoverResultHandler;
class ReadRemoteRssiResultHandler;
BluetoothGattManager();
@ -137,6 +142,9 @@ private:
void ListenNotification(BluetoothGattStatus aStatus,
int aServerIf) override;
void ProceedDiscoverProcess(BluetoothGattClient* aClient,
const BluetoothGattServiceId& aServiceId);
static bool mInShutdown;
};

View File

@ -1117,6 +1117,20 @@ BluetoothServiceBluedroid::DisconnectGattClientInternal(
gatt->Disconnect(aAppUuid, aDeviceAddress, aRunnable);
}
void
BluetoothServiceBluedroid::DiscoverGattServicesInternal(
const nsAString& aAppUuid, BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
ENSURE_BLUETOOTH_IS_READY_VOID(aRunnable);
BluetoothGattManager* gatt = BluetoothGattManager::Get();
ENSURE_GATT_MGR_IS_READY_VOID(gatt, aRunnable);
gatt->Discover(aAppUuid, aRunnable);
}
void
BluetoothServiceBluedroid::UnregisterGattClientInternal(
int aClientIf, BluetoothReplyRunnable* aRunnable)

View File

@ -184,6 +184,10 @@ public:
const nsAString& aDeviceAddress,
BluetoothReplyRunnable* aRunnable) override;
virtual void
DiscoverGattServicesInternal(const nsAString& aAppUuid,
BluetoothReplyRunnable* aRunnable) override;
virtual void
UnregisterGattClientInternal(int aClientIf,
BluetoothReplyRunnable* aRunnable) override;

View File

@ -4291,6 +4291,12 @@ BluetoothDBusService::DisconnectGattClientInternal(
{
}
void
BluetoothDBusService::DiscoverGattServicesInternal(
const nsAString& aAppUuid, BluetoothReplyRunnable* aRunnable)
{
}
void
BluetoothDBusService::UnregisterGattClientInternal(
int aClientIf, BluetoothReplyRunnable* aRunnable)

View File

@ -194,6 +194,11 @@ public:
DisconnectGattClientInternal(const nsAString& aAppUuid,
const nsAString& aDeviceAddress,
BluetoothReplyRunnable* aRunnable) override;
virtual void
DiscoverGattServicesInternal(const nsAString& aAppUuid,
BluetoothReplyRunnable* aRunnable) override;
virtual void
UnregisterGattClientInternal(int aClientIf,
BluetoothReplyRunnable* aRunnable) override;

View File

@ -28,6 +28,73 @@ struct ParamTraits<mozilla::dom::bluetooth::BluetoothStatus>
mozilla::dom::bluetooth::STATUS_RMT_DEV_DOWN>
{ };
template <>
struct ParamTraits<mozilla::dom::bluetooth::BluetoothUuid>
{
typedef mozilla::dom::bluetooth::BluetoothUuid paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
for (uint8_t i = 0; i < 16; i++) {
WriteParam(aMsg, aParam.mUuid[i]);
}
}
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
{
for (uint8_t i = 0; i < 16; i++) {
if (!ReadParam(aMsg, aIter, &(aResult->mUuid[i]))) {
return false;
}
}
return true;
}
};
template <>
struct ParamTraits<mozilla::dom::bluetooth::BluetoothGattId>
{
typedef mozilla::dom::bluetooth::BluetoothGattId paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
WriteParam(aMsg, aParam.mUuid);
WriteParam(aMsg, aParam.mInstanceId);
}
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
{
if (!ReadParam(aMsg, aIter, &(aResult->mUuid)) ||
!ReadParam(aMsg, aIter, &(aResult->mInstanceId))) {
return false;
}
return true;
}
};
template <>
struct ParamTraits<mozilla::dom::bluetooth::BluetoothGattServiceId>
{
typedef mozilla::dom::bluetooth::BluetoothGattServiceId paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
WriteParam(aMsg, aParam.mId);
WriteParam(aMsg, aParam.mIsPrimary);
}
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
{
if (!ReadParam(aMsg, aIter, &(aResult->mId)) ||
!ReadParam(aMsg, aIter, &(aResult->mIsPrimary))) {
return false;
}
return true;
}
};
} // namespace IPC
#endif // mozilla_dom_bluetooth_ipc_bluetoothmessageutils_h__

View File

@ -254,6 +254,8 @@ BluetoothParent::RecvPBluetoothRequestConstructor(
return actor->DoRequest(aRequest.get_ConnectGattClientRequest());
case Request::TDisconnectGattClientRequest:
return actor->DoRequest(aRequest.get_DisconnectGattClientRequest());
case Request::TDiscoverGattServicesRequest:
return actor->DoRequest(aRequest.get_DiscoverGattServicesRequest());
case Request::TUnregisterGattClientRequest:
return actor->DoRequest(aRequest.get_UnregisterGattClientRequest());
case Request::TGattClientReadRemoteRssiRequest:
@ -719,6 +721,18 @@ BluetoothRequestParent::DoRequest(const DisconnectGattClientRequest& aRequest)
return true;
}
bool
BluetoothRequestParent::DoRequest(const DiscoverGattServicesRequest& aRequest)
{
MOZ_ASSERT(mService);
MOZ_ASSERT(mRequestType == Request::TDiscoverGattServicesRequest);
mService->DiscoverGattServicesInternal(aRequest.appUuid(),
mReplyRunnable.get());
return true;
}
bool
BluetoothRequestParent::DoRequest(const UnregisterGattClientRequest& aRequest)
{

View File

@ -223,6 +223,9 @@ protected:
bool
DoRequest(const DisconnectGattClientRequest& aRequest);
bool
DoRequest(const DiscoverGattServicesRequest& aRequest);
bool
DoRequest(const UnregisterGattClientRequest& aRequest);

View File

@ -397,6 +397,14 @@ BluetoothServiceChildProcess::DisconnectGattClientInternal(
DisconnectGattClientRequest(nsString(aAppUuid), nsString(aDeviceAddress)));
}
void
BluetoothServiceChildProcess::DiscoverGattServicesInternal(
const nsAString& aAppUuid, BluetoothReplyRunnable* aRunnable)
{
SendRequest(aRunnable,
DiscoverGattServicesRequest(nsString(aAppUuid)));
}
void
BluetoothServiceChildProcess::UnregisterGattClientInternal(
int aClientIf, BluetoothReplyRunnable* aRunnable)

View File

@ -202,6 +202,10 @@ public:
const nsAString& aDeviceAddress,
BluetoothReplyRunnable* aRunnable) override;
virtual void
DiscoverGattServicesInternal(const nsAString& aAppUuid,
BluetoothReplyRunnable* aRunnable) override;
virtual void
UnregisterGattClientInternal(int aClientIf,
BluetoothReplyRunnable* aRunnable) override;

View File

@ -4,7 +4,12 @@
* 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/. */
using mozilla::dom::bluetooth::BluetoothStatus from "mozilla/dom/bluetooth/BluetoothCommon.h";
using mozilla::dom::bluetooth::BluetoothGattId
from "mozilla/dom/bluetooth/BluetoothCommon.h";
using mozilla::dom::bluetooth::BluetoothGattServiceId
from "mozilla/dom/bluetooth/BluetoothCommon.h";
using mozilla::dom::bluetooth::BluetoothStatus
from "mozilla/dom/bluetooth/BluetoothCommon.h";
namespace mozilla {
namespace dom {
@ -23,6 +28,8 @@ union BluetoothValue
nsString[];
uint8_t[];
BluetoothNamedValue[];
BluetoothGattId[];
BluetoothGattServiceId[];
};
/**

View File

@ -188,6 +188,11 @@ struct DisconnectGattClientRequest
nsString deviceAddress;
};
struct DiscoverGattServicesRequest
{
nsString appUuid;
};
struct UnregisterGattClientRequest
{
int clientIf;
@ -233,6 +238,7 @@ union Request
SendPlayStatusRequest;
ConnectGattClientRequest;
DisconnectGattClientRequest;
DiscoverGattServicesRequest;
UnregisterGattClientRequest;
GattClientReadRemoteRssiRequest;
};

View File

@ -11,6 +11,9 @@ if CONFIG['MOZ_B2G_BT']:
'BluetoothDevice.cpp',
'BluetoothDiscoveryHandle.cpp',
'BluetoothGatt.cpp',
'BluetoothGattCharacteristic.cpp',
'BluetoothGattDescriptor.cpp',
'BluetoothGattService.cpp',
'BluetoothHidManager.cpp',
'BluetoothInterface.cpp',
'BluetoothManager.cpp',
@ -124,6 +127,9 @@ EXPORTS.mozilla.dom.bluetooth += [
'BluetoothDevice.h',
'BluetoothDiscoveryHandle.h',
'BluetoothGatt.h',
'BluetoothGattCharacteristic.h',
'BluetoothGattDescriptor.h',
'BluetoothGattService.h',
'BluetoothManager.h',
'BluetoothPairingHandle.h',
'BluetoothPairingListener.h',

View File

@ -524,7 +524,6 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e1
skip-if = toolkit == 'android' || (toolkit == 'gonk' && debug) #bug 871015, bug 881443
[test_input_files_not_nsIFile.html]
[test_ignoreuserfocus.html]
skip-if = (toolkit == 'gonk' && debug)
[test_fragment_form_pointer.html]
[test_bug1682.html]
[test_bug1823.html]

View File

@ -7,6 +7,8 @@
[CheckPermissions="bluetooth"]
interface BluetoothGatt : EventTarget
{
[Cached, Pure]
readonly attribute sequence<BluetoothGattService> services;
readonly attribute BluetoothConnectionState connectionState;
// Fired when attribute connectionState changed
@ -28,6 +30,14 @@ interface BluetoothGatt : EventTarget
[NewObject]
Promise<void> disconnect();
/**
* Discover services, characteristics, descriptors offered by the remote GATT
* server. The promise will be rejected if the connState is not connected or
* operation fails.
*/
[NewObject]
Promise<void> discoverServices();
/**
* Read RSSI for the remote BLE device if the connectState is connected.
* Otherwise, the Promise will be rejected directly.

View File

@ -0,0 +1,16 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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"]
interface BluetoothGattCharacteristic
{
readonly attribute BluetoothGattService service;
[Cached, Pure]
readonly attribute sequence<BluetoothGattDescriptor> descriptors;
readonly attribute DOMString uuid;
readonly attribute unsigned short instanceId;
};

View File

@ -0,0 +1,12 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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"]
interface BluetoothGattDescriptor
{
readonly attribute BluetoothGattCharacteristic characteristic;
readonly attribute DOMString uuid;
};

View File

@ -0,0 +1,18 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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"]
interface BluetoothGattService
{
[Cached, Pure]
readonly attribute sequence<BluetoothGattCharacteristic> characteristics;
[Cached, Pure]
readonly attribute sequence<BluetoothGattService> includedServices;
readonly attribute boolean isPrimary;
readonly attribute DOMString uuid;
readonly attribute unsigned short instanceId;
};

View File

@ -637,6 +637,9 @@ if CONFIG['MOZ_B2G_BT']:
'BluetoothDevice2.webidl',
'BluetoothDiscoveryHandle.webidl',
'BluetoothGatt.webidl',
'BluetoothGattCharacteristic.webidl',
'BluetoothGattDescriptor.webidl',
'BluetoothGattService.webidl',
'BluetoothManager2.webidl',
'BluetoothPairingHandle.webidl',
'BluetoothPairingListener.webidl',

View File

@ -106,12 +106,10 @@ static size_t getPageSize(void) {
}
/**
* The stack size is chosen carefully so the frozen threads doesn't consume too
* much memory in the Nuwa process. The threads shouldn't run deep recursive
* methods or do large allocations on the stack to avoid stack overflow.
* Use 1 MiB stack size as Android does.
*/
#ifndef NUWA_STACK_SIZE
#define NUWA_STACK_SIZE (1024 * 128)
#define NUWA_STACK_SIZE (1024 * 1024)
#endif
#define NATIVE_THREAD_NAME_LENGTH 16
@ -173,6 +171,8 @@ struct thread_info : public mozilla::LinkedListElement<thread_info> {
pthread_mutex_t *condMutex;
bool condMutexNeedsBalancing;
size_t stackSize;
size_t guardSize;
void *stk;
pid_t origNativeThreadID;
@ -546,20 +546,10 @@ thread_info_new(void) {
tinfo->recreatedNativeThreadID = 0;
tinfo->condMutex = nullptr;
tinfo->condMutexNeedsBalancing = false;
tinfo->stk = MozTaggedAnonymousMmap(nullptr,
NUWA_STACK_SIZE + getPageSize(),
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS,
/* fd */ -1,
/* offset */ 0,
"nuwa-thread-stack");
// We use a smaller stack size. Add protection to stack overflow: mprotect()
// stack top (the page at the lowest address) so we crash instead of corrupt
// other content that is malloc()'d.
mprotect(tinfo->stk, getPageSize(), PROT_NONE);
pthread_attr_init(&tinfo->threadAttr);
// Default stack and guard size.
tinfo->stackSize = NUWA_STACK_SIZE;
tinfo->guardSize = getPageSize();
REAL(pthread_mutex_lock)(&sThreadCountLock);
// Insert to the tail.
@ -572,6 +562,44 @@ thread_info_new(void) {
return tinfo;
}
static void
thread_attr_init(thread_info_t *tinfo, const pthread_attr_t *tattr)
{
pthread_attr_init(&tinfo->threadAttr);
if (tattr) {
// Override default thread stack and guard size with tattr.
pthread_attr_getstacksize(tattr, &tinfo->stackSize);
pthread_attr_getguardsize(tattr, &tinfo->guardSize);
size_t pageSize = getPageSize();
tinfo->stackSize = (tinfo->stackSize + pageSize - 1) % pageSize;
tinfo->guardSize = (tinfo->guardSize + pageSize - 1) % pageSize;
int detachState = 0;
pthread_attr_getdetachstate(tattr, &detachState);
pthread_attr_setdetachstate(&tinfo->threadAttr, detachState);
}
tinfo->stk = MozTaggedAnonymousMmap(nullptr,
tinfo->stackSize + tinfo->guardSize,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS,
/* fd */ -1,
/* offset */ 0,
"nuwa-thread-stack");
// Add protection to stack overflow: mprotect() stack top (the page at the
// lowest address) so we crash instead of corrupt other content that is
// malloc()'d.
mprotect(tinfo->stk, tinfo->guardSize, PROT_NONE);
pthread_attr_setstack(&tinfo->threadAttr,
(char*)tinfo->stk + tinfo->guardSize,
tinfo->stackSize);
}
static void
thread_info_cleanup(void *arg) {
if (sNuwaForking) {
@ -582,7 +610,7 @@ thread_info_cleanup(void *arg) {
thread_info_t *tinfo = (thread_info_t *)arg;
pthread_attr_destroy(&tinfo->threadAttr);
munmap(tinfo->stk, NUWA_STACK_SIZE + getPageSize());
munmap(tinfo->stk, tinfo->stackSize + tinfo->guardSize);
REAL(pthread_mutex_lock)(&sThreadCountLock);
/* unlink tinfo from sAllThreads */
@ -741,11 +769,9 @@ __wrap_pthread_create(pthread_t *thread,
}
thread_info_t *tinfo = thread_info_new();
thread_attr_init(tinfo, attr);
tinfo->startupFunc = start_routine;
tinfo->startupArg = arg;
pthread_attr_setstack(&tinfo->threadAttr,
(char*)tinfo->stk + getPageSize(),
NUWA_STACK_SIZE);
int rv = REAL(pthread_create)(thread,
&tinfo->threadAttr,

View File

@ -154,6 +154,7 @@ SandboxFilterImplContent::Build() {
Allow(SYSCALL(munmap));
Allow(SYSCALL(mprotect));
Allow(SYSCALL(writev));
Allow(SYSCALL(pread64));
AllowThreadClone();
Allow(SYSCALL(brk));
#if SYSCALL_EXISTS(set_thread_area)

View File

@ -17,6 +17,8 @@ def parse_test_opts(input_str):
tests.insert(0, cur_test)
def add_platform(value):
# Ensure platforms exists...
cur_test['platforms'] = cur_test.get('platforms', [])
cur_test['platforms'].insert(0, value.strip())
# This might be somewhat confusing but we parse the string _backwards_ so
@ -45,7 +47,6 @@ def parse_test_opts(input_str):
elif char == ']':
# Entering platform state.
in_platforms = True
cur_test['platforms'] = []
else:
# Accumulator.
token = char + token

View File

@ -29,6 +29,18 @@ class TryTestParserTest(unittest.TestCase):
]
)
self.assertEquals(
parse_test_opts('mochitest-3[Ubuntu,10.6,10.8,Windows XP,Windows 7,Windows 8]'),
[
{
'test': 'mochitest-3',
'platforms': [
'Ubuntu', '10.6', '10.8', 'Windows XP', 'Windows 7', 'Windows 8'
]
}
]
)
self.assertEquals(
parse_test_opts(''),
[]