From 8f22ffefd4f200e3741af45387700e619d5c3a05 Mon Sep 17 00:00:00 2001 From: edwinwu Date: Mon, 21 Feb 2022 22:13:11 -0800 Subject: [PATCH] [BLE Refactor] Move /cal/ble.h , base_types.h to /platform/implementation/ble_v2.h PiperOrigin-RevId: 430133309 --- cpp/cal/api/BUILD | 34 --- cpp/cal/api/ble.h | 245 ---------------------- cpp/cal/base/BUILD | 31 --- cpp/cal/base/ble_types.h | 102 --------- cpp/cal/public/BUILD | 32 --- cpp/cal/public/ble.cc | 106 ---------- cpp/cal/public/ble.h | 104 --------- cpp/cal/public/ble_test.cc | 184 ---------------- internal/platform/implementation/BUILD | 2 + internal/platform/implementation/ble_v2.h | 214 ++++++++++--------- 10 files changed, 107 insertions(+), 947 deletions(-) delete mode 100644 cpp/cal/api/BUILD delete mode 100644 cpp/cal/api/ble.h delete mode 100644 cpp/cal/base/BUILD delete mode 100644 cpp/cal/base/ble_types.h delete mode 100644 cpp/cal/public/BUILD delete mode 100644 cpp/cal/public/ble.cc delete mode 100644 cpp/cal/public/ble.h delete mode 100644 cpp/cal/public/ble_test.cc diff --git a/cpp/cal/api/BUILD b/cpp/cal/api/BUILD deleted file mode 100644 index 864f4e0f..00000000 --- a/cpp/cal/api/BUILD +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -licenses(["notice"]) - -cc_library( - name = "ble", - hdrs = [ - "ble.h", - ], - visibility = [ - "//googlemac/iPhone/Shared/Nearby/Connections:__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 deleted file mode 100644 index 9a5ccc7a..00000000 --- a/cpp/cal/api/ble.h +++ /dev/null @@ -1,245 +0,0 @@ -// 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. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CAL_API_BLE_H_ -#define CAL_API_BLE_H_ - -#include -#include -#include - -#include "absl/strings/string_view.h" -#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 location::nearby::ByteArray GetAdvertisementBytes() const = 0; -}; - -struct ScanResult { - std::unique_ptr peripheral; - int rssi; - int tx_power; - absl::Time timestamp; -}; - -// https://developer.android.com/reference/android/bluetooth/BluetoothGattCharacteristic -// -// Representation of a GATT characteristic. -class GattCharacteristic { - public: - virtual ~GattCharacteristic() = default; - - enum class Permission { - kUnknown = 0, - kRead = 1, - kWrite = 2, - kLast, - }; - - enum class Property { - kUnknown = 0, - kRead = 1, - kWrite = 2, - kIndicate = 3, - kLast, - }; - - virtual std::string GetUuid() const = 0; - - // Returns the UUID of the containing GATT service. - virtual std::string GetServiceUuid() const = 0; -}; - -class ClientGattConnection { - public: - virtual ~ClientGattConnection() {} - virtual BlePeripheral& GetPeripheral() = 0; - virtual bool DiscoverServices() = 0; - virtual absl::optional GetCharacteristic( - absl::string_view service_uuid, - absl::string_view characteristic_uuid) = 0; - virtual absl::optional ReadCharacteristic( - const GattCharacteristic& characteristic) = 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; -}; - -class ServerGattConnection { - public: - virtual ~ServerGattConnection() {} - virtual bool SendCharacteristic(const GattCharacteristic& characteristic, - const location::nearby::ByteArray& value) = 0; -}; - -class ClientGattConnectionLifeCycleCallback { - public: - virtual ~ClientGattConnectionLifeCycleCallback() {} - virtual void OnDisconnected(ClientGattConnection* connection) = 0; - virtual void onConnectionStateChange(ClientGattConnection* connection) = 0; - virtual void onCharacteristicRead(ClientGattConnection* connection) = 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() = 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::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; -}; - -class BleSocket { - public: - virtual ~BleSocket() {} - virtual api::BlePeripheral& GetRemotePeripheral() = 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 location::nearby::ByteArray& message) = 0; - virtual void OnDisconnected(BleSocket* socket) = 0; -}; - -class ServerBleSocketLifeCycleCallback : public BleSocketLifeCycleCallback { - public: - ~ServerBleSocketLifeCycleCallback() override {} - 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() = 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() {} - virtual void OnAdvertisementFound( - const ScanResult& scan_result, - const BleAdvertisementData& advertisement_data) = 0; - }; - virtual bool StartScanning(const std::set& service_uuids, - 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( - ServerGattConnectionCallback callback) = 0; - - virtual bool StartListeningForIncomingBleSockets( - const ServerBleSocketLifeCycleCallback& callback) = 0; - virtual void StopListeningForIncomingBleSockets() = 0; - virtual std::unique_ptr ConnectToGattServer( - BlePeripheral* peripheral, Mtu mtu, PowerMode power_mode, - const ClientGattConnectionLifeCycleCallback& callback) = 0; - virtual std::unique_ptr EstablishBleSocket( - BlePeripheral* peripheral, - const BleSocketLifeCycleCallback& callback) = 0; -}; - -} // namespace api -} // namespace cal -} // namespace nearby - -#endif // CAL_API_BLE_H_ diff --git a/cpp/cal/base/BUILD b/cpp/cal/base/BUILD deleted file mode 100644 index c4e27dbc..00000000 --- a/cpp/cal/base/BUILD +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -licenses(["notice"]) - -cc_library( - name = "types", - hdrs = [ - "ble_types.h", - ], - visibility = [ - "//googlemac/iPhone/Shared/Nearby/Connections:__subpackages__", - "//third_party/nearby/cpp:__subpackages__", - ], - 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 deleted file mode 100644 index fedab335..00000000 --- a/cpp/cal/base/ble_types.h +++ /dev/null @@ -1,102 +0,0 @@ -// 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. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CAL_BASE_TYPES_H_ -#define CAL_BASE_TYPES_H_ - -// TODO(hais) relocate base def class accordingly. -#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" -#include "internal/platform/listeners.h" -#include "internal/platform/output_stream.h" - -namespace nearby { -namespace cal { - -enum class AdvertiseMode { - kUnknown = 0, - kLowPower = 1, - kBalanced = 2, - kLowLatency = 3, -}; - -// Coarse representation of power settings throughout all BLE operations. -enum class PowerMode { - kUnknown = 0, - kUltraLow = 1, - kLow = 2, - kMedium = 3, - kHigh = 4, -}; - -struct AdvertiseSettings { - AdvertiseMode advertise_mode; - PowerMode power_mode; - int timeout; - 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 { - 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. - // - // 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 { - kUnknown = 0, - kLowPower, - kBalanced, - kLowLatency, - // kOpportunistic not supported -}; - -struct ScanSettings { - ScanMode scan_mode; - // Do we need reportDelay, phy, legacy? -}; - -} // namespace cal -} // namespace nearby - -#endif // CAL_BASE_TYPES_H_ diff --git a/cpp/cal/public/BUILD b/cpp/cal/public/BUILD deleted file mode 100644 index b4e3badd..00000000 --- a/cpp/cal/public/BUILD +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -licenses(["notice"]) - -cc_library( - name = "ble", - srcs = [ - "ble.cc", - ], - hdrs = [ - "ble.h", - ], - visibility = [ - "//third_party/nearby:__subpackages__", - ], - deps = [ - "//third_party/nearby/cpp/cal/api:ble", - "//cpp/cal/base:types", - ], -) diff --git a/cpp/cal/public/ble.cc b/cpp/cal/public/ble.cc deleted file mode 100644 index 99149ff8..00000000 --- a/cpp/cal/public/ble.cc +++ /dev/null @@ -1,106 +0,0 @@ -// 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. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "third_party/nearby/cpp/cal/public/ble.h" - -#include - -#include "third_party/nearby/cpp/cal/api/ble.h" -#include "third_party/nearby/cpp/cal/base/ble_types.h" - -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(); } -api::BlePeripheral& BleSocket::GetRemotePeripheral() { - return impl_->GetRemotePeripheral(); -} -bool BleSocket::IsValid() const { return false; } -api::BleSocket& BleSocket::GetImpl() { return *impl_; } - -BlePeripheral::BlePeripheral(api::BlePeripheral* peripheral) { - impl_ = peripheral; -} -std::string BlePeripheral::GetName() const { return impl_->GetName(); } -std::string BlePeripheral::GetAddress() const { return impl_->GetAddress(); } -ByteArray BlePeripheral::GetAdvertisementBytes( - absl::string_view service_id) const { - return impl_->GetAdvertisementBytes(); -} -api::BlePeripheral& BlePeripheral::GetImpl() { return *impl_; } -bool BlePeripheral::IsValid() const { return impl_ != nullptr; } - -BleMedium::BleMedium(std::unique_ptr impl) { - impl_ = std::move(impl); -} - -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() { - // TODO(hais): real impl b/196132654. - return impl_->StopAdvertising(); -} - -bool BleMedium::StartScanning( - const std::string& service_id, const ScanSettings& settings, - const std::string& fast_advertisement_service_uuid, - DiscoveredPeripheralCallback callback) { - // TODO(hais): real impl b/196132654. - return false; -} -bool BleMedium::StopScanning(const std::string& service_id) { - // TODO(hais): real impl b/196132654. - return false; -} - -bool BleMedium::StartAcceptingConnections(const std::string& service_id, - AcceptedConnectionCallback callback) { - // TODO(hais): real impl b/196132654. - return false; -} - -bool cal::BleMedium::StopAcceptingConnections(const std::string& service_id) { - // TODO(hais): real impl b/196132654. - return false; -} -std::unique_ptr cal::BleMedium::ConnectGatt( - nearby::cal::api::BlePeripheral& peripheral, - const api::GattCharacteristic& characteristic, - const api::ClientGattConnectionLifeCycleCallback& callback) { - // TODO(hais): real impl b/196132654. - return impl_->ConnectToGattServer(&peripheral, -1, PowerMode::kUnknown, - callback); -} -void cal::BleMedium::DisconnectGatt( - api::BlePeripheral& peripheral, - const api::GattCharacteristic& characteristic) { - // TODO(hais): real impl b/196132654. -} -bool cal::BleMedium::IsValid() const { return impl_ != nullptr; } -cal::api::BleMedium& cal::BleMedium::GetImpl() { return *impl_; } - -} // namespace cal -} // namespace nearby diff --git a/cpp/cal/public/ble.h b/cpp/cal/public/ble.h deleted file mode 100644 index 2aed770d..00000000 --- a/cpp/cal/public/ble.h +++ /dev/null @@ -1,104 +0,0 @@ -// 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. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CAL_PUBLIC_BLE_H_ -#define CAL_PUBLIC_BLE_H_ - -#include - -#include "third_party/nearby/cpp/cal/api/ble.h" -#include "third_party/nearby/cpp/cal/base/ble_types.h" - -namespace nearby { -namespace cal { - -class BlePeripheral final { - explicit BlePeripheral(api::BlePeripheral* peripheral); - std::string GetName() const; - std::string GetAddress() const; - location::nearby::ByteArray GetAdvertisementBytes( - absl::string_view service_id) const; - api::BlePeripheral& GetImpl(); - bool IsValid() const; - - private: - api::BlePeripheral* impl_; -}; - -class BleSocket final { - location::nearby::InputStream& GetInputStream(); - location::nearby::OutputStream& GetOutputStream(); - location::nearby::Exception Close(); - api::BlePeripheral& GetRemotePeripheral(); - bool IsValid() const; - api::BleSocket& GetImpl(); - - private: - std::shared_ptr impl_; -}; - -class BleMedium final { - public: - struct DiscoveredPeripheralCallback { - std::function - peripheral_discovered_cb; - std::function - peripheral_lost_cb; - }; - - struct AcceptedConnectionCallback { - std::function - accepted_cb = - location::nearby::DefaultCallback(); - }; - - struct AcceptedConnectionInfo { - BleSocket socket; - }; - - explicit BleMedium(std::unique_ptr impl); - - 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, - DiscoveredPeripheralCallback callback); - bool StopScanning(const std::string& service_id); - bool StartAcceptingConnections(const std::string& service_id, - AcceptedConnectionCallback callback); - bool StopAcceptingConnections(const std::string& service_id); - std::unique_ptr ConnectGatt( - api::BlePeripheral& peripheral, - const api::GattCharacteristic& characteristic, - const api::ClientGattConnectionLifeCycleCallback& callback); - void DisconnectGatt(api::BlePeripheral& peripheral, - const api::GattCharacteristic& characteristic); - bool IsValid() const; - api::BleMedium& GetImpl(); - - private: - std::unique_ptr impl_; -}; - -} // namespace cal -} // namespace nearby - -#endif // CAL_PUBLIC_BLE_H_ diff --git a/cpp/cal/public/ble_test.cc b/cpp/cal/public/ble_test.cc deleted file mode 100644 index 48581fc2..00000000 --- a/cpp/cal/public/ble_test.cc +++ /dev/null @@ -1,184 +0,0 @@ -// 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. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// 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/base/ble_types.h" -#include "third_party/nearby/cpp/cal/public/ble.h" - -namespace nearby { -namespace cal { -namespace { - -class MockBlePeripheral : public api::BlePeripheral { - MOCK_METHOD(std::string, GetName, (), (const override)); - MOCK_METHOD(std::string, GetAddress, (), (const override)); - MOCK_METHOD(ByteArray, GetAdvertisementBytes, (), (const override)); -}; - -class MockGattCharacteristic : public api::GattCharacteristic { - MOCK_METHOD(std::string, GetServiceUuid, (), (override)); -}; - -class MockClientGattConnection : public api::ClientGattConnection { - public: - MOCK_METHOD(api::BlePeripheral&, GetPeripheral, (), (override)); - MOCK_METHOD(bool, DiscoverServices, (), (override)); - MOCK_METHOD(absl::optional, GetCharacteristic, - (absl::string_view service_uuid, - absl::string_view characteristic_uuid), - (override)); - MOCK_METHOD(absl::optional, ReadCharacteristic, - (const api::GattCharacteristic& characteristic), (override)); - MOCK_METHOD(bool, WriteCharacteristic, - (const api::GattCharacteristic& characteristic, - const ByteArray& value), - (override)); - MOCK_METHOD(void, Disconnect, (), (override)); - MOCK_METHOD(bool, SetCharacteristicNotification, - (const api::GattCharacteristic& characteristic, bool enable), - (override)); -}; - -class MockServerGattConnection : public api::ServerGattConnection { - public: - MOCK_METHOD(bool, SendCharacteristic, - (const api::GattCharacteristic& characteristic, - const ByteArray& value), - (override)); -}; - -class MockClientGattConnectionLifeCycleCallback - : public api::ClientGattConnectionLifeCycleCallback { - public: - MOCK_METHOD(void, OnDisconnected, (api::ClientGattConnection * connection), - (override)); - MOCK_METHOD(void, onConnectionStateChange, - (api::ClientGattConnection * connection), (override)); - MOCK_METHOD(void, onCharacteristicRead, - (api::ClientGattConnection * connection), (override)); -}; - -class MockServerGattConnectionLifeCycleCallback - : public api::ServerGattConnectionLifeCycleCallback { - public: - MOCK_METHOD(void, OnCharacteristicSubscription, - (api::ServerGattConnection * connection, - const api::GattCharacteristic& characteristic), - (override)); - MOCK_METHOD(void, OnCharacteristicUnsubscription, - (api::ServerGattConnection * connection, - const api::GattCharacteristic& characteristic), - (override)); -}; - -class MockGattServer : public api::GattServer { - public: - MOCK_METHOD(std::unique_ptr, CreateCharacteristic, - (absl::string_view service_uuid, - absl::string_view characteristic_uuid, - const std::set& permissions, - const std::set& properties), - (override)); - MOCK_METHOD(bool, UpdateCharacteristic, - (const api::GattCharacteristic& characteristic, - const ByteArray& value), - (override)); - MOCK_METHOD(void, Stop, (), (override)); -}; - -class MockBleSocket : public api::BleSocket { - public: - MOCK_METHOD(api::BlePeripheral&, GetRemotePeripheral, (), (override)); - MOCK_METHOD(Exception, Write, (const ByteArray& message), (override)); - MOCK_METHOD(Exception, Close, (), (override)); -}; - -class MockBleSocketLifeCycleCallback : public api::BleSocketLifeCycleCallback { - public: - MOCK_METHOD(void, OnMessageReceived, - (api::BleSocket * socket, const ByteArray& message), (override)); - MOCK_METHOD(void, OnDisconnected, (api::BleSocket * socket), (override)); -}; - -class MockServerBleSocketLifeCycleCallback - : public api::ServerBleSocketLifeCycleCallback { - public: - MOCK_METHOD(void, OnSocketEstablished, (api::BleSocket * socket), (override)); -}; - -class MockBleMedium : public api::BleMedium { - public: - MOCK_METHOD(bool, StartAdvertising, - (const BleAdvertisementData& advertisement_data), (override)); - MOCK_METHOD(void, StopAdvertising, (const std::string& service_id), - (override)); - class MockScanCallback : public api::BleMedium::ScanCallback { - public: - MOCK_METHOD(void, OnAdvertisementFound, - (const api::ScanResult& scan_result, - const BleAdvertisementData& advertisement_data), - (override)); - }; - MOCK_METHOD(bool, StartScanning, - (const std::set& service_uuids, PowerMode power_mode, - const ScanCallback& scan_callback), - (override)); - MOCK_METHOD(void, StopScanning, (), (override)); - MOCK_METHOD(std::unique_ptr, StartGattServer, - (const api::ServerGattConnectionLifeCycleCallback& callback), - (override)); - MOCK_METHOD(bool, StartListeningForIncomingBleSockets, - (const api::ServerBleSocketLifeCycleCallback& callback), - (override)); - MOCK_METHOD(void, StopListeningForIncomingBleSockets, (), (override)); - MOCK_METHOD(std::unique_ptr, ConnectToGattServer, - (api::BlePeripheral * peripheral, Mtu mtu, PowerMode power_mode, - const api::ClientGattConnectionLifeCycleCallback& callback), - (override)); - MOCK_METHOD(std::unique_ptr, EstablishBleSocket, - (api::BlePeripheral * peripheral, - const api::BleSocketLifeCycleCallback& callback), - (override)); -}; - -class BleTest : public ::testing::Test { - public: - ::nearby::cal::BleMedium ble_medium_{std::make_unique()}; - const std::string kServiceId = "BleTest"; - const AdvertiseSettings kAdvertiseSettings = AdvertiseSettings{}; - const ByteArray kAdvertisementBytes = ByteArray{"BleTestBytes"}; - const std::string kServiceUuid = "0x2fec"; - const BleAdvertisementData kBleAdvertisementData = { - kAdvertiseSettings, {{kServiceUuid, kAdvertisementBytes}}}; -}; - -TEST_F(BleTest, ConstructorWorks) { EXPECT_TRUE(ble_medium_.IsValid()); } - -TEST_F(BleTest, StartAdvertising) { - MockBleMedium* mock_ble_medium = - static_cast(&ble_medium_.GetImpl()); - EXPECT_CALL(*mock_ble_medium, StartAdvertising).Times(1); - ble_medium_.StartAdvertising(kServiceId, kAdvertiseSettings, - kAdvertisementBytes, kServiceId); -} - -} // namespace -} // namespace cal -} // namespace nearby diff --git a/internal/platform/implementation/BUILD b/internal/platform/implementation/BUILD index d8b24814..75b9ad65 100644 --- a/internal/platform/implementation/BUILD +++ b/internal/platform/implementation/BUILD @@ -69,6 +69,8 @@ cc_library( "//connections/implementation/proto:offline_wire_formats_cc_proto", "//internal/platform:base", "//internal/platform:cancellation_flag", + "@com_google_absl//absl/container:flat_hash_map", + "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", ], diff --git a/internal/platform/implementation/ble_v2.h b/internal/platform/implementation/ble_v2.h index 8a20d0b7..16cf981b 100644 --- a/internal/platform/implementation/ble_v2.h +++ b/internal/platform/implementation/ble_v2.h @@ -22,16 +22,30 @@ #include #include +#include "absl/container/flat_hash_map.h" +#include "absl/container/flat_hash_set.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "internal/platform/byte_array.h" #include "internal/platform/exception.h" +#include "internal/platform/input_stream.h" +#include "internal/platform/listeners.h" +#include "internal/platform/output_stream.h" namespace location { namespace nearby { namespace api { namespace ble_v2 { +// Coarse representation of power settings throughout all BLE operations. +enum class PowerMode { + kUnknown = 0, + kUltraLow = 1, + kLow = 2, + kMedium = 3, + kHigh = 4, +}; + // https://developer.android.com/reference/android/bluetooth/le/AdvertiseData // // Bundle of data found in a BLE advertisement. @@ -40,30 +54,37 @@ namespace ble_v2 { // 0000xxxx-0000-1000-8000-00805F9B34FB. This makes it possible to store two // byte service UUIDs in the advertisement. struct BleAdvertisementData { - using TxPowerLevel = int8_t; + using TxPowerLevel = std::int8_t; - static const TxPowerLevel kUnspecifiedTxPowerLevel = + static constexpr TxPowerLevel kUnspecifiedTxPowerLevel = std::numeric_limits::min(); bool is_connectable; - // When set to kUnspecifiedTxPowerLevel, TX power should not be included in - // the advertisement data. + + // If tx_power_level is not set to kUnspecifiedTxPowerLevel, platform + // implementer needs to set the TxPowerLevel. TxPowerLevel tx_power_level; - // When set to an empty string, local name should not be included in the - // advertisement data. - std::string local_name; - // When set to an empty vector, the set of 16-bit service class UUIDs should - // not be included in the advertisement data. - std::set service_uuids; + + // 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. - std::map service_data; + // + // 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; }; -// Opaque wrapper over a BLE peripheral. Must be able to uniquely identify a -// peripheral so that we can connect to its GATT server. +// TODO(b/213835576): Refactor BlePeripheral. The one in BluetoothAdapter +// should be considered, too. Opaque wrapper over a BLE peripheral. Must be +// able to uniquely identify a peripheral so that we can connect to its GATT +// server. class BlePeripheral { public: - virtual ~BlePeripheral() {} + virtual ~BlePeripheral() = default; // https://developer.android.com/reference/android/bluetooth/BluetoothDevice#getAddress() // @@ -75,11 +96,7 @@ class BlePeripheral { // https://developer.android.com/reference/android/bluetooth/BluetoothGattCharacteristic // // Representation of a GATT characteristic. -class GattCharacteristic { - public: - virtual ~GattCharacteristic() {} - - // Possible permissions of a GATT characteristic. +struct GattCharacteristic { enum class Permission { kUnknown = 0, kRead = 1, @@ -87,7 +104,6 @@ class GattCharacteristic { kLast, }; - // Possible properties of a GATT characteristic. enum class Property { kUnknown = 0, kRead = 1, @@ -96,11 +112,17 @@ class GattCharacteristic { kLast, }; - // Returns the UUID of this characteristic. - virtual std::string GetUuid() = 0; + std::string uuid; + std::string servie_uuid; - // Returns the UUID of the containing GATT service. - virtual std::string GetServiceUuid() = 0; + // Hashable + template + friend H AbslHashValue(H h, const GattCharacteristic& s) { + return H::combine(std::move(h), s.uuid, s.servie_uuid); + } + bool operator==(const GattCharacteristic& rhs) const { + return this->uuid == rhs.uuid && this->servie_uuid == rhs.servie_uuid; + } }; // https://developer.android.com/reference/android/bluetooth/BluetoothGatt @@ -108,11 +130,9 @@ class GattCharacteristic { // Representation of a client GATT connection to a remote GATT server. class ClientGattConnection { public: - virtual ~ClientGattConnection() {} + virtual ~ClientGattConnection() = default; // https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#getDevice() - // - // Retrieves the BLE peripheral that this connection is tied to. virtual BlePeripheral& GetPeripheral() = 0; // https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#discoverServices() @@ -139,8 +159,6 @@ class ClientGattConnection { // https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#readCharacteristic(android.bluetooth.BluetoothGattCharacteristic) // https://developer.android.com/reference/android/bluetooth/BluetoothGattCharacteristic.html#getValue() - // - // Reads a GATT characteristic. No value is returned upon error. virtual absl::optional ReadCharacteristic( const GattCharacteristic& characteristic) = 0; @@ -153,8 +171,6 @@ class ClientGattConnection { const ByteArray& value) = 0; // https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#disconnect() - // - // Disconnects a GATT connection. virtual void Disconnect() = 0; }; @@ -163,13 +179,14 @@ class ClientGattConnection { // Representation of a server GATT connection to a remote GATT client. class ServerGattConnection { public: - virtual ~ServerGattConnection() {} + virtual ~ServerGattConnection() = default; // https://developer.android.com/reference/android/bluetooth/BluetoothGattCharacteristic.html#setValue(byte[]) // https://developer.android.com/reference/android/bluetooth/BluetoothGattServer.html#notifyCharacteristicChanged(android.bluetooth.BluetoothDevice,%20android.bluetooth.BluetoothGattCharacteristic,%20boolean) // // Sends a notification (via indication) to the client that a characteristic - // has changed with the given value. Returns whether or not it was successful. + // has changed with the given value. Returns whether or not it was + // successful. // // The value sent does not have to reflect the locally stored characteristic // value. To update the local value, call GattServer::UpdateCharacteristic. @@ -178,30 +195,26 @@ class ServerGattConnection { }; // Callback for asynchronous events on the client side of a GATT connection. -class ClientGattConnectionLifeCycleCallback { +struct ClientGattConnectionCallback { public: - virtual ~ClientGattConnectionLifeCycleCallback() {} - // Called when the client is disconnected from the GATT server. - virtual void OnDisconnected(ClientGattConnection* connection) = 0; + std::function disconnected_cb = + DefaultCallback(); }; // Callback for asynchronous events on the server side of a GATT connection. -class ServerGattConnectionLifeCycleCallback { - public: - virtual ~ServerGattConnectionLifeCycleCallback() {} - +struct ServerGattConnectionCallback { // Called when a remote peripheral connected to us and subscribed to one of // our characteristics. - virtual void OnCharacteristicSubscription( - ServerGattConnection* connection, - const GattCharacteristic& characteristic) = 0; + std::function + characteristic_subscription_cb; // Called when a remote peripheral unsubscribed from one of our // characteristics. - virtual void OnCharacteristicUnsubscription( - ServerGattConnection* connection, - const GattCharacteristic& characteristic) = 0; + std::function + characteristic_unsubscription_cb; }; // https://developer.android.com/reference/android/bluetooth/BluetoothGattServer @@ -209,7 +222,7 @@ class ServerGattConnectionLifeCycleCallback { // 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. @@ -217,31 +230,29 @@ class GattServer { // 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: + // 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 absl::optional CreateCharacteristic( absl::string_view service_uuid, absl::string_view characteristic_uuid, - const std::set& permissions, - const std::set& properties) = 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. - // Takes ownership of (and is responsible for destroying) the passed-in - // 'value'. - virtual bool UpdateCharacteristic(const GattCharacteristic& characteristic, - const ByteArray& value) = 0; + // Locally updates the value of a characteristic and returns whether or not + // it was successful. + virtual bool UpdateCharacteristic( + const GattCharacteristic& characteristic, + const location::nearby::ByteArray& value) = 0; // Stops a GATT server. virtual void Stop() = 0; }; -// A BLE socket representation. class BleSocket { public: virtual ~BleSocket() {} @@ -256,12 +267,14 @@ class BleSocket { // Closes the socket and blocks until finished. Returns Exception::kIo upon // error, and Exception::kSuccess otherwise. virtual Exception Close() = 0; + virtual InputStream& GetInputStream() = 0; + virtual OutputStream& GetOutputStream() = 0; }; // Callback for asynchronous events on a BleSocket object. class BleSocketLifeCycleCallback { public: - virtual ~BleSocketLifeCycleCallback() {} + virtual ~BleSocketLifeCycleCallback() = default; // Called when a message arrives on a socket. virtual void OnMessageReceived(BleSocket* socket, @@ -280,21 +293,13 @@ class ServerBleSocketLifeCycleCallback : public BleSocketLifeCycleCallback { 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. +// 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() {} - - // Coarse representation of power settings throughout all BLE operations. - enum class PowerMode { - kUnknown = 0, - kLow = 1, - kHigh = 2, - kLast, - }; + 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) // @@ -302,42 +307,33 @@ class BleMedium { // // Power mode should be interpreted in the following way: // LOW: - // - Advertising interval = ~1000ms - // - TX power = low + // - TX power = medium // HIGH: - // - Advertising interval = ~100ms // - TX power = high - virtual bool StartAdvertising(const BleAdvertisementData& advertisement_data, - const BleAdvertisementData& scan_response, + 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 void StopAdvertising() = 0; + virtual bool StopAdvertising() = 0; // https://developer.android.com/reference/android/bluetooth/le/ScanCallback // // Callback for BLE scan results. - class ScanCallback { - public: - virtual ~ScanCallback() {} - - // https://developer.android.com/reference/android/bluetooth/le/ScanCallback.html#onScanResult(int,%20android.bluetooth.le.ScanResult) - // - // Called when a BLE advertisement is discovered. - // - // The passed in advertisement_data is the merged combination of both - // advertisement data and scan response. - // - // Every discovery of an advertisement should be reported, even if the - // advertisement was discovered before. - // - // Ownership of the BleAdvertisementData transfers to the caller at this - // point. - virtual void OnAdvertisementFound( - BlePeripheral* peripheral, - const BleAdvertisementData& advertisement_data) = 0; + // + // The passed in advertisement_data is the merged combination of both + // advertisement data and scan response. + // + // Every discovery of an advertisement should be reported, even if the + // advertisement was discovered before. + // + // Ownership of the BleAdvertisementData transfers to the caller at this + // point. + struct ScanCallback { + std::function + advertisement_found_cb = DefaultCallback(); }; // https://developer.android.com/reference/android/bluetooth/le/BluetoothLeScanner.html#startScan(java.util.List%3Candroid.bluetooth.le.ScanFilter%3E,%20android.bluetooth.le.ScanSettings,%20android.bluetooth.le.ScanCallback) @@ -351,20 +347,19 @@ class BleMedium { // HIGH: // - Scan window = ~4096ms // - Scan interval = ~4096ms - virtual bool StartScanning(const std::set& service_uuids, - PowerMode power_mode, - const ScanCallback& scan_callback) = 0; + virtual bool StartScanning(const std::vector& service_uuids, + PowerMode power_mode, ScanCallback callback) = 0; // https://developer.android.com/reference/android/bluetooth/le/BluetoothLeScanner.html#stopScan(android.bluetooth.le.ScanCallback) // // Stops scanning. - virtual void StopScanning() = 0; + virtual bool 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; // Starts listening for incoming BLE sockets and returns false upon error. virtual bool StartListeningForIncomingBleSockets( @@ -380,16 +375,17 @@ class BleMedium { // Connects to a GATT server and negotiates the specified connection // parameters. Returns nullptr upon error. // - // Both connection interval and MTU can be negotiated on a best-effort basis. + // Both connection interval and MTU can be negotiated on a best-effort + // basis. // // Power mode should be interpreted in the following way: - // LOW: - // - Connection interval = ~11.25ms - 15ms // HIGH: + // - Connection interval = ~11.25ms - 15ms + // LOW: // - Connection interval = ~100ms - 125ms virtual std::unique_ptr ConnectToGattServer( - BlePeripheral* peripheral, Mtu mtu, PowerMode power_mode, - const ClientGattConnectionLifeCycleCallback& callback) = 0; + BlePeripheral& peripheral, Mtu mtu, PowerMode power_mode, + ClientGattConnectionCallback callback) = 0; // Establishes a BLE socket to the specified remote peripheral. Returns // nullptr on error.