Refactor GattCharactristic to support bitwise combination of Permission and Property

PiperOrigin-RevId: 513339751
This commit is contained in:
Qin Wang
2023-03-01 14:21:04 -08:00
committed by Copybara-Service
parent bb0ccf9156
commit 4727861f5d
12 changed files with 157 additions and 137 deletions
+5 -5
View File
@@ -18,6 +18,7 @@
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "absl/strings/escaping.h"
#include "absl/types/optional.h"
@@ -543,10 +544,9 @@ bool BleV2::StartAdvertisementGattServerLocked(
bool BleV2::GenerateAdvertisementCharacteristic(
int slot, const ByteArray& gatt_advertisement, GattServer& gatt_server) {
std::vector<GattCharacteristic::Permission> permissions{
GattCharacteristic::Permission::kRead};
std::vector<GattCharacteristic::Property> properties{
GattCharacteristic::Property::kRead};
GattCharacteristic::Permission permission =
GattCharacteristic::Permission::kRead;
GattCharacteristic::Property property = GattCharacteristic::Property::kRead;
// NOLINTNEXTLINE(google3-legacy-absl-backports)
absl::optional<Uuid> advertiement_uuid =
@@ -559,7 +559,7 @@ bool BleV2::GenerateAdvertisementCharacteristic(
absl::optional<GattCharacteristic> gatt_characteristic =
gatt_server.CreateCharacteristic(
mediums::bleutils::kCopresenceServiceUuid, *advertiement_uuid,
permissions, properties);
permission, property);
if (!gatt_characteristic.has_value()) {
NEARBY_LOGS(INFO) << "Unable to create and add a characterstic to the gatt "
"server for the advertisement.";
+4 -5
View File
@@ -18,6 +18,7 @@
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "absl/functional/any_invocable.h"
#include "absl/types/optional.h"
@@ -158,12 +159,10 @@ class GattServer final {
// NOLINTNEXTLINE(google3-legacy-absl-backports)
absl::optional<api::ble_v2::GattCharacteristic> CreateCharacteristic(
const Uuid& service_uuid, const Uuid& characteristic_uuid,
const std::vector<api::ble_v2::GattCharacteristic::Permission>&
permissions,
const std::vector<api::ble_v2::GattCharacteristic::Property>&
properties) {
const api::ble_v2::GattCharacteristic::Permission permission,
const api::ble_v2::GattCharacteristic::Property property) {
return impl_->CreateCharacteristic(service_uuid, characteristic_uuid,
permissions, properties);
permission, property);
}
bool UpdateCharacteristic(
+10 -13
View File
@@ -455,14 +455,13 @@ TEST_F(BleV2MediumTest, CanStartGattServer) {
ASSERT_NE(gatt_server, nullptr);
std::vector<GattCharacteristic::Permission> permissions = {
GattCharacteristic::Permission::kRead};
std::vector<GattCharacteristic::Property> properties = {
GattCharacteristic::Property::kRead};
GattCharacteristic::Permission permission =
GattCharacteristic::Permission::kRead;
GattCharacteristic::Property property = GattCharacteristic::Property::kRead;
// NOLINTNEXTLINE(google3-legacy-absl-backports)
absl::optional<GattCharacteristic> gatt_characteristic =
gatt_server->CreateCharacteristic(service_uuid, characteristic_uuid,
permissions, properties);
permission, property);
ASSERT_TRUE(gatt_characteristic.has_value());
@@ -491,10 +490,9 @@ TEST_F(BleV2MediumTest, GattClientConnectToGattServerWorks) {
ASSERT_NE(gatt_server, nullptr);
std::vector<GattCharacteristic::Permission> permissions = {
GattCharacteristic::Permission::kRead};
std::vector<GattCharacteristic::Property> properties = {
GattCharacteristic::Property::kRead};
GattCharacteristic::Permission permissions =
GattCharacteristic::Permission::kRead;
GattCharacteristic::Property properties = GattCharacteristic::Property::kRead;
// Add characteristic and its value.
// NOLINTNEXTLINE(google3-legacy-absl-backports)
absl::optional<GattCharacteristic> server_characteristic =
@@ -538,10 +536,9 @@ TEST_F(BleV2MediumTest, GattServerCanNotifyChange) {
BleV2Medium ble_a(adapter_a);
Uuid service_uuid(1234, 5678);
Uuid characteristic_uuid(5678, 1234);
std::vector<GattCharacteristic::Permission> permissions = {
GattCharacteristic::Permission::kRead};
std::vector<GattCharacteristic::Property> properties = {
GattCharacteristic::Property::kRead};
GattCharacteristic::Permission permissions =
GattCharacteristic::Permission::kRead;
GattCharacteristic::Property properties = GattCharacteristic::Property::kRead;
// Start GattServer
std::unique_ptr<GattServer> gatt_server =
@@ -87,12 +87,12 @@ static const TxPowerLevel kTxPowerLevel = TxPowerLevel::kHigh;
// Test creating characteristic.
Uuid service_uuid(1234, 5678);
Uuid characteristic_uuid(5678, 1234);
std::vector<GattCharacteristic::Permission> permissions = {GattCharacteristic::Permission::kRead};
std::vector<GattCharacteristic::Property> properties = {GattCharacteristic::Property::kRead};
GattCharacteristic::Permission permission = GattCharacteristic::Permission::kRead;
GattCharacteristic::Property property = GattCharacteristic::Property::kRead;
// NOLINTNEXTLINE
absl::optional<GattCharacteristic> gatt_characteristic =
gatt_server->CreateCharacteristic(service_uuid, characteristic_uuid, permissions, properties);
gatt_server->CreateCharacteristic(service_uuid, characteristic_uuid, permission, property);
XCTAssertTrue(gatt_characteristic.has_value());
// Test updating characteristic.
+2 -2
View File
@@ -152,8 +152,8 @@ class BleMedium : public api::ble_v2::BleMedium {
absl::optional<api::ble_v2::GattCharacteristic> CreateCharacteristic(
const Uuid &service_uuid, const Uuid &characteristic_uuid,
const std::vector<api::ble_v2::GattCharacteristic::Permission> &permissions,
const std::vector<api::ble_v2::GattCharacteristic::Property> &properties) override;
api::ble_v2::GattCharacteristic::Permission permission,
api::ble_v2::GattCharacteristic::Property property) override;
bool UpdateCharacteristic(const api::ble_v2::GattCharacteristic &characteristic,
const nearby::ByteArray &value) override;
+27 -37
View File
@@ -29,45 +29,35 @@
namespace nearby {
namespace apple {
using Permission = api::ble_v2::GattCharacteristic::Permission;
using Property = api::ble_v2::GattCharacteristic::Property;
namespace {
CBAttributePermissions PermissionToCBPermissions(
const std::vector<api::ble_v2::GattCharacteristic::Permission>& permissions) {
CBAttributePermissions PermissionToCBPermissions(Permission permission) {
CBAttributePermissions characteristPermissions = 0;
for (const auto& permission : permissions) {
switch (permission) {
case api::ble_v2::GattCharacteristic::Permission::kRead:
characteristPermissions |= CBAttributePermissionsReadable;
break;
case api::ble_v2::GattCharacteristic::Permission::kWrite:
characteristPermissions |= CBAttributePermissionsWriteable;
break;
case api::ble_v2::GattCharacteristic::Permission::kLast:
case api::ble_v2::GattCharacteristic::Permission::kUnknown:
default:; // fall through
}
if ((permission & Permission::kRead) != Permission::kNone) {
characteristPermissions |= CBAttributePermissionsReadable;
}
if ((permission & Permission::kWrite) != Permission::kNone) {
characteristPermissions |= CBAttributePermissionsWriteable;
}
return characteristPermissions;
}
CBCharacteristicProperties PropertiesToCBProperties(
const std::vector<api::ble_v2::GattCharacteristic::Property>& properties) {
CBCharacteristicProperties PropertiesToCBProperties(Property property) {
CBCharacteristicProperties characteristicProperties = 0;
for (const auto& property : properties) {
switch (property) {
case api::ble_v2::GattCharacteristic::Property::kRead:
characteristicProperties |= CBCharacteristicPropertyRead;
break;
case api::ble_v2::GattCharacteristic::Property::kWrite:
characteristicProperties |= CBCharacteristicPropertyWrite;
break;
case api::ble_v2::GattCharacteristic::Property::kIndicate:
characteristicProperties |= CBCharacteristicPropertyIndicate;
break;
case api::ble_v2::GattCharacteristic::Property::kLast:
case api::ble_v2::GattCharacteristic::Property::kUnknown:
default:; // fall through
}
if ((property & Property::kRead) != Property::kNone) {
characteristicProperties |= CBCharacteristicPropertyRead;
}
if ((property & Property::kWrite) != Property::kNone) {
characteristicProperties |= CBCharacteristicPropertyWrite;
}
if ((property & Property::kIndicate) != Property::kNone) {
characteristicProperties |= CBCharacteristicPropertyIndicate;
}
if ((property & Property::kNotify) != Property::kNone) {
characteristicProperties |= CBCharacteristicPropertyNotify;
}
return characteristicProperties;
}
@@ -483,12 +473,12 @@ bool BleMedium::IsExtendedAdvertisementsAvailable() { return false; }
// NOLINTNEXTLINE
absl::optional<api::ble_v2::GattCharacteristic> BleMedium::GattServer::CreateCharacteristic(
const Uuid& service_uuid, const Uuid& characteristic_uuid,
const std::vector<api::ble_v2::GattCharacteristic::Permission>& permissions,
const std::vector<api::ble_v2::GattCharacteristic::Property>& properties) {
api::ble_v2::GattCharacteristic::Permission permission,
api::ble_v2::GattCharacteristic::Property property) {
api::ble_v2::GattCharacteristic characteristic = {.uuid = characteristic_uuid,
.service_uuid = service_uuid,
.permissions = permissions,
.properties = properties};
.permission = permission,
.property = property};
[peripheral_
addCBServiceWithUUID:[CBUUID
UUIDWithString:ObjCStringFromCppString(
@@ -497,9 +487,9 @@ absl::optional<api::ble_v2::GattCharacteristic> BleMedium::GattServer::CreateCha
addCharacteristic:[[CBMutableCharacteristic alloc]
initWithType:[CBUUID UUIDWithString:ObjCStringFromCppString(std::string(
characteristic.uuid))]
properties:PropertiesToCBProperties(characteristic.properties)
properties:PropertiesToCBProperties(characteristic.property)
value:nil
permissions:PermissionToCBPermissions(characteristic.permissions)]];
permissions:PermissionToCBPermissions(characteristic.permission)]];
return characteristic;
}
+46 -20
View File
@@ -98,41 +98,67 @@ class BlePeripheral {
//
// Representation of a GATT characteristic.
struct GattCharacteristic {
// Represents the GATT characteristic permissions
// This enumeration supports a bitwise combination of its member values.
// |, &, |= of the values are legal.
enum class Permission {
kUnknown = 0,
kRead = 1,
kWrite = 2,
kNone = 0,
kRead = 1 << 0,
kWrite = 1 << 1,
kLast,
};
// Represents the GATT characteristic properties
// This enumeration supports a bitwise combination of its member values.
// |, &, |= of the values are legal.
enum class Property {
kUnknown = 0,
kRead = 1,
kWrite = 2,
kIndicate = 3,
kNone = 0,
kRead = 1 << 0,
kWrite = 1 << 1,
kIndicate = 1 << 2,
kNotify = 1 << 3,
kLast,
};
Uuid uuid;
Uuid service_uuid;
std::vector<Permission> permissions;
std::vector<Property> properties;
Permission permission;
Property property;
// overloading operator for enum class Permission and Property
friend inline Permission operator|(Permission a, Permission b) {
return static_cast<Permission>(static_cast<int>(a) | static_cast<int>(b));
}
friend inline Permission operator&(Permission a, Permission b) {
return static_cast<Permission>(static_cast<int>(a) & static_cast<int>(b));
}
friend inline Permission& operator|=(Permission& a, Permission b) {
a = a | b;
return a;
}
friend inline Property operator|(Property a, Property b) {
return static_cast<Property>(static_cast<int>(a) | static_cast<int>(b));
}
friend inline Property operator&(Property a, Property b) {
return static_cast<Property>(static_cast<int>(a) & static_cast<int>(b));
}
friend inline Property& operator|=(Property& a, Property b) {
a = a | b;
return a;
}
// Hashable
template <typename H>
friend H AbslHashValue(H h, const GattCharacteristic& s) {
return H::combine(std::move(h), s.uuid, s.service_uuid, s.permissions,
s.properties);
return H::combine(std::move(h), s.uuid, s.service_uuid, s.permission,
s.property);
}
bool operator==(const GattCharacteristic& rhs) const {
bool has_equal_permissions =
std::is_permutation(this->permissions.begin(), this->permissions.end(),
rhs.permissions.begin(), rhs.permissions.end());
bool has_equal_properties =
std::is_permutation(this->properties.begin(), this->properties.end(),
rhs.properties.begin(), rhs.properties.end());
return this->uuid == rhs.uuid && this->service_uuid == rhs.service_uuid &&
has_equal_permissions && has_equal_properties;
this->permission == rhs.permission && this->property == rhs.property;
}
};
@@ -214,8 +240,8 @@ class GattServer {
// NOLINTNEXTLINE(google3-legacy-absl-backports)
virtual absl::optional<GattCharacteristic> CreateCharacteristic(
const Uuid& service_uuid, const Uuid& characteristic_uuid,
const std::vector<GattCharacteristic::Permission>& permissions,
const std::vector<GattCharacteristic::Property>& properties) = 0;
GattCharacteristic::Permission permission,
GattCharacteristic::Property property) = 0;
// https://developer.android.com/reference/android/bluetooth/BluetoothGattCharacteristic.html#setValue(byte[])
//
@@ -355,8 +355,8 @@ bool BleV2Medium::IsExtendedAdvertisementsAvailable() {
std::optional<api::ble_v2::GattCharacteristic>
BleV2Medium::GattServer::CreateCharacteristic(
const Uuid& service_uuid, const Uuid& characteristic_uuid,
const std::vector<api::ble_v2::GattCharacteristic::Permission>& permissions,
const std::vector<api::ble_v2::GattCharacteristic::Property>& properties) {
api::ble_v2::GattCharacteristic::Permission permission,
api::ble_v2::GattCharacteristic::Property property) {
api::ble_v2::GattCharacteristic characteristic = {
.uuid = characteristic_uuid, .service_uuid = service_uuid};
return characteristic;
+2 -4
View File
@@ -211,10 +211,8 @@ class BleV2Medium : public api::ble_v2::BleMedium {
public:
std::optional<api::ble_v2::GattCharacteristic> CreateCharacteristic(
const Uuid& service_uuid, const Uuid& characteristic_uuid,
const std::vector<api::ble_v2::GattCharacteristic::Permission>&
permissions,
const std::vector<api::ble_v2::GattCharacteristic::Property>&
properties) override;
api::ble_v2::GattCharacteristic::Permission permission,
api::ble_v2::GattCharacteristic::Property property) override;
bool UpdateCharacteristic(
const api::ble_v2::GattCharacteristic& characteristic,
@@ -61,7 +61,8 @@ using ::winrt::Windows::Foundation::Collections::IVectorView;
using ::winrt::Windows::Storage::Streams::Buffer;
using ::winrt::Windows::Storage::Streams::DataReader;
using ::winrt::Windows::Storage::Streams::IBuffer;
using Property = api::ble_v2::GattCharacteristic::Property;
using Permission = api::ble_v2::GattCharacteristic::Permission;
} // namespace
BleGattClient::BleGattClient(BluetoothLEDevice ble_device)
@@ -223,22 +224,27 @@ BleGattClient::GetCharacteristic(const Uuid& service_uuid,
// find a way to map it to api::ble_v2::GattCharacteristic.
GattCharacteristicProperties properties =
gatt_characteristic->CharacteristicProperties();
if (properties == GattCharacteristicProperties::Read) {
result.permissions.push_back(
api::ble_v2::GattCharacteristic::Permission::kRead);
result.properties.push_back(
api::ble_v2::GattCharacteristic::Property::kRead);
} else if (properties == GattCharacteristicProperties::Write) {
result.permissions.push_back(
api::ble_v2::GattCharacteristic::Permission::kWrite);
result.properties.push_back(
api::ble_v2::GattCharacteristic::Property::kWrite);
} else if (properties == GattCharacteristicProperties::Indicate) {
result.permissions.push_back(
api::ble_v2::GattCharacteristic::Permission::kRead);
result.properties.push_back(
api::ble_v2::GattCharacteristic::Property::kIndicate);
result.permission = Permission::kNone;
result.property = Property::kNone;
if ((properties & GattCharacteristicProperties::Read) !=
GattCharacteristicProperties::None) {
result.permission |= Permission::kRead;
result.property |= Property::kRead;
}
if ((properties & GattCharacteristicProperties::Write) !=
GattCharacteristicProperties::None) {
result.permission |= Permission::kWrite;
result.property |= Property::kWrite;
}
if ((properties & GattCharacteristicProperties::Indicate) !=
GattCharacteristicProperties::None) {
result.permission |= Permission::kRead;
result.property |= Property::kIndicate;
}
if ((properties & GattCharacteristicProperties::Notify) !=
GattCharacteristicProperties::None) {
result.permission |= Permission::kRead;
result.property |= Property::kNotify;
}
NEARBY_LOGS(VERBOSE) << __func__ << ": Return Characteristic. uuid="
@@ -77,6 +77,8 @@ using ::winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::
using ::winrt::Windows::Foundation::Collections::IVectorView;
using ::winrt::Windows::Storage::Streams::Buffer;
using ::winrt::Windows::Storage::Streams::DataWriter;
using Permission = api::ble_v2::GattCharacteristic::Permission;
using Property = api::ble_v2::GattCharacteristic::Property;
std::string ConvertGattStatusToString(
GattServiceProviderAdvertisementStatus status) {
@@ -109,8 +111,8 @@ BleGattServer::BleGattServer(api::BluetoothAdapter* adapter,
absl::optional<api::ble_v2::GattCharacteristic>
BleGattServer::CreateCharacteristic(
const Uuid& service_uuid, const Uuid& characteristic_uuid,
const std::vector<api::ble_v2::GattCharacteristic::Permission>& permissions,
const std::vector<api::ble_v2::GattCharacteristic::Property>& properties) {
api::ble_v2::GattCharacteristic::Permission permission,
api::ble_v2::GattCharacteristic::Property property) {
NEARBY_LOGS(VERBOSE) << __func__ << ": create characteristic, service_uuid: "
<< std::string(service_uuid) << ", characteristic_uuid: "
<< std::string(characteristic_uuid);
@@ -126,8 +128,8 @@ BleGattServer::CreateCharacteristic(
api::ble_v2::GattCharacteristic gatt_characteristic;
gatt_characteristic.uuid = characteristic_uuid;
gatt_characteristic.service_uuid = service_uuid;
gatt_characteristic.permissions = permissions;
gatt_characteristic.properties = properties;
gatt_characteristic.permission = permission;
gatt_characteristic.property = property;
GattCharacteristicData gatt_characteristic_data;
gatt_characteristic_data.gatt_characteristic = gatt_characteristic;
@@ -158,12 +160,9 @@ bool BleGattServer::UpdateCharacteristic(
if (is_advertising_) {
// Make sure the character has indication property.
bool is_indicate_characteristic = false;
for (const auto property : it.gatt_characteristic.properties) {
if (property ==
api::ble_v2::GattCharacteristic::Property::kIndicate) {
is_indicate_characteristic = true;
break;
}
if ((it.gatt_characteristic.property & Property::kIndicate) !=
Property::kNone) {
is_indicate_characteristic = true;
}
NEARBY_LOGS(INFO) << __func__
@@ -236,32 +235,39 @@ bool BleGattServer::InitializeGattServer() {
bool is_read_supported = false;
bool is_write_supported = false;
bool is_indicate_supported = false;
bool is_notify_supported = false;
GattLocalCharacteristicParameters gatt_characteristic_parameters;
// Set GATT properties.
GattCharacteristicProperties properties =
GattCharacteristicProperties::None;
for (const auto& property :
characteristic_data.gatt_characteristic.properties) {
if (property == api::ble_v2::GattCharacteristic::Property::kRead) {
properties |= GattCharacteristicProperties::Read;
is_read_supported = true;
} else if (property ==
api::ble_v2::GattCharacteristic::Property::kWrite) {
properties |= GattCharacteristicProperties::Write;
is_write_supported = true;
} else if (property ==
api::ble_v2::GattCharacteristic::Property::kIndicate) {
properties |= GattCharacteristicProperties::Indicate;
is_indicate_supported = true;
}
if ((characteristic_data.gatt_characteristic.property &
Property::kRead) != Property::kNone) {
properties |= GattCharacteristicProperties::Read;
is_read_supported = true;
}
if ((characteristic_data.gatt_characteristic.property &
Property::kWrite) != Property::kNone) {
properties |= GattCharacteristicProperties::Write;
is_write_supported = true;
}
if ((characteristic_data.gatt_characteristic.property &
Property::kIndicate) != Property::kNone) {
properties |= GattCharacteristicProperties::Indicate;
is_indicate_supported = true;
}
if ((characteristic_data.gatt_characteristic.property &
Property::kNotify) != Property::kNone) {
properties |= GattCharacteristicProperties::Notify;
is_notify_supported = true;
}
NEARBY_LOGS(VERBOSE) << __func__
<< ": GATT characteristic properties: read="
<< is_read_supported
<< ",write=" << is_write_supported
<< ",indicate=" << is_indicate_supported;
<< ",indicate=" << is_indicate_supported
<< ",notify=" << is_notify_supported;
gatt_characteristic_parameters.CharacteristicProperties(properties);
gatt_characteristic_parameters.WriteProtectionLevel(
@@ -41,10 +41,8 @@ class BleGattServer : public api::ble_v2::GattServer {
~BleGattServer() override = default;
absl::optional<api::ble_v2::GattCharacteristic> CreateCharacteristic(
const Uuid& service_uuid, const Uuid& characteristic_uuid,
const std::vector<api::ble_v2::GattCharacteristic::Permission>&
permissions,
const std::vector<api::ble_v2::GattCharacteristic::Property>& properties)
override;
api::ble_v2::GattCharacteristic::Permission permission,
api::ble_v2::GattCharacteristic::Property property) override;
bool UpdateCharacteristic(
const api::ble_v2::GattCharacteristic& characteristic,