diff --git a/cpp/cal/api/BUILD b/cpp/cal/api/BUILD index 5ca855b1..864f4e0f 100644 --- a/cpp/cal/api/BUILD +++ b/cpp/cal/api/BUILD @@ -21,10 +21,12 @@ cc_library( ], visibility = [ "//googlemac/iPhone/Shared/Nearby/Connections:__subpackages__", - "//third_party/nearby/cpp:__subpackages__", + "//connections:__subpackages__", + "//third_party/nearby/cpp/cal:__subpackages__", ], deps = [ "//cpp/cal/base:types", + "//internal/platform:base", "@com_google_absl//absl/strings", "@com_google_absl//absl/time", "@com_google_absl//absl/types:optional", diff --git a/cpp/cal/api/ble.h b/cpp/cal/api/ble.h index 29879059..9a5ccc7a 100644 --- a/cpp/cal/api/ble.h +++ b/cpp/cal/api/ble.h @@ -1,4 +1,4 @@ -// Copyright 2020 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -23,16 +23,19 @@ #include "absl/time/time.h" #include "absl/types/optional.h" #include "third_party/nearby/cpp/cal/base/ble_types.h" + namespace nearby { namespace cal { namespace api { +// TODO(b/213835576): Refactor BlePeripheral. The one in BluetoothAdapter should +// be considered, too. class BlePeripheral { public: virtual ~BlePeripheral() {} virtual std::string GetName() const = 0; virtual std::string GetAddress() const = 0; - virtual ByteArray GetAdvertisementBytes() const = 0; + virtual location::nearby::ByteArray GetAdvertisementBytes() const = 0; }; struct ScanResult { @@ -42,9 +45,12 @@ struct ScanResult { absl::Time timestamp; }; +// https://developer.android.com/reference/android/bluetooth/BluetoothGattCharacteristic +// +// Representation of a GATT characteristic. class GattCharacteristic { public: - virtual ~GattCharacteristic() {} + virtual ~GattCharacteristic() = default; enum class Permission { kUnknown = 0, @@ -61,7 +67,10 @@ class GattCharacteristic { kLast, }; - virtual std::string GetServiceUuid() = 0; + virtual std::string GetUuid() const = 0; + + // Returns the UUID of the containing GATT service. + virtual std::string GetServiceUuid() const = 0; }; class ClientGattConnection { @@ -72,10 +81,11 @@ class ClientGattConnection { virtual absl::optional GetCharacteristic( absl::string_view service_uuid, absl::string_view characteristic_uuid) = 0; - virtual absl::optional ReadCharacteristic( + virtual absl::optional ReadCharacteristic( const GattCharacteristic& characteristic) = 0; - virtual bool WriteCharacteristic(const GattCharacteristic& characteristic, - const ByteArray& value) = 0; + virtual bool WriteCharacteristic( + const GattCharacteristic& characteristic, + const location::nearby::ByteArray& value) = 0; virtual void Disconnect() = 0; virtual bool SetCharacteristicNotification( const GattCharacteristic& characteristic, bool enable) = 0; @@ -85,7 +95,7 @@ class ServerGattConnection { public: virtual ~ServerGattConnection() {} virtual bool SendCharacteristic(const GattCharacteristic& characteristic, - const ByteArray& value) = 0; + const location::nearby::ByteArray& value) = 0; }; class ClientGattConnectionLifeCycleCallback { @@ -96,26 +106,55 @@ class ClientGattConnectionLifeCycleCallback { virtual void onCharacteristicRead(ClientGattConnection* connection) = 0; }; -class ServerGattConnectionLifeCycleCallback { - public: - virtual ~ServerGattConnectionLifeCycleCallback() {} - virtual void OnCharacteristicSubscription( - ServerGattConnection* connection, - const GattCharacteristic& characteristic) = 0; - virtual void OnCharacteristicUnsubscription( - ServerGattConnection* connection, - const GattCharacteristic& characteristic) = 0; +// Callback for asynchronous events on the server side of a GATT connection. +struct ServerGattConnectionCallback { + // Called when a remote peripheral connected to us and subscribed to one of + // our characteristics. + std::function + characteristic_subscription_cb; + + // Called when a remote peripheral unsubscribed from one of our + // characteristics. + std::function + characteristic_unsubscription_cb; }; +// https://developer.android.com/reference/android/bluetooth/BluetoothGattServer +// +// Representation of a BLE GATT server. class GattServer { public: - virtual ~GattServer() {} + virtual ~GattServer() = default; + + // Creates a characteristic and adds it to the GATT server under the given + // characteristic and service UUIDs. Returns no value upon error. + // + // Characteristics of the same service UUID should be put under one + // service rather than many services with the same UUID. + // + // If the INDICATE property is included, the characteristic should include the + // official Bluetooth Client Characteristic Configuration descriptor with UUID + // 0x2902 and a WRITE permission. This allows remote clients to write to this + // descriptor and subscribe for characteristic changes. For more information + // about this descriptor, please go to: + // https://www.bluetooth.com/specifications/Gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.Gatt.client_characteristic_configuration.xml virtual std::unique_ptr CreateCharacteristic( absl::string_view service_uuid, absl::string_view characteristic_uuid, - const std::set& permissions, - const std::set& properties) = 0; - virtual bool UpdateCharacteristic(const GattCharacteristic& characteristic, - const ByteArray& value) = 0; + const std::vector& permissions, + const std::vector& properties) = 0; + + // https://developer.android.com/reference/android/bluetooth/BluetoothGattCharacteristic.html#setValue(byte[]) + // + // Locally updates the value of a characteristic and returns whether or not it + // was successful. + // TODO(b/213835576): Refactor GattCharacteristic as a POD struct type. + virtual bool UpdateCharacteristic( + const GattCharacteristic& characteristic, + const location::nearby::ByteArray& value) = 0; + + // Stops a GATT server. virtual void Stop() = 0; }; @@ -123,33 +162,53 @@ class BleSocket { public: virtual ~BleSocket() {} virtual api::BlePeripheral& GetRemotePeripheral() = 0; - virtual Exception Write(const ByteArray& message) = 0; - virtual Exception Close() = 0; - virtual InputStream& GetInputStream() = 0; - virtual OutputStream& GetOutputStream() = 0; + virtual location::nearby::Exception Write( + const location::nearby::ByteArray& message) = 0; + virtual location::nearby::Exception Close() = 0; + virtual location::nearby::InputStream& GetInputStream() = 0; + virtual location::nearby::OutputStream& GetOutputStream() = 0; }; class BleSocketLifeCycleCallback { public: virtual ~BleSocketLifeCycleCallback() {} - virtual void OnMessageReceived(BleSocket* socket, - const ByteArray& message) = 0; + virtual void OnMessageReceived( + BleSocket* socket, const location::nearby::ByteArray& message) = 0; virtual void OnDisconnected(BleSocket* socket) = 0; }; class ServerBleSocketLifeCycleCallback : public BleSocketLifeCycleCallback { public: ~ServerBleSocketLifeCycleCallback() override {} - virtual void OnSocketEstablished(BleSocket* socket) = 0; + virtual void OnSocketEstablished(BleSocket& socket) = 0; }; +// The main BLE medium used inside of Nearby. This serves as the entry point for +// all BLE and GATT related operations. class BleMedium { public: using Mtu = uint32_t; - virtual ~BleMedium() {} - virtual bool StartAdvertising( - const BleAdvertisementData& advertisement_data) = 0; - virtual void StopAdvertising(const std::string& service_id) = 0; + + virtual ~BleMedium() = default; + + // https://developer.android.com/reference/android/bluetooth/le/BluetoothLeAdvertiser.html#startAdvertising(android.bluetooth.le.AdvertiseSettings,%20android.bluetooth.le.AdvertiseData,%20android.bluetooth.le.AdvertiseData,%20android.bluetooth.le.AdvertiseCallback) + // + // Starts BLE advertising and returns whether or not it was successful. + // + // Power mode should be interpreted in the following way: + // LOW: + // - TX power = medium + // HIGH: + // - TX power = high + virtual bool StartAdvertising(const BleAdvertisementData& advertising_data, + const BleAdvertisementData& scan_response_data, + PowerMode power_mode) = 0; + + // https://developer.android.com/reference/android/bluetooth/le/BluetoothLeAdvertiser.html#stopAdvertising(android.bluetooth.le.AdvertiseCallback) + // + // Stops advertising. + virtual bool StopAdvertising() = 0; + class ScanCallback { public: virtual ~ScanCallback() {} @@ -161,8 +220,13 @@ class BleMedium { PowerMode power_mode, const ScanCallback& scan_callback) = 0; virtual void StopScanning() = 0; + + // https://developer.android.com/reference/android/bluetooth/BluetoothManager#openGattServer(android.content.Context,%20android.bluetooth.BluetoothGattServerCallback) + // + // Starts a GATT server. Returns a nullptr upon error. virtual std::unique_ptr StartGattServer( - const ServerGattConnectionLifeCycleCallback& callback) = 0; + ServerGattConnectionCallback callback) = 0; + virtual bool StartListeningForIncomingBleSockets( const ServerBleSocketLifeCycleCallback& callback) = 0; virtual void StopListeningForIncomingBleSockets() = 0; @@ -177,4 +241,5 @@ class BleMedium { } // namespace api } // namespace cal } // namespace nearby + #endif // CAL_API_BLE_H_ diff --git a/cpp/cal/base/BUILD b/cpp/cal/base/BUILD index 325cd7d6..c4e27dbc 100644 --- a/cpp/cal/base/BUILD +++ b/cpp/cal/base/BUILD @@ -25,5 +25,7 @@ cc_library( ], deps = [ "//internal/platform:base", + "@com_google_absl//absl/container:flat_hash_map", + "@com_google_absl//absl/container:flat_hash_set", ], ) diff --git a/cpp/cal/base/ble_types.h b/cpp/cal/base/ble_types.h index 091bff72..fedab335 100644 --- a/cpp/cal/base/ble_types.h +++ b/cpp/cal/base/ble_types.h @@ -1,4 +1,4 @@ -// Copyright 2020 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,8 +16,8 @@ #define CAL_BASE_TYPES_H_ // TODO(hais) relocate base def class accordingly. -#include - +#include "absl/container/flat_hash_map.h" +#include "absl/container/flat_hash_set.h" #include "internal/platform/byte_array.h" #include "internal/platform/exception.h" #include "internal/platform/input_stream.h" @@ -27,11 +27,6 @@ namespace nearby { namespace cal { -using ByteArray = location::nearby::ByteArray; -using Exception = location::nearby::Exception; -using InputStream = location::nearby::InputStream; -using OutputStream = location::nearby::OutputStream; - enum class AdvertiseMode { kUnknown = 0, kLowPower = 1, @@ -39,6 +34,7 @@ enum class AdvertiseMode { kLowLatency = 3, }; +// Coarse representation of power settings throughout all BLE operations. enum class PowerMode { kUnknown = 0, kUltraLow = 1, @@ -54,15 +50,37 @@ struct AdvertiseSettings { bool is_connectable; }; +// https://developer.android.com/reference/android/bluetooth/le/AdvertiseData +// +// Bundle of data found in a BLE advertisement. +// +// All service UUIDs will conform to the 16-bit Bluetooth base UUID, +// 0000xxxx-0000-1000-8000-00805F9B34FB. This makes it possible to store two +// byte service UUIDs in the advertisement. struct BleAdvertisementData { - AdvertiseSettings advertise_settings; - // service UUID to advertise bytes map:16-bit service UUID - service Data + using TxPowerLevel = std::int8_t; + + static constexpr TxPowerLevel kUnspecifiedTxPowerLevel = + std::numeric_limits::min(); + + bool is_connectable; + + // If tx_power_level is not set to kUnspecifiedTxPowerLevel, platform + // implementer needs to set the TxPowerLevel. + TxPowerLevel tx_power_level; + + // If the set is not empty, the platform implementer needs to add the + // service_uuids in the advertisement data. + absl::flat_hash_set service_uuids; + + // Maps service UUIDs to their service data. // - // Data type value : 0x16 - // if platform can't advertise data from this key (reaonly in iOS), then (iOS) - // should advertise data via LocalName data type. It means the service_uuid - // here is useless for iOS platform. - std::map service_data_map; + // Note if platform can't advertise data from Data type (0x16) + // (reaonly in iOS), then (iOS) should advertise data via LocalName data type + // (0x08). + // It means the iOS should take the first index of service_data as the data + // for LocalName type. + absl::flat_hash_map service_data; }; enum class ScanMode { diff --git a/cpp/cal/public/BUILD b/cpp/cal/public/BUILD index 7ebd95b4..b4e3badd 100644 --- a/cpp/cal/public/BUILD +++ b/cpp/cal/public/BUILD @@ -23,7 +23,6 @@ cc_library( "ble.h", ], visibility = [ - "//googlemac/iPhone/Shared/Nearby/Connections:__subpackages__", "//third_party/nearby:__subpackages__", ], deps = [ @@ -31,20 +30,3 @@ cc_library( "//cpp/cal/base:types", ], ) - -cc_test( - name = "cal_test", - size = "small", - timeout = "moderate", - srcs = [ - "ble_test.cc", - ], - deps = [ - ":ble", - "//third_party/nearby/cpp/cal/api:ble", - "//cpp/cal/base:types", - "@com_github_protobuf_matchers//protobuf-matchers", - "@com_google_googletest//:gtest", - "@com_google_googletest//:gtest_main", - ], -) diff --git a/cpp/cal/public/ble.cc b/cpp/cal/public/ble.cc index 15c7e6f8..99149ff8 100644 --- a/cpp/cal/public/ble.cc +++ b/cpp/cal/public/ble.cc @@ -1,4 +1,4 @@ -// Copyright 2020 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -22,6 +22,11 @@ namespace nearby { namespace cal { +using ::location::nearby::ByteArray; +using ::location::nearby::Exception; +using ::location::nearby::InputStream; +using ::location::nearby::OutputStream; + InputStream& BleSocket::GetInputStream() { return impl_->GetInputStream(); } OutputStream& BleSocket::GetOutputStream() { return impl_->GetOutputStream(); } Exception BleSocket::Close() { return impl_->Close(); } @@ -37,7 +42,7 @@ BlePeripheral::BlePeripheral(api::BlePeripheral* peripheral) { std::string BlePeripheral::GetName() const { return impl_->GetName(); } std::string BlePeripheral::GetAddress() const { return impl_->GetAddress(); } ByteArray BlePeripheral::GetAdvertisementBytes( - const std::string& service_id) const { + absl::string_view service_id) const { return impl_->GetAdvertisementBytes(); } api::BlePeripheral& BlePeripheral::GetImpl() { return *impl_; } @@ -47,20 +52,18 @@ BleMedium::BleMedium(std::unique_ptr impl) { impl_ = std::move(impl); } -bool BleMedium::StartAdvertising(const std::string& service_id, - const AdvertiseSettings& settings, - const ByteArray& advertisement_bytes, - const std::string& service_uuid) { - return impl_->StartAdvertising( - BleAdvertisementData{.advertise_settings = settings, - .service_data_map = std::map( - {{service_uuid, advertisement_bytes}})}); +bool BleMedium::StartAdvertising(const BleAdvertisementData& advertising_data, + const BleAdvertisementData& scan_response_data, + PowerMode power_mode) { + return impl_->StartAdvertising(advertising_data, scan_response_data, + power_mode); } -bool BleMedium::StopAdvertising(const std::string& service_id) { + +bool BleMedium::StopAdvertising() { // TODO(hais): real impl b/196132654. - impl_->StopAdvertising(service_id); - return true; + return impl_->StopAdvertising(); } + bool BleMedium::StartScanning( const std::string& service_id, const ScanSettings& settings, const std::string& fast_advertisement_service_uuid, diff --git a/cpp/cal/public/ble.h b/cpp/cal/public/ble.h index 5d0352de..2aed770d 100644 --- a/cpp/cal/public/ble.h +++ b/cpp/cal/public/ble.h @@ -1,4 +1,4 @@ -// Copyright 2020 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -27,7 +27,8 @@ class BlePeripheral final { explicit BlePeripheral(api::BlePeripheral* peripheral); std::string GetName() const; std::string GetAddress() const; - ByteArray GetAdvertisementBytes(const std::string& service_id) const; + location::nearby::ByteArray GetAdvertisementBytes( + absl::string_view service_id) const; api::BlePeripheral& GetImpl(); bool IsValid() const; @@ -36,9 +37,9 @@ class BlePeripheral final { }; class BleSocket final { - InputStream& GetInputStream(); - OutputStream& GetOutputStream(); - Exception Close(); + location::nearby::InputStream& GetInputStream(); + location::nearby::OutputStream& GetOutputStream(); + location::nearby::Exception Close(); api::BlePeripheral& GetRemotePeripheral(); bool IsValid() const; api::BleSocket& GetImpl(); @@ -52,7 +53,7 @@ class BleMedium final { struct DiscoveredPeripheralCallback { std::function + const location::nearby::ByteArray& advertisement_bytes)> peripheral_discovered_cb; std::function @@ -70,11 +71,12 @@ class BleMedium final { }; explicit BleMedium(std::unique_ptr impl); - bool StartAdvertising(const std::string& service_id, - const AdvertiseSettings& settings, - const ByteArray& advertisement_bytes, - const std::string& fast_advertisement_service_uuid); - bool StopAdvertising(const std::string& service_id); + + bool StartAdvertising(const BleAdvertisementData& advertising_data, + const BleAdvertisementData& scan_response_data, + PowerMode power_mode); + bool StopAdvertising(); + bool StartScanning(const std::string& service_id, const ScanSettings& settings, const std::string& fast_advertisement_service_uuid, diff --git a/cpp/cal/public/ble_test.cc b/cpp/cal/public/ble_test.cc index d7c01520..48581fc2 100644 --- a/cpp/cal/public/ble_test.cc +++ b/cpp/cal/public/ble_test.cc @@ -1,4 +1,4 @@ -// Copyright 2020 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,12 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "third_party/nearby/cpp/cal/api/ble.h" + #include #include "gmock/gmock.h" #include "protobuf-matchers/protocol-buffer-matchers.h" #include "gtest/gtest.h" -#include "third_party/nearby/cpp/cal/api/ble.h" #include "third_party/nearby/cpp/cal/base/ble_types.h" #include "third_party/nearby/cpp/cal/public/ble.h"