Merge branch 'google:main' into fpp-rust

This commit is contained in:
jbabs1
2023-05-03 15:12:37 -07:00
committed by GitHub
219 changed files with 4893 additions and 1914 deletions
+3 -2
View File
@@ -245,7 +245,7 @@ let package = Package(
.target(
name: "json",
path: "third_party/json",
exclude:[
exclude: [
"json/LICENSES",
"json/cmake",
"json/docs",
@@ -430,10 +430,11 @@ let package = Package(
"connections/implementation/mediums/BUILD",
"connections/implementation/BUILD",
"connections/implementation/fuzzers",
"connections/v3/BUILD",
"connections/BUILD",
"internal/BUILD",
"internal/crypto/BUILD",
"internal/crypto/BUILD.gn",
"internal/interop/BUILD",
"internal/weave/BUILD",
"internal/platform/flags/BUILD",
"internal/platform/implementation/shared/BUILD",
+3 -4
View File
@@ -30,8 +30,9 @@ cc_library(
deps = [
":core_types",
"//connections/implementation:internal",
"//internal:device",
"//connections/v3:v3_types",
"//internal/analytics:event_logger",
"//internal/interop:device",
"//internal/platform:base",
"//internal/platform:logging",
"//internal/platform:types",
@@ -54,7 +55,6 @@ cc_library(
hdrs = [
"advertising_options.h",
"connection_options.h",
"device_provider.h",
"discovery_options.h",
"listeners.h",
"medium_selector.h",
@@ -74,7 +74,6 @@ cc_library(
"//location/nearby/testing:__subpackages__",
],
deps = [
"//internal:device",
"//internal/platform:base",
"//internal/platform:types",
"//internal/platform:util",
@@ -99,7 +98,7 @@ cc_test(
":core",
":core_types",
"//connections/implementation:internal_test",
"//internal:device",
"//internal/interop:device",
"//internal/platform:base",
"//internal/platform:logging",
"//internal/platform:types",
+4 -3
View File
@@ -1,4 +1,4 @@
# Copyright 2020 Google LLC
# Copyright 2020-2023 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,6 +16,7 @@
load("//tools/build_defs/apple:ios.bzl", "ios_unit_test")
load("//tools/build_defs/swift:swift_library.bzl", "swift_library")
load("//third_party/nearby:minimum_os.bzl", "IOS_MINIMUM_OS", "IOS_MINIMUM_TEST_RUNNER")
licenses(["notice"])
@@ -71,8 +72,8 @@ swift_library(
ios_unit_test(
name = "BuildTests",
minimum_os_version = "13.0",
runner = "//testing/utp/ios:IOS_13",
minimum_os_version = IOS_MINIMUM_OS,
runner = IOS_MINIMUM_TEST_RUNNER,
deps = [
":BuildTestsLib",
],
+260 -22
View File
@@ -17,17 +17,22 @@
#include <functional>
#include <string>
#include <type_traits>
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
#include "connections/device_provider.h"
#include "connections/connection_options.h"
#include "connections/implementation/client_proxy.h"
#include "connections/implementation/service_controller.h"
#include "connections/implementation/service_controller_router.h"
#include "connections/listeners.h"
#include "connections/params.h"
#include "connections/payload.h"
#include "connections/v3/connection_listening_options.h"
#include "connections/v3/listeners.h"
#include "internal/analytics/event_logger.h"
#include "internal/device.h"
#include "internal/interop/device.h"
#include "internal/interop/device_provider.h"
namespace nearby {
namespace connections {
@@ -246,33 +251,266 @@ class Core {
std::string Dump();
//******************************* V2 *******************************
void RequestConnectionV2(const NearbyDevice& device,
const ConnectionRequestInfo& info,
ConnectionOptions& connection_options,
ResultCallback callback);
//******************************* V3 *******************************
// NOTE: Do NOT mix with the V1 APIs above, this might result in undefined
// behavior!
void AcceptConnectionV2(const NearbyDevice& device,
const PayloadListener& listener,
// Starts advertising an endpoint for a local app.
//
// service_id - An identifier to advertise your app to other endpoints.
// This can be an arbitrary string, so long as it uniquely
// identifies your service. A good default is to use your
// app's package name.
// advertising_options - The options for advertising.
// local_device - The local device for use when advertising when a
// `DeviceProvider` has not been registered.
// callback - to access the status of the operation when available.
// Possible status codes include:
// Status::STATUS_OK if advertising started successfully.
// Status::STATUS_ALREADY_ADVERTISING if the app is already advertising.
// Status::STATUS_OUT_OF_ORDER_API_CALL if the app is currently
// connected to remote endpoints; call StopAllEndpoints first.
void StartAdvertisingV3(absl::string_view service_id,
const AdvertisingOptions& advertising_options,
const NearbyDevice& local_device,
ResultCallback callback);
void RejectConnectionV2(const NearbyDevice& device, ResultCallback callback);
// Starts advertising an endpoint for a local app.
// Should only be used when DeviceProvider has been registered with this
// Nearby Connections instance. Otherwise, use the
// StartAdvertisingV3(service_id, advertising_options, local_device, callback)
// function above.
//
// service_id - An identifier to advertise your app to other endpoints.
// This can be an arbitrary string, so long as it uniquely
// identifies your service. A good default is to use your
// app's package name.
// advertising_options - The options for advertising.
// callback - to access the status of the operation when available.
// Possible status codes include:
// Status::STATUS_OK if advertising started successfully.
// Status::STATUS_ALREADY_ADVERTISING if the app is already advertising.
// Status::STATUS_OUT_OF_ORDER_API_CALL if the app is currently
// connected to remote endpoints; call StopAllEndpoints first.
void StartAdvertisingV3(absl::string_view service_id,
const AdvertisingOptions& advertising_options,
ResultCallback callback);
// Span is being used here as we will not be modifying this block of memory.
// We also do not need to own this block of memory, so we can use Span.
// We are using NearbyDevice* so as to not lose attributes when using a
// vector-like structure of NearbyDevice, as object information is stripped if
// using NearbyDevice or NearbyDevice&.
void SendPayloadV2(absl::Span<const NearbyDevice*> devices,
const Payload& payload, ResultCallback callback);
// Stops advertising a local endpoint. Should be called after calling
// StartAdvertising, as soon as the application no longer needs to advertise
// itself or goes inactive. Payloads can still be sent to connected
// endpoints after advertising ends.
//
// result_cb - to access the status of the operation when available.
void StopAdvertisingV3(ResultCallback result_cb);
void DisconnectFromDeviceV2(const NearbyDevice& device,
ResultCallback callback);
// Starts discovery for remote endpoints with the specified service ID.
//
// service_id - The ID for the service to be discovered, as specified in
// the corresponding call to StartAdvertising.
// discovery_options - The options for discovery.
// listener_cb - A callback notified when a remote endpoint is discovered.
// result_cb - to access the status of the operation when available.
// Possible status codes include:
// Status::STATUS_OK if discovery started successfully.
// Status::STATUS_ALREADY_DISCOVERING if the app is already
// discovering the specified service.
// Status::STATUS_OUT_OF_ORDER_API_CALL if the app is currently
// connected to remote endpoints; call StopAllEndpoints first.
void StartDiscoveryV3(absl::string_view service_id,
const DiscoveryOptions& discovery_options,
v3::DiscoveryListener listener_cb,
ResultCallback callback);
void InitiateBandwidthUpgradeV2(const NearbyDevice& device,
ResultCallback callback);
// Stops discovery for remote endpoints, after a previous call to
// StartDiscovery, when the client no longer needs to discover endpoints or
// goes inactive. Payloads can still be sent to connected endpoints after
// discovery ends.
//
// result_cb - to access the status of the operation when available.
void StopDiscoveryV3(ResultCallback result_cb);
void RegisterDeviceProvider(const NearbyDeviceProvider& provider);
// Starts listening for incoming connections.
//
// listener_cb - The connection listener to broadcast any updates.
// options - The options for listening for a connection.
// result_cb - to access the status of the operation when available.
// Possible status codes include:
// Status::STATUS_OK if listening started successfully.
// Status::STATUS_ALREADY_LISTENING if the app is already listening.
// Status::STATUS_ALREADY_ADVERTISING if the app is already advertising.
// Status::STATUS_OUT_OF_ORDER_API_CALL if the app is currently connected
// to remote endpoints; call StopAllEndpoints first.
void StartListeningForIncomingConnections(
const v3::ConnectionListeningOptions& options,
v3::ConnectionListener listener_cb, ResultCallback result_cb);
// Stops listening for incoming connections. Should be called after
// calling StartListeningForIncomingConnections.
void StopListeningForIncomingConnections();
// Sends a request to connect to a remote endpoint.
//
// local_device - The local device information which will be shown on the
// remote endpoint. Used only when a DeviceProvider is not
// registered.
// remote_device - The remote device to which a connection request will be
// sent. Should match the value provided in a call to
// DiscoveryListener::endpoint_found_cb()
// connection_options - Connection options for the new connection if both
// sides accept.
// connection_cb - The callback to be notified on connection events.
// result_cb - to access the status of the operation when available.
// Possible status codes include:
// Status::STATUS_OK if the connection request was sent.
// Status::STATUS_ALREADY_CONNECTED_TO_ENDPOINT if the app already
// has a connection to the specified endpoint.
// Status::STATUS_RADIO_ERROR if we failed to connect because of an
// issue with Bluetooth/WiFi.
// Status::STATUS_ERROR if we failed to connect for any other reason.
void RequestConnectionV3(const NearbyDevice& local_device,
const NearbyDevice& remote_device,
const ConnectionOptions& connection_options,
v3::ConnectionListener connection_cb,
ResultCallback result_cb);
// Sends a request to connect to a remote endpoint.
//
// remote_device - The remote device to which a connection request will be
// sent. Should match the value provided in a call to
// DiscoveryListener::endpoint_found_cb()
// connection_options - Connection options for the new connection if both
// sides accept.
// connection_cb - The callback to be notified on connection events.
// result_cb - to access the status of the operation when available.
// Possible status codes include:
// Status::STATUS_OK if the connection request was sent.
// Status::STATUS_ALREADY_CONNECTED_TO_ENDPOINT if the app already
// has a connection to the specified endpoint.
// Status::STATUS_RADIO_ERROR if we failed to connect because of an
// issue with Bluetooth/WiFi.
// Status::STATUS_ERROR if we failed to connect for any other reason.
void RequestConnectionV3(const NearbyDevice& remote_device,
const ConnectionOptions& connection_options,
v3::ConnectionListener connection_cb,
ResultCallback result_cb);
// Accepts a connection to a remote endpoint. This method must be called
// before Payloads can be exchanged with the remote endpoint.
//
// remote_device - The remote device. Should match the value provided in a
// call to ConnectionListener::OnConnectionInitiated.
//
// listener_cb - A callback for payloads exchanged with the remote endpoint.
//
// result_cb - to access the status of the operation when available.
// Possible status codes include:
// Status::STATUS_OK if the connection request was accepted.
// Status::STATUS_ALREADY_CONNECTED_TO_ENDPOINT if the app already.
// has a connection to the specified endpoint.
// Status::STATUS_ENDPOINT_UNKNOWN if the app doesn't currently have a
// pending connection to the remote device.
void AcceptConnectionV3(const NearbyDevice& remote_device,
v3::PayloadListener listener_cb,
ResultCallback result_cb);
// Rejects a connection to a remote endpoint.
//
// remote_device - The device for the remote endpoint. Should match the
// value provided in a call to
// v3::ConnectionListener::OnConnectionInitiated().
// result_cb - to access the status of the operation when available.
// Possible status codes include:
// Status::STATUS_OK} if the connection request was rejected.
// Status::STATUS_ALREADY_CONNECTED_TO_ENDPOINT} if the app already
// has a connection to the specified endpoint.
void RejectConnectionV3(const NearbyDevice& remote_device,
ResultCallback result_cb);
// Sends a Payload to a remote device. Payloads can only be sent to remote
// devices once a notice of connection acceptance has been delivered via
// v3::ConnectionListener::OnConnectionResult().
//
// remote_device - The remote device to which the payload should be sent.
// payload - The Payload to be sent.
// result_cb - to access the status of the operation when available.
// Possible status codes include:
// Status::STATUS_OUT_OF_ORDER_API_CALL if the device has not first
// performed advertisement or discovery (to set the Strategy.
// Status::STATUS_ENDPOINT_UNKNOWN if there's no active (or pending)
// connection to the remote endpoint.
// Status::STATUS_OK if none of the above errors occurred. Note that this
// indicates that Nearby Connections will attempt to send the Payload,
// but not that the send has successfully completed yet. Errors might
// still occur during transmission (and at different times for
// different endpoints), and will be delivered via
// PayloadCallback#onPayloadTransferUpdate.
void SendPayloadV3(const NearbyDevice& remote_device, const Payload& payload,
ResultCallback result_cb);
// Cancels a Payload currently in-flight to or from remote endpoint(s).
//
// remote_device - The remote device with which the payload is being
// exchanged.
// payload_id - The identifier for the Payload to be canceled.
// result_cb - to access the status of the operation when available.
// Possible status codes include:
// Status::STATUS_OK if none of the above errors occurred.
void CancelPayloadV3(const NearbyDevice& remote_device, int64_t payload_id,
ResultCallback result_cb);
// Disconnects from a remote endpoint. {@link Payload}s can no longer be sent
// to or received from the endpoint after this method is called.
//
// remote_device - The remote device to disconnect from.
// result_cb - to access the status of the operation when available.
// Possible status codes include:
// Status::STATUS_OK - finished successfully.
void DisconnectFromDeviceV3(const NearbyDevice& remote_device,
ResultCallback result_cb);
// Disconnects from, and removes all traces, of all connected and/or
// discovered endpoints. This call is expected to be preceded by a call to
// StopAdvertising() or StopDiscovery() as needed. After calling
// StopAllDevices(), no further operations with remote endpoints will be
// possible until a new call to one of StartAdvertising() or StartDiscovery().
//
// result_cb - To access the status of the operation when available.
void StopAllDevicesV3(ResultCallback result_cb);
// Sends a request to initiate connection bandwidth upgrade.
//
// remote_device - The identifier for the remote device which will be
// switching to a higher connection data rate and possibly
// different wireless protocol. On success, calls
// ConnectionListener::bandwidth_changed_cb().
// result_cb - to access the status of the operation when available.
// Possible status codes include:
// Status::STATUS_OK - finished successfully.
void InitiateBandwidthUpgradeV3(const NearbyDevice& remote_device,
ResultCallback result_cb);
// Updates AdvertisingOptions. It compares the old AdvertisingOptions and the
// new AdvertisingOptions to start/stop each advertising medium.
//
// advertising_options - The new advertising options a client wishes to use.
// result_cb - to access the status of the operation when available.
void UpdateAdvertisingOptionsV3(const AdvertisingOptions& advertising_options,
ResultCallback result_cb);
// Updates DiscoveryOptions. It compares the old DiscoveryOptions and the new
// DiscoveryOptions to start/stop each discovery medium.
//
// discovery_options - The new discovery options a client wishes to use.
// result_cb - to access the status of the operation when available.
void UpdateDiscoveryOptionsV3(const DiscoveryOptions& discovery_options,
ResultCallback result_cb);
// Registers a DeviceProvider to provide functionality for Nearby Connections
// to interact with the DeviceProvider for retrieving the local device.
template <typename T, typename std::enable_if<std::is_base_of<
NearbyDevice, T>::value>::type* = nullptr>
void RegisterDeviceProvider(NearbyDeviceProvider<T>* provider);
private:
ClientProxy client_;
+1 -1
View File
@@ -137,9 +137,9 @@ cc_library(
"//connections/implementation/mediums:utils",
"//connections/implementation/mediums/webrtc",
"//connections/implementation/proto:offline_wire_formats_cc_proto",
"//internal:device",
"//internal/analytics:event_logger",
"//internal/flags:nearby_flags",
"//internal/interop:device",
"//internal/platform:base",
"//internal/platform:cancellation_flag",
"//internal/platform:comm",
+1 -48
View File
@@ -30,7 +30,7 @@
#include "connections/status.h"
#include "connections/strategy.h"
#include "internal/analytics/event_logger.h"
#include "internal/device.h"
#include "internal/interop/device.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/cancelable_alarm.h"
#include "internal/platform/cancellation_flag.h"
@@ -199,53 +199,6 @@ class ClientProxy final {
std::string Dump();
//********************************** V2 **********************************
void OnDeviceFound(const absl::string_view service_id,
const NearbyDevice& device,
location::nearby::proto::connections::Medium medium);
// Proxies to the client's DiscoveryListener::OnEndpointLost() callback.
void OnEndpointLost(absl::string_view service_id, const NearbyDevice& device);
// Proxies to the client's ConnectionListener::OnInitiated() callback.
void OnConnectionInitiated(const NearbyDevice& device,
const ConnectionResponseInfo& info,
const ConnectionOptions& connection_options,
const ConnectionListener& listener,
absl::string_view connection_token);
void OnConnectionAccepted(const NearbyDevice& device);
void OnConnectionRejected(const NearbyDevice& device, const Status& status);
void OnBandwidthChanged(const NearbyDevice& device, Medium new_medium);
// If notify is true, also calls the client's
// ConnectionListener.disconnected_cb() callback.
void OnDisconnected(const NearbyDevice& device, bool notify);
BooleanMediumSelector GetUpgradableMediums(const NearbyDevice& device) const;
bool IsConnectedToEndpoint(const NearbyDevice& device) const;
// No payloads should be sent until isConnectedToEndpoint()
// returns true.
bool HasPendingConnectionToEndpoint(const NearbyDevice& device) const;
bool HasLocalEndpointResponded(const NearbyDevice& device) const;
bool HasRemoteEndpointResponded(const NearbyDevice& device) const;
void LocalEndpointAcceptedConnection(const NearbyDevice& device,
const PayloadListener& listener);
void LocalEndpointRejectedConnection(const NearbyDevice& device);
void RemoteEndpointAcceptedConnection(const NearbyDevice& device);
void RemoteEndpointRejectedConnection(const NearbyDevice& device);
bool IsConnectionAccepted(const NearbyDevice& device) const;
bool IsConnectionRejected(const NearbyDevice& device) const;
void OnPayload(const NearbyDevice& device, Payload payload);
void OnPayloadProgress(const NearbyDevice& device,
const PayloadProgressInfo& info);
bool LocalConnectionIsAccepted(const NearbyDevice& device) const;
bool RemoteConnectionIsAccepted(const NearbyDevice& device) const;
void AddCancellationFlag(const NearbyDevice& device);
CancellationFlag* GetCancellationFlag(const NearbyDevice& device);
void CancelEndpoint(const NearbyDevice& device);
const location::nearby::connections::OsInfo& GetLocalOsInfo() const;
std::optional<location::nearby::connections::OsInfo> GetRemoteOsInfo(
absl::string_view endpoint_id) const;
@@ -27,10 +27,18 @@ constexpr absl::string_view kConfigPackage = "nearby";
// The Nearby Connections features.
namespace nearby_connections_feature {
// LINT.IfChanged
// Disable/Enable BLE v2 in Nearby Connections SDK.
constexpr auto kEnableBleV2 =
flags::Flag<bool>(kConfigPackage, "45401515", false);
// LINT.ThenChange(
// //depot/google3/location/nearby/cpp/sharing/clients/windows/nearby_sharing_service_adapter_dart.h,
// //depot/google3/location/nearby/cpp/sharing/clients/windows/nearby_sharing_service_adapter_dart.cc,
// //depot/google3/location/nearby/cpp/sharing/clients/dart/platform/lib/ffi_types.dart,
// //depot/google3/location/nearby/cpp/sharing/clients/dart/platform/lib/types/models.dart
// )
} // namespace nearby_connections_feature
} // namespace config_package_nearby
} // namespace connections
@@ -268,11 +268,12 @@ TEST_P(P2pClusterPcpHandlerTest, CanConnect) {
const std::string kBssid = "34:36:3B:C7:8C:71";
const std::int32_t kFreq = 5200;
constexpr char kIp4Bytes[] = {(char)192, (char)168, (char)1, (char)37};
constexpr char kIp4Bytes[] = {(char)192, (char)168, (char)1, (char)37, 0};
connection_options_.connection_info.supports_5_ghz = true;
connection_options_.connection_info.bssid = kBssid;
connection_options_.connection_info.ap_frequency = kFreq;
connection_options_.connection_info.ip_address.resize(4);
connection_options_.connection_info.ip_address = std::string(kIp4Bytes);
client_b_.AddCancellationFlag(discovered.endpoint_id);
@@ -207,11 +207,12 @@ TEST_P(P2pPointToPointPcpHandlerTest, CanConnect) {
const std::string kBssid = "34:36:3B:C7:8C:71";
const std::int32_t kFreq = 5200;
constexpr char kIp4Bytes[] = {(char)192, (char)168, (char)1, (char)37};
constexpr char kIp4Bytes[] = {(char)192, (char)168, (char)1, (char)37, 0};
connection_options_.connection_info.supports_5_ghz = true;
connection_options_.connection_info.bssid = kBssid;
connection_options_.connection_info.ap_frequency = kFreq;
connection_options_.connection_info.ip_address.resize(4);
connection_options_.connection_info.ip_address = std::string(kIp4Bytes);
client_b_.AddCancellationFlag(discovered.endpoint_id);
@@ -43,6 +43,8 @@ message V1Frame {
KEEP_ALIVE = 5;
DISCONNECTION = 6;
PAIRED_KEY_ENCRYPTION = 7;
AUTHENTICATION_MESSAGE = 8;
AUTHENTICATION_RESULT = 9;
}
optional FrameType type = 1;
@@ -54,6 +56,8 @@ message V1Frame {
optional KeepAliveFrame keep_alive = 6;
optional DisconnectionFrame disconnection = 7;
optional PairedKeyEncryptionFrame paired_key_encryption = 8;
optional AuthenticationMessageFrame authentication_message = 9;
optional AuthenticationResultFrame authentication_result = 10;
}
message ConnectionRequestFrame {
@@ -251,6 +255,10 @@ message BandwidthUpgradeNegotiationFrame {
optional int32 port = 3;
optional int32 frequency = 4;
optional string gateway = 5 [default = "0.0.0.0"];
// IPv6 link-local address, network order (128bits).
// The GO should listen on both IPv4 and IPv6 addresses.
// https://en.wikipedia.org/wiki/Link-local_address#IPv6
optional bytes ip_v6_address = 6;
}
// Accompanies Medium.WEB_RTC
@@ -318,6 +326,21 @@ message PairedKeyEncryptionFrame {
optional bytes signed_data = 1;
}
// Nearby Connections authentication frame, contains the bytes format of a
// DeviceProvider's authentication message.
message AuthenticationMessageFrame {
// An auth message generated by DeviceProvider.
// To be sent to the remote device for verification during connection setups.
optional bytes auth_message = 1;
}
// Nearby Connections authentication result frame.
message AuthenticationResultFrame {
// The authentication result. Non null if this frame is used to exchange
// authentication result.
optional int32 result = 1;
}
message MediumMetadata {
// True if local device supports 5GHz.
optional bool supports_5_ghz = 1;
+4 -3
View File
@@ -1,4 +1,4 @@
# Copyright 2022 Google LLC
# Copyright 2022-2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -14,6 +14,7 @@
load("//tools/build_defs/apple:ios.bzl", "ios_unit_test")
load("//tools/build_defs/swift:swift_library.bzl", "swift_library")
load("//third_party/nearby:minimum_os.bzl", "IOS_MINIMUM_OS", "IOS_MINIMUM_TEST_RUNNER")
licenses(["notice"])
@@ -41,8 +42,8 @@ swift_library(
ios_unit_test(
name = "Tests",
minimum_os_version = "13.0",
runner = "//testing/utp/ios:IOS_13",
minimum_os_version = IOS_MINIMUM_OS,
runner = IOS_MINIMUM_TEST_RUNNER,
deps = [
":TestsLib",
],
@@ -31,6 +31,7 @@
23252B5729D739E400BB0370 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
23252B5929D739E500BB0370 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
23252B5C29D739E500BB0370 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
236C727829F83A1F00E54333 /* iOS-Example-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "iOS-Example-Info.plist"; sourceTree = SOURCE_ROOT; };
23D1FD2329D8A73200620802 /* Config.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Config.swift; sourceTree = "<group>"; };
23D1FD2529D8A9FF00620802 /* DiscoveredEndpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscoveredEndpoint.swift; sourceTree = "<group>"; };
23D1FD2729D8AA2200620802 /* ConnectionRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectionRequest.swift; sourceTree = "<group>"; };
@@ -78,6 +79,7 @@
23252B5429D739E400BB0370 /* iOS Example */ = {
isa = PBXGroup;
children = (
236C727829F83A1F00E54333 /* iOS-Example-Info.plist */,
23F6A71429D7B0AB00558F56 /* Model */,
23252B5529D739E400BB0370 /* HelloConnectionsApp.swift */,
23252B5729D739E400BB0370 /* ContentView.swift */,
@@ -345,6 +347,9 @@
DEVELOPMENT_TEAM = "";
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "iOS-Example-Info.plist";
INFOPLIST_KEY_NSBluetoothAlwaysUsageDescription = "This app demonstrates Nearby Connections. Supply a value for this string to explain how the user benefits when they allow the app to use Bluetooth.";
INFOPLIST_KEY_NSLocalNetworkUsageDescription = "This app demonstrates Nearby Connections. Supply a value for this string to explain how the user benefits when they allow the app to use Local Network.";
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
@@ -374,6 +379,9 @@
DEVELOPMENT_TEAM = "";
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "iOS-Example-Info.plist";
INFOPLIST_KEY_NSBluetoothAlwaysUsageDescription = "This app demonstrates Nearby Connections. Supply a value for this string to explain how the user benefits when they allow the app to use Bluetooth.";
INFOPLIST_KEY_NSLocalNetworkUsageDescription = "This app demonstrates Nearby Connections. Supply a value for this string to explain how the user benefits when they allow the app to use Local Network.";
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSBonjourServices</key>
<array>
<string>_307BEAB11028._tcp</string>
</array>
</dict>
</plist>
+4 -3
View File
@@ -1,4 +1,4 @@
# Copyright 2022 Google LLC
# Copyright 2022-2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -14,6 +14,7 @@
load("//tools/build_defs/apple:ios.bzl", "ios_unit_test")
load("//tools/build_defs/swift:swift_library.bzl", "swift_library")
load("//third_party/nearby:minimum_os.bzl", "IOS_MINIMUM_OS", "IOS_MINIMUM_TEST_RUNNER")
licenses(["notice"])
@@ -52,8 +53,8 @@ swift_library(
ios_unit_test(
name = "Tests",
minimum_os_version = "13.0",
runner = "//testing/utp/ios:IOS_13",
minimum_os_version = IOS_MINIMUM_OS,
runner = IOS_MINIMUM_TEST_RUNNER,
deps = [
":TestsLib",
],
+18
View File
@@ -0,0 +1,18 @@
cc_library(
name = "v3_types",
hdrs = [
"bandwidth_info.h",
"connection_listening_options.h",
"connection_resolution.h",
"listeners.h",
],
visibility = [
"//connections:__subpackages__",
],
deps = [
"//connections:core_types",
"//internal/interop:device",
"//proto:connections_enums_cc_proto",
"@com_google_absl//absl/functional:any_invocable",
],
)
+54
View File
@@ -0,0 +1,54 @@
// Copyright 2023 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 THIRD_PARTY_NEARBY_CONNECTIONS_V3_BANDWIDTH_INFO_H_
#define THIRD_PARTY_NEARBY_CONNECTIONS_V3_BANDWIDTH_INFO_H_
#include "proto/connections_enums.pb.h"
namespace nearby {
namespace connections {
namespace v3 {
// Represents the connection quality.
enum class Quality {
// Unknown connection quality. Recommended to wait for one of kMedium or
// kHigh.
kUnknown = 0,
// The connection quality is poor (5KBps) and is not suitable for
// sending files. It's recommended you wait until the connection
// quality improves.
kLow = 1,
// The connection quality is ok (60~200KBps) and is suitable for
// sending small files. For large files, it's recommended you wait
// until the connection quality improves.
kMedium = 2,
// The connection quality is good or great (1MBps~60MBps) and files
// can readily be sent. The connection quality cannot improve further
// but may still be impacted by environment or hardware limitations.
kHigh = 3,
};
// Used to indicate the new connection quality when upgrading to a new medium
// e.g. BT -> WiFi direct.
struct BandwidthInfo {
Quality quality;
::location::nearby::proto::connections::Medium medium;
};
} // namespace v3
} // namespace connections
} // namespace nearby
#endif // THIRD_PARTY_NEARBY_CONNECTIONS_V3_BANDWIDTH_INFO_H_
@@ -0,0 +1,47 @@
// Copyright 2023 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 THIRD_PARTY_NEARBY_CONNECTIONS_V3_CONNECTION_LISTENING_OPTIONS_H_
#define THIRD_PARTY_NEARBY_CONNECTIONS_V3_CONNECTION_LISTENING_OPTIONS_H_
#include <vector>
#include "connections/strategy.h"
#include "internal/interop/device.h"
#include "proto/connections_enums.pb.h"
namespace nearby {
namespace connections {
namespace v3 {
struct ConnectionListeningOptions {
Strategy strategy;
bool allow_bluetooth_radio_toggling = true;
bool allow_wifi_radio_toggling = true;
bool enable_ble_listening = false;
bool enable_bluetooth_listening = true;
bool enable_wlan_listening = true;
bool auto_upgrade_bandwidth = true;
bool enforce_topology_constraints = true;
std::vector<location::nearby::proto::connections::Medium> upgrade_mediums;
std::vector<::location::nearby::proto::connections::Medium> listening_mediums;
nearby::NearbyDevice::Type listening_endpoint_type =
NearbyDevice::Type::kConnectionsDevice;
};
} // namespace v3
} // namespace connections
} // namespace nearby
#endif // THIRD_PARTY_NEARBY_CONNECTIONS_V3_CONNECTION_LISTENING_OPTIONS_H_
+32
View File
@@ -0,0 +1,32 @@
// Copyright 2023 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 THIRD_PARTY_NEARBY_CONNECTIONS_V3_CONNECTION_RESOLUTION_H_
#define THIRD_PARTY_NEARBY_CONNECTIONS_V3_CONNECTION_RESOLUTION_H_
#include "connections/status.h"
namespace nearby {
namespace connections {
namespace v3 {
struct ConnectionResult {
nearby::connections::Status status;
};
} // namespace v3
} // namespace connections
} // namespace nearby
#endif // THIRD_PARTY_NEARBY_CONNECTIONS_V3_CONNECTION_RESOLUTION_H_
+133
View File
@@ -0,0 +1,133 @@
// Copyright 2023 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 THIRD_PARTY_NEARBY_CONNECTIONS_V3_LISTENERS_H_
#define THIRD_PARTY_NEARBY_CONNECTIONS_V3_LISTENERS_H_
#include "absl/functional/any_invocable.h"
#include "connections/listeners.h"
#include "connections/v3/bandwidth_info.h"
#include "connections/v3/connection_resolution.h"
#include "internal/interop/device.h"
namespace nearby {
namespace connections {
namespace v3 {
struct ConnectionListener {
// A basic encrypted channel has been created between you and the endpoint.
// Both sides are now asked if they wish to accept or reject the connection
// before any data can be sent over this channel.
//
// This is your chance, before you accept the connection, to confirm that you
// connected to the correct device. Both devices are given an identical token;
// it's up to you to decide how to verify it before proceeding. Typically this
// involves showing the token on both devices and having the users manually
// compare and confirm; however, this is only required if you desire a secure
// connection between the devices.
//
// Whichever route you decide to take (including not authenticating the other
// device), call Core::AcceptConnection() when you're ready to talk, or
// Core::RejectConnection() to close the connection.
//
// remote_device - The identifier for the remote endpoint.
// info - Other relevant information about the connection.
absl::AnyInvocable<void(const NearbyDevice& remote_device,
const ConnectionResponseInfo& info)>
initiated_cb = [](const NearbyDevice&, const ConnectionResponseInfo&) {};
// Called when both sides have accepted or either side has rejected the
// connection. If the {@link ConnectionResolution}'s status is {@link
// ConnectionsStatusCodes#SUCCESS}, both sides have accepted the
// connection and may now send {@link Payload}s to each other.
// Otherwise, the connection was rejected.
// remote_device - The identifier for the remote endpoint.
// resolution - The resolution of the connection (accepted or rejected).
absl::AnyInvocable<void(const NearbyDevice& remote_device,
ConnectionResult resolution)>
result_cb = [](const NearbyDevice&, ConnectionResult) {};
// Called when a remote endpoint is disconnected or has become unreachable.
// At this point service (re-)discovery may start again.
//
// remote_device - The identifier for the remote endpoint.
absl::AnyInvocable<void(const NearbyDevice& remote_device)> disconnected_cb =
[](const NearbyDevice&) {};
// Called when the connection's available bandwidth has changed.
//
// remote_device - The identifier for the remote endpoint.
// bandwidth_info - Bandwidth info about the new medium that was upgraded to.
absl::AnyInvocable<void(const NearbyDevice& remote_device,
BandwidthInfo bandwidth_info)>
bandwidth_changed_cb = [](const NearbyDevice&, BandwidthInfo) {};
};
struct DiscoveryListener {
// Called when a remote endpoint is discovered.
//
// remote_device - The remote device that was discovered.
// service_id - The ID of the service advertised by the remote endpoint.
absl::AnyInvocable<void(const NearbyDevice& remote_device,
const absl::string_view service_id)>
endpoint_found_cb = [](const NearbyDevice&, const absl::string_view) {};
// Called when a remote endpoint is no longer discoverable; only called for
// endpoints that previously had been passed to {@link
// #onEndpointFound(String, DiscoveredEndpointInfo)}.
//
// remote_device - The ID of the remote endpoint that was lost.
absl::AnyInvocable<void(const NearbyDevice& remote_device)> endpoint_lost_cb =
[](const NearbyDevice&) {};
// Called when a remote endpoint is found with an updated distance.
//
// arguments:
// remote_device - The ID of the remote endpoint that was lost.
// info - The distance info, encoded as enum value.
absl::AnyInvocable<void(const NearbyDevice& remote_device, DistanceInfo info)>
endpoint_distance_changed_cb = [](const NearbyDevice&, DistanceInfo) {};
};
struct PayloadListener {
// Called when a Payload is received from a remote endpoint. Depending
// on the type of the Payload, all of the data may or may not have been
// received at the time of this call. Use OnPayloadProgress() to
// get updates on the status of the data received.
//
// remote_device - The identifier for the remote endpoint that sent the
// payload.
// payload - The Payload object received.
absl::AnyInvocable<void(const NearbyDevice& remote_device, Payload payload)>
payload_received_cb = [](const NearbyDevice&, Payload) {};
// Called with progress information about an active Payload transfer, either
// incoming or outgoing.
//
// remote_device - The identifier for the remote endpoint that is sending or
// receiving this payload.
// info - The PayloadProgressInfo structure describing the status of
// the transfer.
absl::AnyInvocable<void(const NearbyDevice& remote_device,
const PayloadProgressInfo& info)>
payload_progress_cb =
[](const NearbyDevice&, const PayloadProgressInfo&) {};
};
} // namespace v3
} // namespace connections
} // namespace nearby
#endif // THIRD_PARTY_NEARBY_CONNECTIONS_V3_LISTENERS_H_
+14
View File
@@ -39,3 +39,17 @@ cc_test(
"@com_google_googletest//:gtest_main",
],
)
cc_test(
name = "pair_failure_test",
size = "small",
srcs = [
"pair_failure_test.cc",
],
shard_count = 16,
deps = [
":common",
"@com_github_protobuf_matchers//protobuf-matchers",
"@com_google_googletest//:gtest_main",
],
)
+9
View File
@@ -90,6 +90,15 @@ std::ostream& operator<<(std::ostream& stream, PairFailure failure) {
stream
<< "[Potential pairing device lost between GATT connection attempts]";
break;
case PairFailure::kDeviceLostMidPairing:
stream << "[Potential pairing device lost during pairing.]";
break;
case PairFailure::kPairingAndConnect:
stream << "[Failed to pair with discovered device.]";
break;
case PairFailure::kPairingTimeout:
stream << "[Potential pairing failed with timeout.]";
break;
}
return stream;
+7 -1
View File
@@ -68,7 +68,13 @@ enum class PairFailure {
kPasskeyMismatch = 19,
// Potential pairing device lost between GATT connection attempts.
kPairingDeviceLostBetweenGattConnectionAttempts = 20,
kMaxValue = kPairingDeviceLostBetweenGattConnectionAttempts,
// Potential pairing device lost during pairing.
kDeviceLostMidPairing = 21,
// Failed to pair and connect with discovered device.
kPairingAndConnect = 22,
// Potential pairing timeout.
kPairingTimeout = 23,
kMaxValue = kPairingTimeout,
};
std::ostream& operator<<(std::ostream& stream, PairFailure failure);
+68
View File
@@ -0,0 +1,68 @@
// Copyright 2023 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 "fastpair/common/pair_failure.h"
#include "gtest/gtest.h"
namespace nearby {
namespace fastpair {
namespace {
TEST(PairFailureTest, PairFailureValue) {
EXPECT_EQ(static_cast<int>(PairFailure::kCreateGattConnection), 0);
EXPECT_EQ(static_cast<int>(PairFailure::kGattServiceDiscovery), 1);
EXPECT_EQ(static_cast<int>(PairFailure::kGattServiceDiscoveryTimeout), 2);
EXPECT_EQ(static_cast<int>(PairFailure::kDataEncryptorRetrieval), 3);
EXPECT_EQ(
static_cast<int>(PairFailure::kKeyBasedPairingCharacteristicDiscovery),
4);
EXPECT_EQ(static_cast<int>(PairFailure::kPasskeyCharacteristicDiscovery), 5);
EXPECT_EQ(static_cast<int>(PairFailure::kAccountKeyCharacteristicDiscovery),
6);
EXPECT_EQ(
static_cast<int>(PairFailure::kKeyBasedPairingCharacteristicSubscription),
7);
EXPECT_EQ(static_cast<int>(PairFailure::kPasskeyCharacteristicSubscription),
8);
EXPECT_EQ(static_cast<int>(
PairFailure::kKeyBasedPairingCharacteristicSubscriptionTimeout),
9);
EXPECT_EQ(
static_cast<int>(PairFailure::kPasskeyCharacteristicSubscriptionTimeout),
10);
EXPECT_EQ(static_cast<int>(PairFailure::kKeyBasedPairingCharacteristicWrite),
11);
EXPECT_EQ(static_cast<int>(PairFailure::kPasskeyPairingCharacteristicWrite),
12);
EXPECT_EQ(static_cast<int>(PairFailure::kKeyBasedPairingResponseTimeout), 13);
EXPECT_EQ(static_cast<int>(PairFailure::kPasskeyResponseTimeout), 14);
EXPECT_EQ(
static_cast<int>(PairFailure::kKeybasedPairingResponseDecryptFailure),
15);
EXPECT_EQ(
static_cast<int>(PairFailure::kIncorrectKeyBasedPairingResponseType), 16);
EXPECT_EQ(static_cast<int>(PairFailure::kPasskeyDecryptFailure), 17);
EXPECT_EQ(static_cast<int>(PairFailure::kIncorrectPasskeyResponseType), 18);
EXPECT_EQ(static_cast<int>(PairFailure::kPasskeyMismatch), 19);
EXPECT_EQ(static_cast<int>(
PairFailure::kPairingDeviceLostBetweenGattConnectionAttempts),
20);
EXPECT_EQ(static_cast<int>(PairFailure::kDeviceLostMidPairing), 21);
EXPECT_EQ(static_cast<int>(PairFailure::kPairingAndConnect), 22);
EXPECT_EQ(static_cast<int>(PairFailure::kPairingTimeout), 23);
}
} // namespace
} // namespace fastpair
} // namespace nearby
+2 -1
View File
@@ -30,7 +30,8 @@ FastPairWrapperImpl::FastPairWrapperImpl() {
FastPairWrapperImpl::~FastPairWrapperImpl() = default;
void FastPairWrapperImpl::StartScan() {
scanner_broker_ = std::make_unique<ScannerBrokerImpl>();
Mediums mediums;
scanner_broker_ = std::make_unique<ScannerBrokerImpl>(mediums);
if (is_scanning_) {
NEARBY_LOGS(VERBOSE) << __func__ << ": We're currently scanning. ";
return;
+1 -3
View File
@@ -16,8 +16,6 @@
#include <memory>
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
#include "internal/platform/medium_environment.h"
@@ -42,7 +40,7 @@ TEST_F(FastPairWrapperImplTest, StartScanningSuccess) {
EXPECT_FALSE(wrapper_->IsPairing());
EXPECT_FALSE(wrapper_->IsServerAccessing());
wrapper_->StartScan();
SystemClock::Sleep(absl::Milliseconds(200));
SystemClock::Sleep(absl::Milliseconds(2000));
EXPECT_TRUE(wrapper_->IsScanning());
env_.Stop();
}
+2
View File
@@ -27,6 +27,7 @@ lexan.cc_windows_dll(
"-Ithird_party",
],
defines = [
"LOG_SEVERITY_VERBOSE",
"_WIN32_WINNT=_WIN32_WINNT_WIN10",
],
tags = ["windows-dll"],
@@ -57,6 +58,7 @@ lexan.cc_windows_dll(
"-Ithird_party",
],
defines = [
"LOG_SEVERITY_VERBOSE",
"_WIN32_WINNT=_WIN32_WINNT_WIN10",
],
tags = ["windows-dll"],
@@ -24,6 +24,11 @@ namespace windows {
static FastPairWrapper *pWrapper_ = nullptr;
void *InitFastPairWrapper() {
#if defined(NEARBY_LOG_SEVERITY)
// Direct override of logging level.
NEARBY_LOG_SET_SEVERITY(NEARBY_LOG_SEVERITY);
#endif // LOG_SEVERITY_VERBOSE;
FastPairWrapperImpl *pWrapper = new FastPairWrapperImpl();
pWrapper_ = pWrapper;
return pWrapper;
@@ -36,7 +41,7 @@ void CloseFastPairWrapper(FastPairWrapper *pWrapper) {
}
void __stdcall StartScan(FastPairWrapper *pWrapper) {
NEARBY_LOGS(INFO) << "StartScan is called";
NEARBY_LOGS(VERBOSE) << "StartScan is called";
if (pWrapper_ == nullptr) {
NEARBY_LOGS(INFO) << "The pWrapper is a null pointer.";
return;
+30 -3
View File
@@ -20,6 +20,7 @@ cc_library(
"fast_pair_data_encryptor_impl.cc",
"fast_pair_gatt_service_client_impl.cc",
"fast_pair_handshake_impl.cc",
"fast_pair_handshake_lookup.cc",
],
hdrs = [
"fast_pair_data_encryptor.h",
@@ -28,6 +29,7 @@ cc_library(
"fast_pair_gatt_service_client_impl.h",
"fast_pair_handshake.h",
"fast_pair_handshake_impl.h",
"fast_pair_handshake_lookup.h",
],
visibility = [
"//:__subpackages__",
@@ -37,19 +39,22 @@ cc_library(
"//fastpair/common",
"//fastpair/crypto",
"//fastpair/dataparser",
"//fastpair/internal/ble",
"//fastpair/internal/mediums",
"//fastpair/repository",
"//fastpair/server_access",
"//internal/base:bluetooth_address",
"//internal/platform:base",
"//internal/platform:comm",
"//internal/platform:logging",
"//internal/platform:types",
"//internal/platform:uuid",
"@boringssl//:crypto",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/functional:any_invocable",
"@com_google_absl//absl/functional:bind_front",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/synchronization",
"@com_google_absl//absl/time",
"@com_google_absl//absl/types:span",
],
)
@@ -82,7 +87,7 @@ cc_test(
"//fastpair/common",
"//fastpair/crypto",
"//fastpair/dataparser",
"//fastpair/internal/ble",
"//fastpair/internal/mediums",
"//fastpair/server_access:test_support",
"//fastpair/testing",
"//internal/platform:logging",
@@ -107,6 +112,7 @@ cc_test(
":handshake",
":test_support",
"//fastpair/common",
"//fastpair/internal/mediums",
"//fastpair/testing",
"//internal/platform:base",
"//internal/platform:comm",
@@ -116,6 +122,7 @@ cc_test(
"//internal/platform/implementation/g3", # build_cleaner: keep
"//internal/test",
"@com_github_protobuf_matchers//protobuf-matchers",
"@com_google_absl//absl/status",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/time",
"@com_google_googletest//:gtest_main",
@@ -142,3 +149,23 @@ cc_test(
"@com_google_googletest//:gtest_main",
],
)
cc_test(
name = "fast_pair_handshake_lookup_test",
size = "small",
srcs = [
"fast_pair_handshake_lookup_test.cc",
],
shard_count = 16,
deps = [
":handshake",
"//fastpair/common",
"//fastpair/internal/mediums",
"//internal/platform:test_util",
"//internal/platform:types",
"//internal/platform/implementation/g3", # build_cleaner: keep
"@com_github_protobuf_matchers//protobuf-matchers",
"@com_google_absl//absl/strings",
"@com_google_googletest//:gtest_main",
],
)
@@ -43,26 +43,28 @@ class FakeFastPairGattServiceClient : public FastPairGattServiceClient {
WriteResponseCallback write_response_callback) override {
key_based_write_response_callback_ = std::move(write_response_callback);
}
void WritePasskeyAsync(
uint8_t message_type, uint32_t passkey,
const FastPairDataEncryptor& fast_pair_data_encryptor,
WriteResponseCallback write_response_callback) override {
passkey_write_response_callback_ = std::move(write_response_callback);
}
void RunOnGattClientInitializedCallback(
std::optional<PairFailure> failure = absl::nullopt) {
std::optional<PairFailure> failure = std::nullopt) {
std::move(on_initialized_callback_)(failure);
}
void RunWriteResponseCallback(
absl::string_view value,
std::optional<PairFailure> failure = absl::nullopt) {
std::optional<PairFailure> failure = std::nullopt) {
std::move(key_based_write_response_callback_)(value, failure);
}
void RunWritePasskeyCallback(
absl::string_view value,
std::optional<PairFailure> failure = absl::nullopt) {
std::optional<PairFailure> failure = std::nullopt) {
std::move(passkey_write_response_callback_)(value, failure);
}
@@ -88,7 +88,8 @@ void FastPairDataEncryptorImpl::Factory::CreateAsyncWithKeyExchange(
NEARBY_LOGS(INFO) << __func__ << ": Attempting to get device metadata.";
FastPairRepository::Get()->GetDeviceMetadata(
device.GetModelId(),
[&on_get_instance_callback](DeviceMetadata& metadata) {
[on_get_instance_callback = std::move(on_get_instance_callback)](
DeviceMetadata& metadata) mutable {
FastPairDataEncryptorImpl::Factory::DeviceMetadataRetrieved(
std::move(on_get_instance_callback), metadata);
});
@@ -16,6 +16,7 @@
#include <algorithm>
#include <array>
#include <cstdint>
#include <iterator>
#include <memory>
#include <optional>
@@ -27,11 +28,15 @@
#include "absl/functional/any_invocable.h"
#include "absl/functional/bind_front.h"
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "absl/types/span.h"
#include "fastpair/common/constant.h"
#include "fastpair/common/fast_pair_device.h"
#include "fastpair/common/pair_failure.h"
#include "fastpair/handshake/fast_pair_data_encryptor.h"
#include "fastpair/handshake/fast_pair_gatt_service_client.h"
#include "fastpair/internal/mediums/mediums.h"
#include "internal/base/bluetooth_address.h"
#include "internal/platform/ble_v2.h"
#include "internal/platform/logging.h"
#include "internal/platform/uuid.h"
#include <openssl/rand.h>
@@ -63,12 +68,13 @@ FastPairGattServiceClientImpl::Factory*
// static
std::unique_ptr<FastPairGattServiceClient>
FastPairGattServiceClientImpl::Factory::Create(const FastPairDevice& device) {
FastPairGattServiceClientImpl::Factory::Create(const FastPairDevice& device,
Mediums& mediums) {
if (g_test_factory_) {
return g_test_factory_->CreateInstance();
}
return std::make_unique<FastPairGattServiceClientImpl>(device);
return std::make_unique<FastPairGattServiceClientImpl>(device, mediums);
}
// static
@@ -80,8 +86,8 @@ void FastPairGattServiceClientImpl::Factory::SetFactoryForTesting(
FastPairGattServiceClientImpl::Factory::~Factory() = default;
FastPairGattServiceClientImpl::FastPairGattServiceClientImpl(
const FastPairDevice& device)
: device_address_(device.GetBleAddress()) {}
const FastPairDevice& device, Mediums& mediums)
: device_address_(device.GetBleAddress()), mediums_(mediums) {}
void FastPairGattServiceClientImpl::InitializeGattConnection(
absl::AnyInvocable<void(std::optional<PairFailure>)>
@@ -113,7 +119,10 @@ void FastPairGattServiceClientImpl::AttemptGattConnection() {
void FastPairGattServiceClientImpl::CreateGattConnection() {
NEARBY_LOGS(INFO) << __func__ << " : Create Gatt Connection to the device.";
gatt_client_ = ble_.ConnectToGattServer(device_address_);
if (mediums_.GetBluetoothRadio().Enable() &&
mediums_.GetBleV2().IsAvailable()) {
gatt_client_ = mediums_.GetBleV2().ConnectToGattServer(device_address_);
}
if (!gatt_client_) {
// The device must have been lost between connection attempts.
NotifyInitializedError(
@@ -168,7 +177,7 @@ void FastPairGattServiceClientImpl::GetFastPairGattCharacteristics() {
}
is_initialized_ = true;
std::move(on_gatt_initialized_callback_)(absl::nullopt);
std::move(on_gatt_initialized_callback_)(std::nullopt);
}
std::optional<GattCharacteristic>
@@ -255,7 +264,7 @@ void FastPairGattServiceClientImpl::WriteRequestAsync(
std::vector<uint8_t> data_to_write_vec(data_to_write.begin(),
data_to_write.end());
// Append the public version of the private key to the message so thedevice
// Append the public version of the private key to the message so the device
// can generate the shared secret to decrypt the message.
const std::optional<std::array<uint8_t, 64>> public_key =
fast_pair_data_encryptor.GetPublicKey();
@@ -340,7 +349,7 @@ void FastPairGattServiceClientImpl::WritePasskeyAsync(
// Subscribe the notification once the passkey characteristic's value changed
if (SubscribePasskeyCharacteristic()) {
is_passkey_notification_subscribed_ = true;
// Write passkey confonirmation request to the passkey characteristic
// Write passkey confirmation request to the passkey characteristic
WritePasskeyCharacteristic(
std::string(data_to_write_vec.begin(), data_to_write_vec.end()));
}
@@ -25,7 +25,7 @@
#include "fastpair/common/fast_pair_device.h"
#include "fastpair/common/pair_failure.h"
#include "fastpair/handshake/fast_pair_gatt_service_client.h"
#include "fastpair/internal/ble/ble.h"
#include "fastpair/internal/mediums/mediums.h"
#include "internal/platform/ble_v2.h"
#include "internal/platform/timer_impl.h"
@@ -41,7 +41,7 @@ class FastPairGattServiceClientImpl : public FastPairGattServiceClient {
class Factory {
public:
static std::unique_ptr<FastPairGattServiceClient> Create(
const FastPairDevice& device);
const FastPairDevice& device, Mediums& mediums);
static void SetFactoryForTesting(Factory* test_factory);
protected:
@@ -52,7 +52,8 @@ class FastPairGattServiceClientImpl : public FastPairGattServiceClient {
static Factory* g_test_factory_;
};
explicit FastPairGattServiceClientImpl(const FastPairDevice& device);
explicit FastPairGattServiceClientImpl(const FastPairDevice& device,
Mediums& mediums);
FastPairGattServiceClientImpl(const FastPairGattServiceClientImpl&) = delete;
FastPairGattServiceClientImpl& operator=(
const FastPairGattServiceClientImpl&) = delete;
@@ -144,7 +145,7 @@ class FastPairGattServiceClientImpl : public FastPairGattServiceClient {
bool is_initialized_ = false;
std::string device_address_;
std::unique_ptr<GattClient> gatt_client_;
Ble ble_;
Mediums& mediums_;
};
} // namespace fastpair
} // namespace nearby
@@ -15,17 +15,22 @@
#include "fastpair/handshake/fast_pair_gatt_service_client_impl.h"
#include <array>
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include "gtest/gtest.h"
#include "absl/status/status.h"
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "fastpair/common/constant.h"
#include "fastpair/common/fast_pair_device.h"
#include "fastpair/common/pair_failure.h"
#include "fastpair/common/protocol.h"
#include "fastpair/handshake/fake_fast_pair_data_encryptor.h"
#include "fastpair/handshake/fast_pair_gatt_service_client.h"
#include "fastpair/internal/mediums/mediums.h"
#include "internal/platform/ble_v2.h"
#include "internal/platform/bluetooth_adapter.h"
#include "internal/platform/byte_array.h"
@@ -161,7 +166,9 @@ class FastPairGattServiceClientTest : public testing::Test {
void InitializeFastPairGattServiceClient() {
FastPairDevice device(kMetadataId, kProviderAddress,
Protocol::kFastPairInitialPairing);
gatt_client_ = FastPairGattServiceClientImpl::Factory::Create(device);
Mediums mediums;
gatt_client_ =
FastPairGattServiceClientImpl::Factory::Create(device, mediums);
gatt_client_->InitializeGattConnection(
[this](std::optional<PairFailure> failure) {
initalized_failure_ = failure;
@@ -188,18 +195,16 @@ class FastPairGattServiceClientTest : public testing::Test {
passkey_characteristic_.value(), false, {});
}
absl::optional<PairFailure> GetInitializedCallbackResult() {
std::optional<PairFailure> GetInitializedCallbackResult() {
return initalized_failure_;
}
void WriteTestCallback(absl::string_view response,
absl::optional<PairFailure> failure) {
std::optional<PairFailure> failure) {
write_failure_ = failure;
}
absl::optional<PairFailure> GetWriteCallbackResult() {
return write_failure_;
}
std::optional<PairFailure> GetWriteCallbackResult() { return write_failure_; }
void WriteRequestToKeyBased() {
gatt_client_->WriteRequestAsync(
@@ -240,8 +245,8 @@ class FastPairGattServiceClientTest : public testing::Test {
private:
std::optional<GattCharacteristic> key_based_characteristic_;
std::optional<GattCharacteristic> passkey_characteristic_;
absl::optional<PairFailure> initalized_failure_;
absl::optional<PairFailure> write_failure_;
std::optional<PairFailure> initalized_failure_;
std::optional<PairFailure> write_failure_;
Property properties_ = Property::kWrite | Property::kNotify;
Permission permissions_ = Permission::kWrite;
};
@@ -277,7 +282,7 @@ TEST_F(FastPairGattServiceClientTest, SuccessfulWriteKeyBaseCharacteristics) {
InitializeFastPairGattServiceClient();
WriteRequestToKeyBased();
EXPECT_EQ(TriggerKeyBasedGattChanged(), absl::OkStatus());
EXPECT_EQ(GetWriteCallbackResult(), absl::nullopt);
EXPECT_EQ(GetWriteCallbackResult(), std::nullopt);
}
TEST_F(FastPairGattServiceClientTest, SuccessfulWritePasskeyCharacteristics) {
@@ -285,7 +290,7 @@ TEST_F(FastPairGattServiceClientTest, SuccessfulWritePasskeyCharacteristics) {
InitializeFastPairGattServiceClient();
WriteRequestToPasskey();
EXPECT_EQ(TriggerPasskeyGattChanged(), absl::OkStatus());
EXPECT_EQ(GetWriteCallbackResult(), absl::nullopt);
EXPECT_EQ(GetWriteCallbackResult(), std::nullopt);
}
TEST_F(FastPairGattServiceClientTest, FailedSubscribeKeybaseCharacteristic) {
@@ -297,7 +302,7 @@ TEST_F(FastPairGattServiceClientTest, FailedSubscribeKeybaseCharacteristic) {
PairFailure::kKeyBasedPairingCharacteristicSubscription);
WriteRequestToPasskey();
EXPECT_EQ(TriggerPasskeyGattChanged(), absl::OkStatus());
EXPECT_EQ(GetWriteCallbackResult(), absl::nullopt);
EXPECT_EQ(GetWriteCallbackResult(), std::nullopt);
}
TEST_F(FastPairGattServiceClientTest, FailedSubscribePasskeyCharacteristic) {
@@ -306,7 +311,7 @@ TEST_F(FastPairGattServiceClientTest, FailedSubscribePasskeyCharacteristic) {
RemoveDiscoveredPasskeyCharacteristic();
WriteRequestToKeyBased();
EXPECT_EQ(TriggerKeyBasedGattChanged(), absl::OkStatus());
EXPECT_EQ(GetWriteCallbackResult(), absl::nullopt);
EXPECT_EQ(GetWriteCallbackResult(), std::nullopt);
WriteRequestToPasskey();
EXPECT_EQ(GetWriteCallbackResult(),
PairFailure::kPasskeyCharacteristicSubscription);
+2 -4
View File
@@ -49,11 +49,10 @@ class FastPairHandshake {
FastPairDevice& device, std::optional<PairFailure> failure)>;
FastPairHandshake(
FastPairDevice& device, OnCompleteCallback on_complete_cb,
OnCompleteCallback on_complete_cb,
std::unique_ptr<FastPairDataEncryptor> data_encryptor,
std::unique_ptr<FastPairGattServiceClient> gatt_service_client)
: device_(&device),
on_complete_callback_(std::move(on_complete_cb)),
: on_complete_callback_(std::move(on_complete_cb)),
fast_pair_data_encryptor_(std::move(data_encryptor)),
fast_pair_gatt_service_client_(std::move(gatt_service_client)) {}
@@ -73,7 +72,6 @@ class FastPairHandshake {
protected:
bool completed_successfully_ = false;
FastPairDevice* device_;
OnCompleteCallback on_complete_callback_;
std::unique_ptr<FastPairDataEncryptor> fast_pair_data_encryptor_;
std::unique_ptr<FastPairGattServiceClient> fast_pair_gatt_service_client_;
+26 -21
View File
@@ -31,23 +31,24 @@ namespace nearby {
namespace fastpair {
FastPairHandshakeImpl::FastPairHandshakeImpl(FastPairDevice& device,
Mediums& mediums,
OnCompleteCallback on_complete)
: FastPairHandshake(device, std::move(on_complete), nullptr, nullptr) {
: FastPairHandshake(std::move(on_complete), nullptr, nullptr) {
fast_pair_gatt_service_client_ =
FastPairGattServiceClientImpl::Factory::Create(device);
FastPairGattServiceClientImpl::Factory::Create(device, mediums);
fast_pair_gatt_service_client_->InitializeGattConnection(
[this](std::optional<PairFailure> failure) {
OnGattClientInitializedCallback(failure);
[&](std::optional<PairFailure> failure) {
OnGattClientInitializedCallback(device, failure);
});
}
void FastPairHandshakeImpl::OnGattClientInitializedCallback(
std::optional<PairFailure> failure) {
FastPairDevice& device, std::optional<PairFailure> failure) {
if (failure.has_value()) {
NEARBY_LOGS(WARNING) << __func__
<< ": Failed to init gatt client with failure = "
<< failure.value();
std::move(on_complete_callback_)(*device_, failure.value());
std::move(on_complete_callback_)(device, failure.value());
return;
}
@@ -55,16 +56,19 @@ void FastPairHandshakeImpl::OnGattClientInitializedCallback(
<< __func__
<< ": Fast Pair GATT service client initialization successful.";
FastPairDataEncryptorImpl::Factory::CreateAsync(
*device_, absl::bind_front(
&FastPairHandshakeImpl::OnDataEncryptorCreateAsync, this));
device,
[&](std::unique_ptr<FastPairDataEncryptor> fast_pair_data_encryptor) {
OnDataEncryptorCreateAsync(device, std::move(fast_pair_data_encryptor));
});
}
void FastPairHandshakeImpl::OnDataEncryptorCreateAsync(
FastPairDevice& device,
std::unique_ptr<FastPairDataEncryptor> fast_pair_data_encryptor) {
if (!fast_pair_data_encryptor) {
NEARBY_LOGS(WARNING) << __func__
<< ": Failed to create Fast Pair Data Encryptor.";
std::move(on_complete_callback_)(*device_,
std::move(on_complete_callback_)(device,
PairFailure::kDataEncryptorRetrieval);
return;
}
@@ -74,21 +78,22 @@ void FastPairHandshakeImpl::OnDataEncryptorCreateAsync(
fast_pair_gatt_service_client_->WriteRequestAsync(
/*message_type=*/kKeyBasedPairingType,
/*flags=*/kInitialOrSubsequentFlags,
/*provider_address=*/device_->GetBleAddress(),
/*provider_address=*/device.GetBleAddress(),
/*seekers_address=*/"", *fast_pair_data_encryptor_,
[this](absl::string_view response, std::optional<PairFailure> failure) {
OnWriteResponse(response, failure);
[&](absl::string_view response, std::optional<PairFailure> failure) {
OnWriteResponse(device, response, failure);
});
}
void FastPairHandshakeImpl::OnWriteResponse(
absl::string_view response, std::optional<PairFailure> failure) {
FastPairDevice& device, absl::string_view response,
std::optional<PairFailure> failure) {
if (failure.has_value()) {
NEARBY_LOGS(WARNING)
<< __func__
<< ": Failed during key-based pairing protocol with failure = "
<< failure.value();
std::move(on_complete_callback_)(*device_, failure.value());
std::move(on_complete_callback_)(device, failure.value());
return;
}
@@ -98,33 +103,33 @@ void FastPairHandshakeImpl::OnWriteResponse(
NEARBY_LOGS(WARNING)
<< __func__ << ": Handshake failed because of incorrect response size.";
std::move(on_complete_callback_)(
*device_, PairFailure::kKeybasedPairingResponseDecryptFailure);
device, PairFailure::kKeybasedPairingResponseDecryptFailure);
return;
}
std::vector<uint8_t> response_bytes(response.begin(), response.end());
fast_pair_data_encryptor_->ParseDecryptResponse(
response_bytes, [this](std::optional<DecryptedResponse> response) {
OnParseDecryptedResponse(response);
response_bytes, [&](std::optional<DecryptedResponse> response) {
OnParseDecryptedResponse(device, response);
});
}
void FastPairHandshakeImpl::OnParseDecryptedResponse(
std::optional<DecryptedResponse>& response) {
FastPairDevice& device, std::optional<DecryptedResponse>& response) {
if (!response.has_value()) {
NEARBY_LOGS(WARNING) << __func__
<< ": Missing decrypted response from parse.";
std::move(on_complete_callback_)(
*device_, PairFailure::kKeybasedPairingResponseDecryptFailure);
device, PairFailure::kKeybasedPairingResponseDecryptFailure);
return;
}
NEARBY_LOGS(INFO) << __func__
<< ": Successfully decrypted and parsed response.";
device_->set_public_address(
device.set_public_address(
device::CanonicalizeBluetoothAddress(response->address_bytes));
completed_successfully_ = true;
std::move(on_complete_callback_)(*device_, absl::nullopt);
std::move(on_complete_callback_)(device, absl::nullopt);
}
} // namespace fastpair
@@ -22,23 +22,28 @@
#include "fastpair/common/pair_failure.h"
#include "fastpair/crypto/decrypted_response.h"
#include "fastpair/handshake/fast_pair_handshake.h"
#include "fastpair/internal/mediums/mediums.h"
namespace nearby {
namespace fastpair {
class FastPairHandshakeImpl : public FastPairHandshake {
public:
FastPairHandshakeImpl(FastPairDevice& device, OnCompleteCallback on_complete);
explicit FastPairHandshakeImpl(FastPairDevice& device, Mediums& mediums,
OnCompleteCallback on_complete);
FastPairHandshakeImpl(const FastPairHandshakeImpl&) = delete;
FastPairHandshakeImpl& operator=(const FastPairHandshakeImpl&) = delete;
private:
void OnGattClientInitializedCallback(std::optional<PairFailure> failure);
void OnGattClientInitializedCallback(FastPairDevice& device,
std::optional<PairFailure> failure);
void OnDataEncryptorCreateAsync(
FastPairDevice& device,
std::unique_ptr<FastPairDataEncryptor> fast_pair_data_encryptor);
void OnWriteResponse(absl::string_view response,
void OnWriteResponse(FastPairDevice& device, absl::string_view response,
std::optional<PairFailure> failure);
void OnParseDecryptedResponse(std::optional<DecryptedResponse>& response);
void OnParseDecryptedResponse(FastPairDevice& device,
std::optional<DecryptedResponse>& response);
};
} // namespace fastpair
@@ -162,8 +162,9 @@ TEST_F(FastPairHandshakeImplTest, Success) {
FastPairDevice device(kMetadataId, kProviderAddress,
Protocol::kFastPairInitialPairing);
CountDownLatch latch(1);
Mediums mediums;
handshake_ = std::make_unique<FastPairHandshakeImpl>(
device,
device, mediums,
[&](FastPairDevice& callback_device, std::optional<PairFailure> failure) {
EXPECT_EQ(&device, &callback_device);
EXPECT_EQ(device.public_address(), kPublicAddress);
@@ -180,8 +181,9 @@ TEST_F(FastPairHandshakeImplTest, GattError) {
FastPairDevice device(kMetadataId, kProviderAddress,
Protocol::kFastPairInitialPairing);
CountDownLatch latch(1);
Mediums mediums;
handshake_ = std::make_unique<FastPairHandshakeImpl>(
device,
device, mediums,
[&](FastPairDevice& callback_device, std::optional<PairFailure> failure) {
EXPECT_EQ(&device, &callback_device);
EXPECT_EQ(failure.value(), PairFailure::kCreateGattConnection);
@@ -197,8 +199,9 @@ TEST_F(FastPairHandshakeImplTest, DataEncryptorCreateError) {
FastPairDevice device(kMetadataId, kProviderAddress,
Protocol::kFastPairInitialPairing);
CountDownLatch latch(1);
Mediums mediums;
handshake_ = std::make_unique<FastPairHandshakeImpl>(
device,
device, mediums,
[&](FastPairDevice& callback_device, std::optional<PairFailure> failure) {
EXPECT_EQ(&device, &callback_device);
EXPECT_EQ(failure.value(), PairFailure::kDataEncryptorRetrieval);
@@ -214,8 +217,9 @@ TEST_F(FastPairHandshakeImplTest, WriteResponseError) {
FastPairDevice device(kMetadataId, kProviderAddress,
Protocol::kFastPairInitialPairing);
CountDownLatch latch(1);
Mediums mediums;
handshake_ = std::make_unique<FastPairHandshakeImpl>(
device,
device, mediums,
[&](FastPairDevice& callback_device, std::optional<PairFailure> failure) {
EXPECT_EQ(&device, &callback_device);
EXPECT_EQ(failure.value(),
@@ -233,8 +237,9 @@ TEST_F(FastPairHandshakeImplTest, WriteResponseWrongSize) {
FastPairDevice device(kMetadataId, kProviderAddress,
Protocol::kFastPairInitialPairing);
CountDownLatch latch(1);
Mediums mediums;
handshake_ = std::make_unique<FastPairHandshakeImpl>(
device,
device, mediums,
[&](FastPairDevice& callback_device, std::optional<PairFailure> failure) {
EXPECT_EQ(&device, &callback_device);
EXPECT_EQ(failure.value(),
@@ -252,8 +257,9 @@ TEST_F(FastPairHandshakeImplTest, ParseResponseError) {
FastPairDevice device(kMetadataId, kProviderAddress,
Protocol::kFastPairInitialPairing);
CountDownLatch latch(1);
Mediums mediums;
handshake_ = std::make_unique<FastPairHandshakeImpl>(
device,
device, mediums,
[&](FastPairDevice& callback_device, std::optional<PairFailure> failure) {
EXPECT_EQ(&device, &callback_device);
EXPECT_EQ(failure.value(),
@@ -0,0 +1,90 @@
// Copyright 2023 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 "fastpair/handshake/fast_pair_handshake_lookup.h"
#include <memory>
#include <utility>
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "fastpair/handshake/fast_pair_handshake_impl.h"
#include "internal/platform/logging.h"
namespace nearby {
namespace fastpair {
FastPairHandshakeLookup* FastPairHandshakeLookup::instance_ = nullptr;
absl::Mutex FastPairHandshakeLookup::mutex_(absl::kConstInit);
// static
FastPairHandshakeLookup* FastPairHandshakeLookup::GetInstance() {
absl::MutexLock lock(&mutex_);
if (!instance_) {
instance_ = new FastPairHandshakeLookup();
}
return instance_;
}
FastPairHandshake* FastPairHandshakeLookup::Get(FastPairDevice* device) {
absl::MutexLock lock(&mutex_);
auto it = fast_pair_handshakes_.find(device);
return it != fast_pair_handshakes_.end() ? it->second.get() : nullptr;
}
FastPairHandshake* FastPairHandshakeLookup::Get(absl::string_view address) {
absl::MutexLock lock(&mutex_);
for (const auto& pair : fast_pair_handshakes_) {
if (pair.first->public_address() == address ||
pair.first->GetBleAddress() == address) {
return pair.second.get();
}
}
return nullptr;
}
bool FastPairHandshakeLookup::Erase(FastPairDevice* device) {
absl::MutexLock lock(&mutex_);
return fast_pair_handshakes_.erase(device) == 1;
}
bool FastPairHandshakeLookup::Erase(absl::string_view address) {
absl::MutexLock lock(&mutex_);
for (const auto& pair : fast_pair_handshakes_) {
if (pair.first->public_address() == address ||
pair.first->GetBleAddress() == address) {
fast_pair_handshakes_.erase(pair.first);
return true;
}
}
return false;
}
void FastPairHandshakeLookup::Clear() {
absl::MutexLock lock(&mutex_);
fast_pair_handshakes_.clear();
}
FastPairHandshake* FastPairHandshakeLookup::Create(
FastPairDevice& device, Mediums& mediums, OnCompleteCallback on_complete) {
absl::MutexLock lock(&mutex_);
auto it = fast_pair_handshakes_.emplace(
&device, std::make_unique<FastPairHandshakeImpl>(device, mediums,
std::move(on_complete)));
DCHECK(it.second);
return it.first->second.get();
}
} // namespace fastpair
} // namespace nearby
@@ -0,0 +1,87 @@
// Copyright 2023 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 THIRD_PARTY_NEARBY_FASTPAIR_HANDSHAKE_FAST_PAIR_HANDSHAKE_LOOKUP_H_
#define THIRD_PARTY_NEARBY_FASTPAIR_HANDSHAKE_FAST_PAIR_HANDSHAKE_LOOKUP_H_
#include <memory>
#include <optional>
#include "absl/container/flat_hash_map.h"
#include "absl/functional/any_invocable.h"
#include "absl/synchronization/mutex.h"
#include "fastpair/common/fast_pair_device.h"
#include "fastpair/common/pair_failure.h"
#include "fastpair/handshake/fast_pair_handshake.h"
#include "fastpair/internal/mediums/mediums.h"
namespace nearby {
namespace fastpair {
// This Singletonclass creates, deletes and exposes FastPairHandshake instances.
class FastPairHandshakeLookup {
public:
using OnCompleteCallback = absl::AnyInvocable<void(
FastPairDevice& device, std::optional<PairFailure> failure)>;
// This is the static method that controls the access to the singleton
// instance. On the first run, it creates a singleton object and places it
// into the static field. On subsequent runs, it returns the existing object
// stored in the static field.
static FastPairHandshakeLookup* GetInstance();
// Singletons should not be cloneable.
FastPairHandshakeLookup(const FastPairHandshakeLookup&) = delete;
// Singletons should not be assignable.
FastPairHandshakeLookup& operator=(const FastPairHandshakeLookup&) = delete;
// Get an existing instance for |FastPairdevice|.
FastPairHandshake* Get(FastPairDevice* device);
// Get an existing instance for |address|.
FastPairHandshake* Get(absl::string_view address);
// Erases the FastPairHandshake instance for |FastPairdevice| if it exists.
bool Erase(FastPairDevice* device);
// Erases the FastPairHandshake instance for |FastPairdevice| if it exists.
bool Erase(absl::string_view address);
// Deletes all existing FastPairHandshake instances.
void Clear();
// Creates and returns a new instance for |FastPairdevice| if no instance
// already exists.
// Returns the existing instance if there is one.
FastPairHandshake* Create(FastPairDevice& device, Mediums& mediums,
OnCompleteCallback on_complete);
protected:
// Constructor/destructor of singleton object should not be public
// for which the destructor will never be called.
// and constructor will be invoked once from GetInstance() static method.
FastPairHandshakeLookup() = default;
~FastPairHandshakeLookup() = default;
private:
static absl::Mutex mutex_;
static FastPairHandshakeLookup* instance_ ABSL_GUARDED_BY(mutex_);
absl::flat_hash_map<FastPairDevice*, std::unique_ptr<FastPairHandshake>>
fast_pair_handshakes_ ABSL_GUARDED_BY(mutex_);
};
} // namespace fastpair
} // namespace nearby
#endif // THIRD_PARTY_NEARBY_FASTPAIR_HANDSHAKE_FAST_PAIR_HANDSHAKE_LOOKUP_H_
@@ -0,0 +1,127 @@
// Copyright 2023 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 "fastpair/handshake/fast_pair_handshake_lookup.h"
#include <memory>
#include <optional>
#include "gtest/gtest.h"
#include "absl/strings/string_view.h"
#include "fastpair/common/fast_pair_device.h"
#include "fastpair/common/pair_failure.h"
#include "fastpair/common/protocol.h"
#include "fastpair/internal/mediums/mediums.h"
#include "internal/platform/count_down_latch.h"
namespace nearby {
namespace fastpair {
namespace {
constexpr absl::string_view kValidModelId("718c17");
constexpr absl::string_view kBLEAddress("ble_address");
constexpr absl::string_view kPubliceAddress("public_address");
class FastPairHandshakeLookupTest : public ::testing::Test {
public:
FastPairHandshakeLookupTest() {
device_ = new FastPairDevice(kValidModelId, kBLEAddress,
Protocol::kFastPairInitialPairing);
device_->set_public_address(kPubliceAddress);
}
void CreateFastPairHandshkeInstanceForDevice(FastPairDevice& device) {
CountDownLatch latch(1);
Mediums mediums;
EXPECT_TRUE(FastPairHandshakeLookup::GetInstance()->Create(
device, mediums,
[&](FastPairDevice& cb_device, std::optional<PairFailure> failure) {
EXPECT_EQ(&device, &cb_device);
EXPECT_EQ(failure, PairFailure::kCreateGattConnection);
latch.CountDown();
}));
latch.Await();
}
FastPairDevice* device_ = nullptr;
};
TEST_F(FastPairHandshakeLookupTest, CreateFastPairHandshkeInstanceForDevice) {
EXPECT_FALSE(FastPairHandshakeLookup::GetInstance()->Get(device_));
EXPECT_FALSE(FastPairHandshakeLookup::GetInstance()->Get(kBLEAddress));
EXPECT_FALSE(FastPairHandshakeLookup::GetInstance()->Get(kPubliceAddress));
CreateFastPairHandshkeInstanceForDevice(*device_);
// GetFastPairHandshakeWithDevicePtr
EXPECT_TRUE(FastPairHandshakeLookup::GetInstance()->Get(device_));
// GetFastPairHandshakeWithBLEAddress
EXPECT_TRUE(FastPairHandshakeLookup::GetInstance()->Get(kBLEAddress));
// GetFastPairHandshakeWithPublicAddress
EXPECT_TRUE(FastPairHandshakeLookup::GetInstance()->Get(kPubliceAddress));
// GetFastPairHandshakeWithDevicePtr
EXPECT_TRUE(FastPairHandshakeLookup::GetInstance()->Get(device_));
// GetFastPairHandshakeWithWrongAddress
EXPECT_FALSE(FastPairHandshakeLookup::GetInstance()->Get(""));
}
TEST_F(FastPairHandshakeLookupTest, EraseFastPairHandshakeWithDevicePtr) {
CreateFastPairHandshkeInstanceForDevice(*device_);
EXPECT_TRUE(FastPairHandshakeLookup::GetInstance()->Get(device_));
EXPECT_TRUE(FastPairHandshakeLookup::GetInstance()->Erase(device_));
// Already Erased
EXPECT_FALSE(FastPairHandshakeLookup::GetInstance()->Get(device_));
EXPECT_FALSE(FastPairHandshakeLookup::GetInstance()->Erase(kBLEAddress));
EXPECT_FALSE(FastPairHandshakeLookup::GetInstance()->Erase(kPubliceAddress));
}
TEST_F(FastPairHandshakeLookupTest, EraseFastPairHandshakeWithBLEAddress) {
CreateFastPairHandshkeInstanceForDevice(*device_);
EXPECT_TRUE(FastPairHandshakeLookup::GetInstance()->Get(device_));
// Erase Wrong Address
EXPECT_FALSE(FastPairHandshakeLookup::GetInstance()->Erase(""));
EXPECT_TRUE(FastPairHandshakeLookup::GetInstance()->Erase(kBLEAddress));
// Already Erased
EXPECT_FALSE(FastPairHandshakeLookup::GetInstance()->Get(device_));
EXPECT_FALSE(FastPairHandshakeLookup::GetInstance()->Erase(device_));
EXPECT_FALSE(FastPairHandshakeLookup::GetInstance()->Erase(kPubliceAddress));
}
TEST_F(FastPairHandshakeLookupTest, EraseFastPairHandshakeWithPublicAddress) {
CreateFastPairHandshkeInstanceForDevice(*device_);
EXPECT_TRUE(FastPairHandshakeLookup::GetInstance()->Get(device_));
EXPECT_TRUE(FastPairHandshakeLookup::GetInstance()->Erase(kPubliceAddress));
// Already Erased
EXPECT_FALSE(FastPairHandshakeLookup::GetInstance()->Get(device_));
EXPECT_FALSE(FastPairHandshakeLookup::GetInstance()->Erase(device_));
EXPECT_FALSE(FastPairHandshakeLookup::GetInstance()->Erase(kBLEAddress));
}
TEST_F(FastPairHandshakeLookupTest, ClearAllFastPairHandshakeInstances) {
CreateFastPairHandshkeInstanceForDevice(*device_);
EXPECT_TRUE(FastPairHandshakeLookup::GetInstance()->Get(device_));
FastPairHandshakeLookup::GetInstance()->Clear();
EXPECT_FALSE(FastPairHandshakeLookup::GetInstance()->Get(device_));
}
} // namespace
} // namespace fastpair
} // namespace nearby
@@ -15,12 +15,17 @@
licenses(["notice"])
cc_library(
name = "ble",
name = "mediums",
srcs = [
"ble.cc",
"ble_v2.cc",
"bluetooth_radio.cc",
],
hdrs = [
"ble.h",
"ble_v2.h",
"bluetooth_radio.h",
"mediums.h",
],
visibility = [
"//fastpair:__subpackages__",
@@ -30,13 +35,41 @@ cc_library(
"//internal/platform:comm",
"//internal/platform:logging",
"//internal/platform:types",
"@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/time",
],
)
cc_test(
name = "bluetooth_radio_test",
size = "small",
srcs = [
"bluetooth_radio_test.cc",
],
shard_count = 16,
deps = [
":mediums",
"//internal/platform/implementation/g3", # build_cleaner: keep
"@com_github_protobuf_matchers//protobuf-matchers",
"@com_google_googletest//:gtest_main",
],
)
cc_test(
name = "mediums_test",
size = "small",
srcs = [
"mediums_test.cc",
],
shard_count = 16,
deps = [
":mediums",
"//internal/platform/implementation/g3", # build_cleaner: keep
"@com_github_protobuf_matchers//protobuf-matchers",
"@com_google_googletest//:gtest_main",
],
)
cc_test(
name = "ble_test",
size = "small",
@@ -45,7 +78,7 @@ cc_test(
],
shard_count = 16,
deps = [
":ble",
":mediums",
"//internal/platform:base",
"//internal/platform:comm",
"//internal/platform:test_util",
@@ -57,3 +90,18 @@ cc_test(
"@com_google_googletest//:gtest_main",
],
)
cc_test(
name = "ble_v2_test",
size = "small",
srcs = [
"ble_v2_test.cc",
],
shard_count = 16,
deps = [
":mediums",
"//internal/platform/implementation/g3", # build_cleaner: keep
"@com_github_protobuf_matchers//protobuf-matchers",
"@com_google_googletest//:gtest_main",
],
)
@@ -12,87 +12,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "fastpair/internal/ble/ble.h"
#include "fastpair/internal/mediums/ble.h"
#include <memory>
#include <string>
#include <utility>
#include "internal/platform/ble_v2.h"
#include "fastpair/internal/mediums/bluetooth_radio.h"
#include "internal/platform/bluetooth_adapter.h"
#include "internal/platform/logging.h"
#include "internal/platform/mutex_lock.h"
namespace nearby {
namespace fastpair {
namespace {
// A stub BlePeripheral implementation.
class BlePeripheralStub : public api::ble_v2::BlePeripheral {
public:
explicit BlePeripheralStub(absl::string_view ble_address) {
ble_address_ = std::string(ble_address);
}
std::string GetAddress() const override { return ble_address_; }
private:
std::string ble_address_;
};
} // namespace
Ble::~Ble() {
// We never enabled Bluetooth, nothing to do.
if (!ever_saved_state_.Get()) {
NEARBY_LOG(INFO, "BT adapter was not used. Not touching HW.");
return;
}
NEARBY_LOG(INFO, "Bring BT adapter to original state");
if (!SetBluetoothState(originally_enabled_.Get())) {
NEARBY_LOG(INFO, "Failed to restore BT adapter original state.");
}
}
bool Ble::Enable() {
if (!SaveOriginalState()) {
return false;
}
return SetBluetoothState(true);
}
bool Ble::Disable() {
if (!SaveOriginalState()) {
return false;
}
return SetBluetoothState(false);
}
bool Ble::IsEnabled() const {
return IsAdapterValid() && IsInDesiredState(true);
}
bool Ble::SetBluetoothState(bool enable) {
return adapter_.SetStatus(enable ? BluetoothAdapter::Status::kEnabled
: BluetoothAdapter::Status::kDisabled);
}
bool Ble::IsInDesiredState(bool should_be_enabled) const {
return adapter_.IsEnabled() == should_be_enabled;
}
bool Ble::SaveOriginalState() {
if (!IsAdapterValid()) {
return false;
}
// If we haven't saved the original state of the radio, save it.
if (!ever_saved_state_.Set(true)) {
originally_enabled_.Set(adapter_.IsEnabled());
}
return true;
}
Ble::Ble(BluetoothRadio& radio) : radio_(radio) {}
bool Ble::IsAvailable() const {
MutexLock lock(&mutex_);
@@ -122,7 +54,7 @@ bool Ble::StartScanning(const std::string& service_id,
return false;
}
if (!IsEnabled()) {
if (!radio_.IsEnabled()) {
NEARBY_LOGS(INFO)
<< "Can't start BLE scanning because Bluetooth was NOT enabled";
return false;
@@ -183,18 +115,9 @@ bool Ble::StopScanning(const std::string& service_id) {
return ret;
}
std::unique_ptr<GattClient> Ble::ConnectToGattServer(
absl::string_view ble_address) {
MutexLock lock(&mutex_);
auto v2_peripheral = std::make_unique<BlePeripheralStub>(ble_address);
return v2_medium_.ConnectToGattServer(BleV2Peripheral(v2_peripheral.get()),
api::ble_v2::TxPowerLevel::kUnknown,
{});
}
bool Ble::IsScanning() {
NEARBY_LOGS(INFO) << __func__;
MutexLock lock(&mutex_);
return IsScanningLocked();
}
@@ -15,59 +15,30 @@
#ifndef THIRD_PARTY_NEARBY_FASTPAIR_INTERNAL_BLE_BLE_H_
#define THIRD_PARTY_NEARBY_FASTPAIR_INTERNAL_BLE_BLE_H_
#include <cstdint>
#include <memory>
#include <string>
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "internal/platform/atomic_boolean.h"
#include "fastpair/internal/mediums/bluetooth_radio.h"
#include "internal/platform/ble.h"
#include "internal/platform/ble_v2.h"
#include "internal/platform/bluetooth_adapter.h"
#include "internal/platform/multi_thread_executor.h"
#include "internal/platform/mutex.h"
namespace nearby {
namespace fastpair {
// Provides the operations that can be performed on the Bluetooth Low Energy
// (BLE) medium.
class Ble {
public:
using DiscoveredPeripheralCallback = BleMedium::DiscoveredPeripheralCallback;
Ble() = default;
Ble(Ble&&) = default;
Ble& operator=(Ble&&) = default;
explicit Ble(BluetoothRadio& bluetooth_radio);
Ble(Ble&&) = delete;
Ble& operator=(Ble&&) = delete;
~Ble() = default;
// Reverts the Ble to its original state.
~Ble();
// Enables Bluetooth. Returns true if enabled successfully.
// This must be called before attempting to invoke any other methods of
// this class.
bool Enable();
// Disables Bluetooth. Returns true if disabled successfully.
bool Disable();
// Returns true if the Bluetooth radio is currently enabled.
bool IsEnabled() const;
// Returns true if Ble communications are supported by a platform.
// Returns true, if Ble communications are supported by a platform.
bool IsAvailable() const ABSL_LOCKS_EXCLUDED(mutex_);
// Returns true if this object owns a valid platform implementation.
bool IsMediumValid() const ABSL_LOCKS_EXCLUDED(mutex_) {
MutexLock lock(&mutex_);
return medium_.IsValid();
}
// Returns true if this object has a valid BluetoothAdapter reference.
bool IsAdapterValid() const { return adapter_.IsValid(); }
// Return true if Ble is currenlty scanning.
bool IsScanning() ABSL_LOCKS_EXCLUDED(mutex_);
// Enables Ble scanning mode. Will report any discoverable peripherals in
// range through a callback. Returns true, if scanning mode was enabled,
// false otherwise.
@@ -76,51 +47,29 @@ class Ble {
DiscoveredPeripheralCallback callback)
ABSL_LOCKS_EXCLUDED(mutex_);
// Returns a new GattClient connection to a gatt server.
std::unique_ptr<GattClient> ConnectToGattServer(
absl::string_view ble_address);
// Disables Ble discovery mode.
bool StopScanning(const std::string& service_id) ABSL_LOCKS_EXCLUDED(mutex_);
// Return true if Ble is currenlty scanning.
bool IsScanning() ABSL_LOCKS_EXCLUDED(mutex_);
// Return BleMedium
BleMedium& getMedium() { return medium_; }
// Return BluetoothAdapter
BluetoothAdapter& GetBluetoothAdapter() { return adapter_; }
private:
mutable Mutex mutex_;
// BluetoothAdapter::IsValid() will return false if BT is not supported.
BluetoothAdapter adapter_;
DiscoveredPeripheralCallback discovered_peripheral_callback_;
BleMedium medium_ ABSL_GUARDED_BY(mutex_){adapter_};
BleV2Medium v2_medium_ ABSL_GUARDED_BY(mutex_){adapter_};
bool is_scanning_ = false;
// Same as IsAvailable(), but must be called with mutex_ held.
bool IsAvailableLocked() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Same as IsDiscovering(), but must be called with mutex_ held.
bool IsScanningLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
bool SetBluetoothState(bool enable);
bool IsInDesiredState(bool should_be_enabled) const;
// To be called in enable() and disable(). This will remember the
// original state of the ble before any ble state has been modified.
// Returns false if Bluetooth doesn't exist on the device and the state cannot
// be obtained.
bool SaveOriginalState();
// The Ble's original state, before we modified it. True if
// originally enabled, false if originally disabled.
// We restore the radio to its original state in the destructor.
AtomicBoolean originally_enabled_{false};
// false if we never modified the radio state, true otherwise.
AtomicBoolean ever_saved_state_{false};
mutable Mutex mutex_;
DiscoveredPeripheralCallback discovered_peripheral_callback_;
BluetoothRadio& radio_ ABSL_GUARDED_BY(mutex_);
BluetoothAdapter& adapter_ ABSL_GUARDED_BY(mutex_){
radio_.GetBluetoothAdapter()};
BleMedium medium_ ABSL_GUARDED_BY(mutex_){adapter_};
bool is_scanning_ = false;
};
} // namespace fastpair
@@ -1,4 +1,4 @@
// Copyright 2022 Google LLC
// Copyright 2023 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,13 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "fastpair/internal/ble/ble.h"
#include "fastpair/internal/mediums/ble.h"
#include <string>
#include "gtest/gtest.h"
#include "internal/platform/ble.h"
#include "internal/platform/bluetooth_adapter.h"
#include "internal/platform/count_down_latch.h"
#include "internal/platform/medium_environment.h"
@@ -26,64 +24,27 @@ namespace nearby {
namespace fastpair {
namespace {
using FeatureFlags = FeatureFlags::Flags;
using DiscoveredPeripheralCallback = BleMedium::DiscoveredPeripheralCallback;
constexpr absl::Duration kWaitDuration = absl::Milliseconds(1000);
constexpr absl::string_view kServiceID{"com.google.location.nearby.apps.test"};
constexpr absl::string_view kAdvertisementString{"96C12E"};
constexpr absl::string_view kFastPairServiceUuid{"\x2c\xfe"};
class BleTest : public ::testing::TestWithParam<FeatureFlags> {
protected:
using DiscoveredPeripheralCallback = BleMedium::DiscoveredPeripheralCallback;
MediumEnvironment& env_{MediumEnvironment::Instance()};
};
TEST_F(BleTest, ConstructorDestructorWorks) {
Ble ble;
EXPECT_TRUE(ble.IsAdapterValid());
TEST(BleTest, ConstructorDestructorWorks) {
BluetoothRadio radio;
Ble ble(radio);
EXPECT_TRUE(ble.IsAvailable());
EXPECT_FALSE(ble.IsScanning());
}
TEST_F(BleTest, CanEnable) {
Ble ble;
EXPECT_TRUE(ble.IsAdapterValid());
EXPECT_TRUE(ble.IsEnabled());
EXPECT_TRUE(ble.Disable());
EXPECT_FALSE(ble.IsEnabled());
EXPECT_TRUE(ble.Enable());
EXPECT_TRUE(ble.IsEnabled());
}
TEST_F(BleTest, CanDisable) {
Ble ble;
EXPECT_TRUE(ble.IsAdapterValid());
EXPECT_TRUE(ble.IsEnabled());
EXPECT_TRUE(ble.Disable());
EXPECT_FALSE(ble.IsEnabled());
}
TEST_F(BleTest, CanConstructValidObject) {
env_.Start();
Ble ble_a;
Ble ble_b;
EXPECT_TRUE(ble_a.IsMediumValid());
EXPECT_TRUE(ble_a.IsAdapterValid());
EXPECT_TRUE(ble_a.IsAvailable());
EXPECT_TRUE(ble_b.IsMediumValid());
EXPECT_TRUE(ble_b.IsAdapterValid());
EXPECT_TRUE(ble_b.IsAvailable());
EXPECT_NE(&ble_a.GetBluetoothAdapter(), &ble_b.GetBluetoothAdapter());
env_.Stop();
}
TEST_F(BleTest, CanStartDiscovery) {
env_.Start();
Ble ble_a;
Ble ble_b;
ble_a.Enable();
ble_b.Enable();
TEST(BleTest, CanStartDiscovery) {
MediumEnvironment::Instance().Start();
BluetoothRadio radio_a;
BluetoothRadio radio_b;
Ble ble_a{radio_a};
Ble ble_b{radio_b};
radio_a.Enable();
radio_b.Enable();
std::string service_id(kServiceID);
ByteArray advertisement_bytes{std::string(kAdvertisementString)};
std::string fast_pair_service_uuid(kFastPairServiceUuid);
@@ -112,16 +73,8 @@ TEST_F(BleTest, CanStartDiscovery) {
EXPECT_TRUE(lost_latch.Await(kWaitDuration).result());
EXPECT_TRUE(ble_a.StopScanning(service_id));
EXPECT_FALSE(ble_a.IsScanning());
env_.Stop();
MediumEnvironment::Instance().Stop();
}
TEST_F(BleTest, CannConnectToGattServer) {
env_.Start();
Ble ble;
EXPECT_NE(ble.ConnectToGattServer("bleaddress"), nullptr);
env_.Stop();
}
} // namespace
} // namespace fastpair
} // namespace nearby
+69
View File
@@ -0,0 +1,69 @@
// Copyright 2023 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 "fastpair/internal/mediums/ble_v2.h"
#include <memory>
#include <string>
#include "internal/platform/mutex_lock.h"
namespace nearby {
namespace fastpair {
namespace {
// A stub BlePeripheral implementation.
class BlePeripheralStub : public api::ble_v2::BlePeripheral {
public:
explicit BlePeripheralStub(absl::string_view ble_address) {
ble_address_ = std::string(ble_address);
}
std::string GetAddress() const override { return ble_address_; }
private:
std::string ble_address_;
};
} // namespace
BleV2::BleV2(BluetoothRadio& radio) : radio_(radio) {}
bool BleV2::IsAvailable() const {
MutexLock lock(&mutex_);
return IsAvailableLocked();
}
bool BleV2::IsAvailableLocked() const {
return medium_.IsValid() && adapter_.IsValid() && adapter_.IsEnabled();
}
std::unique_ptr<GattClient> BleV2::ConnectToGattServer(
absl::string_view ble_address) {
MutexLock lock(&mutex_);
if (!radio_.IsEnabled()) {
NEARBY_LOGS(INFO)
<< "Can't connect to GattServer because Bluetooth was NOT enabled";
return nullptr;
}
if (!IsAvailableLocked()) {
NEARBY_LOGS(VERBOSE)
<< __func__
<< "Can't connect to GattServer because BleV2 isn't available.";
return nullptr;
}
auto v2_peripheral = std::make_unique<BlePeripheralStub>(ble_address);
return medium_.ConnectToGattServer(BleV2Peripheral(v2_peripheral.get()),
api::ble_v2::TxPowerLevel::kUnknown, {});
}
} // namespace fastpair
} // namespace nearby
+56
View File
@@ -0,0 +1,56 @@
// Copyright 2023 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 THIRD_PARTY_NEARBY_FASTPAIR_INTERNAL_MEDIUMS_BLE_V2_H_
#define THIRD_PARTY_NEARBY_FASTPAIR_INTERNAL_MEDIUMS_BLE_V2_H_
#include <memory>
#include "fastpair/internal/mediums/bluetooth_radio.h"
#include "internal/platform/ble_v2.h"
#include "internal/platform/mutex.h"
#include "internal/platform/mutex_lock.h"
namespace nearby {
namespace fastpair {
// Provides the operations that can be performed on the Bluetooth Low Energy
// (BLE_V2) medium.
class BleV2 {
public:
explicit BleV2(BluetoothRadio& bluetooth_radio);
~BleV2() = default;
// Returns true, if BleV2 communications are supported by a platform.
bool IsAvailable() const ABSL_LOCKS_EXCLUDED(mutex_);
// Returns a new GattClient connection to a gatt server.
std::unique_ptr<GattClient> ConnectToGattServer(
absl::string_view ble_address);
private:
// Same as IsAvailable(), but must be called with mutex_ held.
bool IsAvailableLocked() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
mutable Mutex mutex_;
BluetoothRadio& radio_ ABSL_GUARDED_BY(mutex_);
BluetoothAdapter& adapter_ ABSL_GUARDED_BY(mutex_){
radio_.GetBluetoothAdapter()};
BleV2Medium medium_ ABSL_GUARDED_BY(mutex_){adapter_};
};
} // namespace fastpair
} // namespace nearby
#endif // THIRD_PARTY_NEARBY_FASTPAIR_INTERNAL_MEDIUMS_BLE_V2_H_
+46
View File
@@ -0,0 +1,46 @@
// Copyright 2023 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 "fastpair/internal/mediums/ble_v2.h"
#include "gtest/gtest.h"
namespace nearby {
namespace fastpair {
namespace {
TEST(BleV2Test, IsAvailable) {
BluetoothRadio radio;
BleV2 bleV2(radio);
EXPECT_TRUE(bleV2.IsAvailable());
EXPECT_TRUE(radio.Disable());
EXPECT_FALSE(bleV2.IsAvailable());
}
TEST(BleV2Test, CanConnectToGattServer) {
BluetoothRadio radio;
BleV2 bleV2(radio);
EXPECT_TRUE(bleV2.ConnectToGattServer("bleaddress"));
}
TEST(BleV2Test, CannotConnectToGattServer) {
BluetoothRadio radio;
BleV2 bleV2(radio);
EXPECT_TRUE(radio.Disable());
EXPECT_FALSE(bleV2.ConnectToGattServer("bleaddress"));
}
} // namespace
} // namespace fastpair
} // namespace nearby
@@ -0,0 +1,86 @@
// Copyright 2023 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 "fastpair/internal/mediums/bluetooth_radio.h"
#include "internal/platform/logging.h"
namespace nearby {
namespace fastpair {
BluetoothRadio::BluetoothRadio() {
if (!IsAdapterValid()) {
NEARBY_LOGS(ERROR) << "Bluetooth adapter is not valid: BT is not supported";
}
}
BluetoothRadio::~BluetoothRadio() {
// We never enabled Bluetooth, nothing to do.
if (!ever_saved_state_.Get()) {
NEARBY_LOGS(INFO) << "BT adapter was not used. Not touching HW.";
return;
}
NEARBY_LOG(INFO, "Bring BT adapter to original state");
if (!SetBluetoothState(originally_enabled_.Get())) {
NEARBY_LOGS(INFO) << "Failed to restore BT adapter original state.";
}
}
bool BluetoothRadio::Enable() {
NEARBY_LOGS(INFO) << __func__;
if (!SaveOriginalState()) {
return false;
}
return SetBluetoothState(true);
}
bool BluetoothRadio::Disable() {
if (!SaveOriginalState()) {
return false;
}
return SetBluetoothState(false);
}
bool BluetoothRadio::IsEnabled() const {
return IsAdapterValid() && IsInDesiredState(true);
}
bool BluetoothRadio::SetBluetoothState(bool enable) {
return bluetooth_adapter_.SetStatus(
enable ? BluetoothAdapter::Status::kEnabled
: BluetoothAdapter::Status::kDisabled);
}
bool BluetoothRadio::IsInDesiredState(bool should_be_enabled) const {
return bluetooth_adapter_.IsEnabled() == should_be_enabled;
}
bool BluetoothRadio::SaveOriginalState() {
if (!IsAdapterValid()) {
return false;
}
// If we haven't saved the original state of the radio, save it.
if (!ever_saved_state_.Set(true)) {
originally_enabled_.Set(bluetooth_adapter_.IsEnabled());
}
return true;
}
} // namespace fastpair
} // namespace nearby
@@ -0,0 +1,79 @@
// Copyright 2023 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 THIRD_PARTY_NEARBY_FASTPAIR_INTERNAL_MEDIUMS_BLUETOOTH_RADIO_H_
#define THIRD_PARTY_NEARBY_FASTPAIR_INTERNAL_MEDIUMS_BLUETOOTH_RADIO_H_
#include "internal/platform/atomic_boolean.h"
#include "internal/platform/bluetooth_adapter.h"
namespace nearby {
namespace fastpair {
// Provides the operations that can be performed on the Bluetooth radio.
class BluetoothRadio {
public:
BluetoothRadio();
BluetoothRadio(BluetoothRadio&&) = default;
BluetoothRadio& operator=(BluetoothRadio&&) = default;
// Reverts the Bluetooth radio to its original state.
~BluetoothRadio();
// Enables Bluetooth.
//
// This must be called before attempting to invoke any other methods of
// this class.
//
// Returns true if enabled successfully.
bool Enable();
// Disables Bluetooth.
//
// Returns true if disabled successfully.
bool Disable();
// Returns true if the Bluetooth radio is currently enabled.
bool IsEnabled() const;
// Returns result of BluetoothAdapter::IsValid() for private adapter instance.
bool IsAdapterValid() const { return bluetooth_adapter_.IsValid(); }
BluetoothAdapter& GetBluetoothAdapter() { return bluetooth_adapter_; }
private:
bool SetBluetoothState(bool enable);
bool IsInDesiredState(bool should_be_enabled) const;
// To be called in enable() and disable(). This will remember the
// original state of the radio before any radio state has been modified.
// Returns false if Bluetooth doesn't exist on the device and the state cannot
// be obtained.
bool SaveOriginalState();
// BluetoothAdapter::IsValid() will return false if BT is not supported.
BluetoothAdapter bluetooth_adapter_;
// The Bluetooth radio's original state, before we modified it. True if
// originally enabled, false if originally disabled.
// We restore the radio to its original state in the destructor.
AtomicBoolean originally_enabled_{false};
// false if we never modified the radio state, true otherwise.
AtomicBoolean ever_saved_state_{false};
};
} // namespace fastpair
} // namespace nearby
#endif // THIRD_PARTY_NEARBY_FASTPAIR_INTERNAL_MEDIUMS_BLUETOOTH_RADIO_H_
@@ -0,0 +1,48 @@
// Copyright 2023 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 "fastpair/internal/mediums/bluetooth_radio.h"
#include "gtest/gtest.h"
namespace nearby {
namespace fastpair {
namespace {
TEST(BluetoothRadioTest, ConstructorDestructorWorks) {
BluetoothRadio radio;
EXPECT_TRUE(radio.IsAdapterValid());
}
TEST(BluetoothRadioTest, CanEnable) {
BluetoothRadio radio;
EXPECT_TRUE(radio.IsAdapterValid());
EXPECT_TRUE(radio.IsEnabled());
EXPECT_TRUE(radio.Disable());
EXPECT_FALSE(radio.IsEnabled());
EXPECT_TRUE(radio.Enable());
EXPECT_TRUE(radio.IsEnabled());
}
TEST(BluetoothRadioTest, CanDisable) {
BluetoothRadio radio;
EXPECT_TRUE(radio.IsAdapterValid());
EXPECT_TRUE(radio.IsEnabled());
EXPECT_TRUE(radio.Disable());
EXPECT_FALSE(radio.IsEnabled());
}
} // namespace
} // namespace fastpair
} // namespace nearby
+56
View File
@@ -0,0 +1,56 @@
// Copyright 2023 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 THIRD_PARTY_NEARBY_FASTPAIR_INTERNAL_MEDIUMS_MEDIUMS_H_
#define THIRD_PARTY_NEARBY_FASTPAIR_INTERNAL_MEDIUMS_MEDIUMS_H_
#include "fastpair/internal/mediums/ble.h"
#include "fastpair/internal/mediums/ble_v2.h"
#include "fastpair/internal/mediums/bluetooth_radio.h"
namespace nearby {
namespace fastpair {
// Facilitates convenient and reliable usage of various wireless mediums.
class Mediums {
public:
Mediums() = default;
~Mediums() = default;
// Returns a handle to the Bluetooth radio.
BluetoothRadio& GetBluetoothRadio() { return bluetooth_radio_; }
// Returns a handle to the Ble medium.
Ble& GetBle() { return ble_; }
// Returns a handle to the Ble medium.
BleV2& GetBleV2() { return ble_v2_; }
private:
// The order of declaration is critical for both construction and
// destruction.
//
// 1) Construction: The individual mediums have a dependency on the
// corresponding radio, so the radio must be initialized first.
//
// 2) Destruction: The individual mediums should be shut down before the
// corresponding radio.
BluetoothRadio bluetooth_radio_;
Ble ble_{bluetooth_radio_};
BleV2 ble_v2_{bluetooth_radio_};
};
} // namespace fastpair
} // namespace nearby
#endif // THIRD_PARTY_NEARBY_FASTPAIR_INTERNAL_MEDIUMS_MEDIUMS_H_
+31
View File
@@ -0,0 +1,31 @@
// Copyright 2023 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 "fastpair/internal/mediums/mediums.h"
#include "gtest/gtest.h"
namespace nearby {
namespace fastpair {
namespace {
TEST(MediumTest, ConstructorWorks) {
Mediums medium;
EXPECT_TRUE(medium.GetBluetoothRadio().IsAdapterValid());
EXPECT_FALSE(medium.GetBle().IsScanning());
EXPECT_TRUE(medium.GetBleV2().ConnectToGattServer("ble_address"));
}
} // namespace
} // namespace fastpair
} // namespace nearby
-3
View File
@@ -14,8 +14,6 @@ cc_library(
deps = [
"//internal/network:types",
"@com_google_absl//absl/functional:any_invocable",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
],
)
@@ -32,7 +30,6 @@ cc_test(
deps = [
":nearby_fastpair_test",
"//internal/network:types",
"//internal/platform/implementation/g3",
"@com_github_protobuf_matchers//protobuf-matchers",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/functional:any_invocable",
@@ -21,7 +21,6 @@
#include <utility>
#include <vector>
#include "absl/status/statusor.h"
#include "internal/network/http_client.h"
namespace nearby {
@@ -52,11 +51,6 @@ class FastPairFakeHttpClient : public HttpClient {
request_infos_.push_back(std::move(request_info));
}
absl::StatusOr<HttpResponse> GetResponse(
const HttpRequest& request) override {
return absl::UnimplementedError("unimplemented");
}
// Mock methods
void CompleteRequest(const absl::StatusOr<HttpResponse>& response,
size_t pos = 0) {
+2 -2
View File
@@ -29,12 +29,12 @@ Mediator::Mediator(std::unique_ptr<ScannerBroker> scanner_broker,
scanner_broker_->AddObserver(this);
}
void Mediator::OnDeviceFound(const FastPairDevice& device) {
void Mediator::OnDeviceFound(FastPairDevice& device) {
NEARBY_LOGS(INFO) << __func__ << ": " << device;
// Show discovery notification
}
void Mediator::OnDeviceLost(const FastPairDevice& device) {
void Mediator::OnDeviceLost(FastPairDevice& device) {
NEARBY_LOGS(INFO) << __func__ << ": " << device;
}
+2 -2
View File
@@ -33,8 +33,8 @@ class Mediator final : public ScannerBroker::Observer {
~Mediator() override = default;
// ScannerBroker::Observer
void OnDeviceFound(const FastPairDevice& device) override;
void OnDeviceLost(const FastPairDevice& device) override;
void OnDeviceFound(FastPairDevice& device) override;
void OnDeviceLost(FastPairDevice& device) override;
void StartScanning();
+1 -4
View File
@@ -16,10 +16,7 @@ cc_library(
copts = [
"-Ithird_party",
],
visibility = [
"//fastpair:__subpackages__",
"//location/nearby/cpp/sharing:__subpackages__",
],
visibility = ["//fastpair:__subpackages__"],
deps = [
"//fastpair/common",
"//fastpair/proto:fastpair_cc_proto",
@@ -26,7 +26,6 @@
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "fastpair/internal/test/fast_pair_fake_http_client.h"
#include "internal/network/http_client.h"
namespace nearby {
namespace fastpair {
@@ -41,11 +40,6 @@ constexpr char kRequestUrl[] = "https://googleapis.com/nearbysharing/test";
constexpr char kQueryParameterAlternateOutputKey[] = "alt";
constexpr char kQueryParameterAlternateOutputProto[] = "proto";
class MockHttpClient : public network::HttpClient {
public:
~MockHttpClient() override = default;
};
const FastPairMetadataFetcher::QueryParameters&
GetTestRequestProtoAsQueryParameters() {
static const FastPairMetadataFetcher::QueryParameters*
@@ -130,11 +124,9 @@ class FastPairMetadataFetcherImplTest : public ::testing::Test {
void CheckFastPairRepositoryGetUnauthRequest(
const FastPairMetadataFetcher::QueryParameters&
request_as_query_parameters) {
FastPairFakeHttpClient* fake_http_client =
reinterpret_cast<FastPairFakeHttpClient*>(http_client_.get());
EXPECT_EQ(fake_http_client->GetPendingRequest().size(), 1);
EXPECT_EQ(http_client_->GetPendingRequest().size(), 1);
const network::HttpRequest& request =
fake_http_client->GetPendingRequest()[0].request;
http_client_->GetPendingRequest()[0].request;
CheckPlatformTypeHeader(request.GetAllHeaders());
@@ -154,16 +146,14 @@ class FastPairMetadataFetcherImplTest : public ::testing::Test {
int error,
std::optional<network::HttpStatusCode> response_code = std::nullopt,
const std::optional<std::string>& response_string = std::nullopt) {
FastPairFakeHttpClient* client =
reinterpret_cast<FastPairFakeHttpClient*>(http_client_.get());
client->CompleteRequest(error, response_code, response_string);
http_client_->CompleteRequest(error, response_code, response_string);
EXPECT_TRUE(result_ || network_error_);
}
std::unique_ptr<std::string> result_;
std::unique_ptr<FastPairHttpError> network_error_;
private:
std::unique_ptr<network::HttpClient> http_client_;
std::unique_ptr<FastPairFakeHttpClient> http_client_;
FastPairMetadataFetcherImpl flow_{api::DeviceInfo::OsType::kChromeOs};
};
+6 -5
View File
@@ -29,7 +29,7 @@ cc_library(
],
deps = [
"//fastpair/common",
"//fastpair/internal/ble",
"//fastpair/internal/mediums",
"//fastpair/scanning/fastpair:scanning",
"//internal/base",
"//internal/platform:base",
@@ -68,14 +68,15 @@ cc_test(
deps = [
":scanner",
"//fastpair/common",
"//fastpair/scanning/fastpair:scanning",
"//fastpair/scanning/fastpair:test_support",
"//fastpair/internal/mediums",
"//fastpair/proto:fastpair_cc_proto",
"//fastpair/server_access:test_support",
"//internal/platform:base",
"//internal/platform:test_util",
"//internal/platform/implementation:types",
"//internal/platform:types",
"//internal/platform/implementation/g3", # build_cleaner: keep
"@com_github_protobuf_matchers//protobuf-matchers",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/time",
"@com_google_googletest//:gtest_main",
],
)
+4 -1
View File
@@ -33,7 +33,7 @@ cc_library(
deps = [
"//fastpair/common",
"//fastpair/dataparser",
"//fastpair/internal/ble",
"//fastpair/internal/mediums",
"//fastpair/proto:fastpair_cc_proto",
"//fastpair/repository",
"//fastpair/server_access",
@@ -45,6 +45,8 @@ cc_library(
"@com_google_absl//absl/functional:any_invocable",
"@com_google_absl//absl/functional:bind_front",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/synchronization",
"@com_google_absl//absl/time",
],
)
@@ -78,6 +80,7 @@ cc_test(
deps = [
":scanning",
"//fastpair/common",
"//fastpair/internal/mediums",
"//internal/platform:base",
"//internal/platform:comm",
"//internal/platform:test_util",
@@ -32,6 +32,7 @@ class FakeFastPairScanner final : public FastPairScanner {
void RemoveObserver(Observer* observer) override;
void NotifyDeviceFound(const BlePeripheral& peripheral);
void NotifyDeviceLost(const BlePeripheral& peripheral);
void StartScanning() override {};
private:
ObserverList<FastPairScanner::Observer> observer_;
@@ -25,6 +25,7 @@
#include "absl/functional/bind_front.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "fastpair/common/constant.h"
#include "fastpair/common/fast_pair_device.h"
#include "fastpair/common/protocol.h"
@@ -65,19 +66,16 @@ FastPairDiscoverableScannerImpl::Factory*
FastPairDiscoverableScannerImpl::Factory::g_test_factory_ = nullptr;
std::unique_ptr<FastPairDiscoverableScanner>
FastPairDiscoverableScannerImpl::Factory::Create(
std::shared_ptr<FastPairScanner> scanner,
std::shared_ptr<BluetoothAdapter> adapter, DeviceCallback found_callback,
DeviceCallback lost_callback) {
FastPairDiscoverableScannerImpl::Factory::Create(FastPairScanner& scanner,
DeviceCallback found_callback,
DeviceCallback lost_callback) {
if (g_test_factory_) {
return g_test_factory_->CreateInstance(
std::move(scanner), std::move(adapter), std::move(found_callback),
std::move(lost_callback));
return g_test_factory_->CreateInstance(scanner, std::move(found_callback),
std::move(lost_callback));
}
return std::make_unique<FastPairDiscoverableScannerImpl>(
std::move(scanner), std::move(adapter), std::move(found_callback),
std::move(lost_callback));
scanner, std::move(found_callback), std::move(lost_callback));
}
void FastPairDiscoverableScannerImpl::Factory::SetFactoryForTesting(
@@ -89,14 +87,12 @@ FastPairDiscoverableScannerImpl::Factory::~Factory() = default;
// FastPairScannerImpl
FastPairDiscoverableScannerImpl::FastPairDiscoverableScannerImpl(
std::shared_ptr<FastPairScanner> scanner,
std::shared_ptr<BluetoothAdapter> adapter, DeviceCallback found_callback,
FastPairScanner& scanner, DeviceCallback found_callback,
DeviceCallback lost_callback)
: scanner_(std::move(scanner)),
adapter_(std::move(adapter)),
: scanner_(scanner),
found_callback_(std::move(found_callback)),
lost_callback_(std::move(lost_callback)) {
scanner_->AddObserver(this);
scanner_.AddObserver(this);
}
void FastPairDiscoverableScannerImpl::OnDeviceFound(
@@ -108,8 +104,10 @@ void FastPairDiscoverableScannerImpl::OnDeviceFound(
<< ": Device doesn't have any Fast Pair Service Data.";
return;
}
model_id_parse_attempts_[peripheral.GetName()] = 1;
{
absl::MutexLock lock(&mutex_);
model_id_parse_attempts_[peripheral.GetName()] = 1;
}
NEARBY_LOGS(INFO) << __func__ << ": Attempting to get model ID";
std::vector<uint8_t> service_data;
std::move(std::begin(fast_pair_service_data),
@@ -125,18 +123,20 @@ void FastPairDiscoverableScannerImpl::OnDeviceFound(
void FastPairDiscoverableScannerImpl::OnModelIdRetrieved(
const std::string& address,
const std::optional<absl::string_view> model_id) {
auto it = model_id_parse_attempts_.find(address);
{
absl::MutexLock lock(&mutex_);
auto it = model_id_parse_attempts_.find(address);
// If there's no entry in the map, the device was lost while parsing.
if (it == model_id_parse_attempts_.end()) {
NEARBY_LOGS(WARNING)
<< __func__
<< ": Returning early because device as lost while parsing.";
return;
// If there's no entry in the map, the device was lost while parsing.
if (it == model_id_parse_attempts_.end()) {
NEARBY_LOGS(WARNING)
<< __func__
<< ": Returning early because device as lost while parsing.";
return;
}
model_id_parse_attempts_.erase(it);
}
model_id_parse_attempts_.erase(it);
if (!model_id.has_value()) {
NEARBY_LOGS(INFO) << __func__
<< ": Returning early because no model id was parsed.";
@@ -182,9 +182,11 @@ void FastPairDiscoverableScannerImpl::OnDeviceMetadataRetrieved(
"Ignoring this advertisement";
return;
}
FastPairDevice device(model_id, address, Protocol::kFastPairInitialPairing);
NotifyDeviceFound(device);
absl::MutexLock lock(&mutex_);
notified_devices_.insert_or_assign(
address, std::make_unique<FastPairDevice>(
model_id, address, Protocol::kFastPairInitialPairing));
NotifyDeviceFound(*notified_devices_[address]);
}
void FastPairDiscoverableScannerImpl::NotifyDeviceFound(
@@ -192,23 +194,21 @@ void FastPairDiscoverableScannerImpl::NotifyDeviceFound(
NEARBY_LOGS(VERBOSE) << "Notify Device found:"
<< "BluetoothAddress = " << device.GetBleAddress()
<< ", Model id = " << device.GetModelId();
notified_devices_[device.GetBleAddress()] = &device;
found_callback_(device);
}
void FastPairDiscoverableScannerImpl::OnDeviceLost(
const BlePeripheral& peripheral) {
NEARBY_LOGS(INFO) << __func__ << ": Running lost callback";
absl::MutexLock lock(&mutex_);
model_id_parse_attempts_.erase(peripheral.GetName());
auto it = notified_devices_.find(peripheral.GetName());
// Don't invoke callback if we didn't notify this device.
if (it == notified_devices_.end()) return;
FastPairDevice* notified_device = it->second;
lost_callback_(*it->second);
notified_devices_.erase(it);
lost_callback_(*notified_device);
}
} // namespace fastpair
@@ -20,7 +20,9 @@
#include <string>
#include <vector>
#include "absl/synchronization/mutex.h"
#include "fastpair/common/fast_pair_device.h"
#include "fastpair/internal/mediums/mediums.h"
#include "fastpair/repository/device_metadata.h"
#include "fastpair/scanning/fastpair/fast_pair_discoverable_scanner.h"
#include "fastpair/scanning/fastpair/fast_pair_scanner.h"
@@ -36,25 +38,22 @@ class FastPairDiscoverableScannerImpl : public FastPairDiscoverableScanner,
class Factory {
public:
static std::unique_ptr<FastPairDiscoverableScanner> Create(
std::shared_ptr<FastPairScanner> scanner,
std::shared_ptr<BluetoothAdapter> adapter,
DeviceCallback found_callback, DeviceCallback lost_callback);
FastPairScanner& scanner, DeviceCallback found_callback,
DeviceCallback lost_callback);
static void SetFactoryForTesting(Factory* g_test_factory);
protected:
virtual ~Factory();
virtual std::unique_ptr<FastPairDiscoverableScanner> CreateInstance(
std::shared_ptr<FastPairScanner> scanner,
std::shared_ptr<BluetoothAdapter> adapter,
DeviceCallback found_callback, DeviceCallback lost_callback) = 0;
FastPairScanner& scanner, DeviceCallback found_callback,
DeviceCallback lost_callback) = 0;
private:
static Factory* g_test_factory_;
};
FastPairDiscoverableScannerImpl(std::shared_ptr<FastPairScanner> scanner,
std::shared_ptr<BluetoothAdapter> adapter,
FastPairDiscoverableScannerImpl(FastPairScanner& scanner,
DeviceCallback found_callback,
DeviceCallback lost_callback);
FastPairDiscoverableScannerImpl(const FastPairDiscoverableScannerImpl&) =
@@ -75,12 +74,14 @@ class FastPairDiscoverableScannerImpl : public FastPairDiscoverableScanner,
DeviceMetadata& device_metadata);
void NotifyDeviceFound(FastPairDevice& device);
std::shared_ptr<FastPairScanner> scanner_;
std::shared_ptr<BluetoothAdapter> adapter_;
absl::Mutex mutex_;
FastPairScanner& scanner_;
DeviceCallback found_callback_;
DeviceCallback lost_callback_;
absl::flat_hash_map<std::string, FastPairDevice*> notified_devices_;
absl::flat_hash_map<std::string, int> model_id_parse_attempts_;
absl::flat_hash_map<std::string, std::unique_ptr<FastPairDevice>>
notified_devices_ ABSL_GUARDED_BY(mutex_);
absl::flat_hash_map<std::string, int> model_id_parse_attempts_
ABSL_GUARDED_BY(mutex_);
ObserverList<FastPairScanner::Observer> observer_list_;
};
@@ -19,8 +19,6 @@
#include <utility>
#include <vector>
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
#include "absl/synchronization/notification.h"
#include "fastpair/scanning/fastpair/fake_fast_pair_scanner.h"
@@ -78,13 +76,11 @@ class FastPairDiscoverableScannerImplTest : public testing::Test {
public:
void SetUp() override {
SetUpMetadata();
scanner_ = std::make_shared<FakeFastPairScanner>();
adapter_ = std::make_shared<BluetoothAdapter>();
scanner_ = std::make_unique<FakeFastPairScanner>();
}
void TearDown() override {
scanner_.reset();
adapter_.reset();
repository_.reset();
}
@@ -98,9 +94,8 @@ class FastPairDiscoverableScannerImplTest : public testing::Test {
// void TearDown() override { discoverable_scanner_.reset(); }
protected:
std::shared_ptr<FakeFastPairScanner> scanner_;
std::unique_ptr<FakeFastPairScanner> scanner_;
std::unique_ptr<FakeFastPairRepository> repository_;
std::shared_ptr<BluetoothAdapter> adapter_;
DeviceCallback found_device_callback_;
DeviceCallback lost_device_callback_;
};
@@ -117,7 +112,7 @@ TEST_F(FastPairDiscoverableScannerImplTest, ValidModelId) {
std::unique_ptr<FastPairDiscoverableScanner>
discoverable_scanner_from_factory =
FastPairDiscoverableScannerImpl::Factory::Create(
scanner_, adapter_, std::move(found_device_callback_),
*scanner_, std::move(found_device_callback_),
std::move(lost_device_callback_));
auto ble_peripheral =
@@ -136,7 +131,7 @@ TEST_F(FastPairDiscoverableScannerImplTest, InvalidModelId) {
std::unique_ptr<FastPairDiscoverableScanner>
discoverable_scanner_from_factory =
FastPairDiscoverableScannerImpl::Factory::Create(
scanner_, adapter_, std::move(found_device_callback_),
*scanner_, std::move(found_device_callback_),
std::move(lost_device_callback_));
auto ble_peripheral = std::make_unique<FakeBlePeripheral>(
@@ -153,7 +148,7 @@ TEST_F(FastPairDiscoverableScannerImplTest, NoServiceData) {
std::unique_ptr<FastPairDiscoverableScanner>
discoverable_scanner_from_factory =
FastPairDiscoverableScannerImpl::Factory::Create(
scanner_, adapter_, std::move(found_device_callback_),
*scanner_, std::move(found_device_callback_),
std::move(lost_device_callback_));
auto ble_peripheral =
@@ -174,7 +169,7 @@ TEST_F(FastPairDiscoverableScannerImplTest, UnsupportedDeviceType) {
std::unique_ptr<FastPairDiscoverableScanner>
discoverable_scanner_from_factory =
FastPairDiscoverableScannerImpl::Factory::Create(
scanner_, adapter_, std::move(found_device_callback_),
*scanner_, std::move(found_device_callback_),
std::move(lost_device_callback_));
auto ble_peripheral =
@@ -196,7 +191,7 @@ TEST_F(FastPairDiscoverableScannerImplTest, UnsupportedNotifictionType) {
std::unique_ptr<FastPairDiscoverableScanner>
discoverable_scanner_from_factory =
FastPairDiscoverableScannerImpl::Factory::Create(
scanner_, adapter_, std::move(found_device_callback_),
*scanner_, std::move(found_device_callback_),
std::move(lost_device_callback_));
auto ble_peripheral =
@@ -222,7 +217,7 @@ TEST_F(FastPairDiscoverableScannerImplTest, UnspecifiedNotificationType) {
std::unique_ptr<FastPairDiscoverableScanner>
discoverable_scanner_from_factory =
FastPairDiscoverableScannerImpl::Factory::Create(
scanner_, adapter_, std::move(found_device_callback_),
*scanner_, std::move(found_device_callback_),
std::move(lost_device_callback_));
auto ble_peripheral =
@@ -246,7 +241,7 @@ TEST_F(FastPairDiscoverableScannerImplTest, V1NotificationType) {
std::unique_ptr<FastPairDiscoverableScanner>
discoverable_scanner_from_factory =
FastPairDiscoverableScannerImpl::Factory::Create(
scanner_, adapter_, std::move(found_device_callback_),
*scanner_, std::move(found_device_callback_),
std::move(lost_device_callback_));
auto ble_peripheral =
@@ -270,7 +265,7 @@ TEST_F(FastPairDiscoverableScannerImplTest, V2NotificationType) {
std::unique_ptr<FastPairDiscoverableScanner>
discoverable_scanner_from_factory =
FastPairDiscoverableScannerImpl::Factory::Create(
scanner_, adapter_, std::move(found_device_callback_),
*scanner_, std::move(found_device_callback_),
std::move(lost_device_callback_));
auto ble_peripheral =
@@ -287,7 +282,7 @@ TEST_F(FastPairDiscoverableScannerImplTest, NearbyShareModelId) {
std::unique_ptr<FastPairDiscoverableScanner>
discoverable_scanner_from_factory =
FastPairDiscoverableScannerImpl::Factory::Create(
scanner_, adapter_, std::move(found_device_callback_),
*scanner_, std::move(found_device_callback_),
std::move(lost_device_callback_));
auto ble_peripheral = std::make_unique<FakeBlePeripheral>(
@@ -309,7 +304,7 @@ TEST_F(FastPairDiscoverableScannerImplTest,
std::unique_ptr<FastPairDiscoverableScanner>
discoverable_scanner_from_factory =
FastPairDiscoverableScannerImpl::Factory::Create(
scanner_, adapter_, std::move(found_device_callback_),
*scanner_, std::move(found_device_callback_),
std::move(lost_device_callback_));
auto ble_peripheral =
@@ -38,7 +38,8 @@ class FastPairScanner {
virtual void AddObserver(Observer* observer) = 0;
virtual void RemoveObserver(Observer* observer) = 0;
protected:
virtual void StartScanning() = 0;
virtual ~FastPairScanner() = default;
};
@@ -17,6 +17,7 @@
#include <memory>
#include <string>
#include "absl/time/time.h"
#include "fastpair/common/constant.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/logging.h"
@@ -31,31 +32,9 @@ constexpr absl::Duration kFastPairLowPowerInactiveSeconds = absl::Seconds(3);
constexpr char kFastPairServiceUuid[] = "0000FE2C-0000-1000-8000-00805F9B34FB";
} // namespace
// static
FastPairScannerImpl::Factory* FastPairScannerImpl::Factory::g_test_factory_ =
nullptr;
// static
std::shared_ptr<FastPairScanner> FastPairScannerImpl::Factory::Create() {
if (g_test_factory_) {
return g_test_factory_->CreateInstance();
}
return std::make_shared<FastPairScannerImpl>();
}
// static
void FastPairScannerImpl::Factory::SetFactoryForTesting(
Factory* g_test_factory) {
g_test_factory_ = g_test_factory;
}
FastPairScannerImpl::Factory::~Factory() = default;
// FastPairScannerImpl
FastPairScannerImpl::FastPairScannerImpl() {
FastPairScannerImpl::FastPairScannerImpl(Mediums& mediums) : mediums_(mediums) {
task_runner_ = std::make_unique<TaskRunnerImpl>(1);
StartScanning();
}
void FastPairScannerImpl::AddObserver(FastPairScanner::Observer* observer) {
@@ -67,10 +46,12 @@ void FastPairScannerImpl::RemoveObserver(FastPairScanner::Observer* observer) {
}
void FastPairScannerImpl::StartScanning() {
NEARBY_LOGS(VERBOSE) << __func__;
task_runner_->PostTask(
[this]() {
if (ble_.Enable() &&
ble_.StartScanning(
if (mediums_.GetBluetoothRadio().Enable() &&
mediums_.GetBle().IsAvailable() &&
mediums_.GetBle().StartScanning(
kServiceId, kFastPairServiceUuid,
{
.peripheral_discovered_cb =
@@ -108,7 +89,7 @@ void FastPairScannerImpl::StartScanning() {
void FastPairScannerImpl::StopScanning() {
DCHECK(IsFastPairLowPowerEnabled());
ble_.StopScanning(kServiceId);
mediums_.GetBle().StopScanning(kServiceId);
task_runner_->PostDelayedTask(kFastPairLowPowerInactiveSeconds,
[this]() { StartScanning(); });
}
@@ -15,18 +15,14 @@
#ifndef THIRD_PARTY_NEARBY_FASTPAIR_SCANNING_FASTPAIR_FAST_PAIR_SCANNER_IMPL_H_
#define THIRD_PARTY_NEARBY_FASTPAIR_SCANNING_FASTPAIR_FAST_PAIR_SCANNER_IMPL_H_
#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "fastpair/internal/ble/ble.h"
#include "fastpair/internal/mediums/mediums.h"
#include "fastpair/scanning/fastpair/fast_pair_scanner.h"
#include "internal/base/observer_list.h"
#include "internal/platform/bluetooth_adapter.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/task_runner.h"
namespace nearby {
@@ -34,21 +30,7 @@ namespace fastpair {
class FastPairScannerImpl : public FastPairScanner {
public:
class Factory {
public:
static std::shared_ptr<FastPairScanner> Create();
static void SetFactoryForTesting(Factory* g_test_factory);
protected:
virtual ~Factory();
virtual std::shared_ptr<FastPairScanner> CreateInstance() = 0;
private:
static Factory* g_test_factory_;
};
FastPairScannerImpl();
explicit FastPairScannerImpl(Mediums& mediums);
FastPairScannerImpl(const FastPairScannerImpl&) = delete;
FastPairScannerImpl& operator=(const FastPairScannerImpl&) = delete;
~FastPairScannerImpl() override = default;
@@ -65,11 +47,9 @@ class FastPairScannerImpl : public FastPairScanner {
// Todo(b/267348348): Support Flags to control feature ramp
bool IsFastPairLowPowerEnabled() const { return false; }
// For unit test
Ble& GetBle() { return ble_; }
void StartScanning() override;
private:
void StartScanning();
void StopScanning();
std::unique_ptr<TaskRunner> task_runner_;
@@ -80,7 +60,7 @@ class FastPairScannerImpl : public FastPairScanner {
device_address_advertisement_data_map_;
BluetoothAdapter bluetooth_adapter_;
Ble ble_;
Mediums& mediums_;
ObserverList<FastPairScanner::Observer> observer_;
};
@@ -14,153 +14,86 @@
#include "fastpair/scanning/fastpair/fast_pair_scanner_impl.h"
#include <algorithm>
#include <memory>
#include <string>
#include <vector>
#include "gtest/gtest.h"
#include "absl/strings/escaping.h"
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "fastpair/internal/mediums/mediums.h"
#include "fastpair/scanning/fastpair/fast_pair_scanner.h"
#include "internal/platform/bluetooth_adapter.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/count_down_latch.h"
#include "internal/platform/medium_environment.h"
namespace nearby {
namespace fastpair {
namespace {
// Below constants are used to construct MockBluetoothDevice for testing.
constexpr char kTestBleDeviceAddress[] = "11:12:13:14:15:16";
constexpr char kTestModelId[] = "112233";
constexpr absl::Duration kTaskWaitTimeout = absl::Milliseconds(200);
class FakeBlePeripheral : public api::BlePeripheral {
public:
explicit FakeBlePeripheral(absl::string_view name,
absl::string_view service_data) {
name_ = std::string(name);
std::string service_data_str = std::string(service_data);
ByteArray advertisement_bytes(service_data_str);
advertisement_data_ = advertisement_bytes;
}
FakeBlePeripheral(const FakeBlePeripheral&) = default;
~FakeBlePeripheral() override = default;
std::string GetName() const override { return name_; }
ByteArray GetAdvertisementBytes(
const std::string& service_id) const override {
return advertisement_data_;
}
void SetName(const std::string& name) { name_ = name; }
void SetAdvertisementBytes(ByteArray advertisement_bytes) {
advertisement_data_ = advertisement_bytes;
}
private:
std::string name_;
ByteArray advertisement_data_;
};
constexpr absl::Duration kTaskWaitTimeout = absl::Milliseconds(1000);
constexpr absl::string_view kServiceID{"Fast Pair"};
constexpr absl::string_view kModelId{"718c17"};
constexpr absl::string_view kFastPairServiceUuid{
"0000FE2C-0000-1000-8000-00805F9B34FB"};
class FastPairScannerObserver : public FastPairScanner::Observer {
public:
explicit FastPairScannerObserver(FastPairScanner* scanner,
CountDownLatch* accept_latch,
CountDownLatch* lost_latch) {
accept_latch_ = accept_latch;
lost_latch_ = lost_latch;
scanner->AddObserver(this);
}
// FastPairScanner::Observer overrides
void OnDeviceFound(const BlePeripheral& peripheral) override {
device_addreses_.push_back(peripheral.GetName());
on_device_found_count_++;
accept_latch_->CountDown();
}
void OnDeviceLost(const BlePeripheral& peripheral) override {
auto it = std::find(device_addreses_.begin(), device_addreses_.end(),
peripheral.GetName());
if (it == device_addreses_.end()) return;
device_addreses_.erase(it);
lost_latch_->CountDown();
}
bool DoesDeviceListContainTestDevice(const std::string& address) {
auto it =
std::find(device_addreses_.begin(), device_addreses_.end(), address);
return it != device_addreses_.end();
}
int on_device_found_count() { return on_device_found_count_; }
private:
std::vector<std::string> device_addreses_;
int on_device_found_count_ = 0;
CountDownLatch* accept_latch_ = nullptr;
CountDownLatch* lost_latch_ = nullptr;
};
class FastPairScannerImplTest : public testing::Test {
public:
void SetUp() override {
env_.Start();
scanner_ = std::make_shared<FastPairScannerImpl>();
SystemClock::Sleep(kTaskWaitTimeout);
scanner_observer_ = std::make_unique<FastPairScannerObserver>();
scanner_->AddObserver(scanner_observer_.get());
}
void TearDown() override {
scanner_->RemoveObserver(scanner_observer_.get());
scanner_.reset();
scanner_observer_.reset();
env_.Stop();
}
void TriggerOnDeviceFound(absl::string_view address, absl::string_view data) {
auto ble_peripheral = std::make_unique<FakeBlePeripheral>(address, data);
scanner_->OnDeviceFound(BlePeripheral(ble_peripheral.get()));
}
void TriggerOnDeviceLost(absl::string_view address, absl::string_view data) {
auto ble_peripheral = std::make_unique<FakeBlePeripheral>(address, data);
scanner_->OnDeviceLost(BlePeripheral(ble_peripheral.get()));
}
protected:
MediumEnvironment& env_{MediumEnvironment::Instance()};
std::shared_ptr<FastPairScannerImpl> scanner_;
std::unique_ptr<FastPairScannerObserver> scanner_observer_;
};
TEST_F(FastPairScannerImplTest, StartScanningSuccessfully) {
EXPECT_TRUE(scanner_->GetBle().IsScanning());
// Not StopScanning as FastPairLowPowerDisabled
}
TEST_F(FastPairScannerImplTest, StartScanning) {
env_.Start();
TEST_F(FastPairScannerImplTest, DeviceFoundNotifiesObservers) {
TriggerOnDeviceFound(kTestBleDeviceAddress, kTestModelId);
EXPECT_TRUE(scanner_observer_->DoesDeviceListContainTestDevice(
kTestBleDeviceAddress));
}
// Create Fast Pair Scanner and add its observer
Mediums mediums_1;
auto scanner = std::make_unique<FastPairScannerImpl>(mediums_1);
CountDownLatch accept_latch(1);
CountDownLatch lost_latch(1);
FastPairScannerObserver observer(scanner.get(), &accept_latch, &lost_latch);
TEST_F(FastPairScannerImplTest, DeviceLostNotifiesObservers) {
TriggerOnDeviceFound(kTestBleDeviceAddress, kTestModelId);
EXPECT_TRUE(scanner_observer_->DoesDeviceListContainTestDevice(
kTestBleDeviceAddress));
TriggerOnDeviceLost(kTestBleDeviceAddress, kTestModelId);
EXPECT_FALSE(scanner_observer_->DoesDeviceListContainTestDevice(
kTestBleDeviceAddress));
}
// Create Advertiser and startAdvertising
Mediums mediums_2;
std::string service_id(kServiceID);
ByteArray advertisement_bytes{absl::HexStringToBytes(kModelId)};
std::string fast_pair_service_uuid(kFastPairServiceUuid);
mediums_2.GetBle().getMedium().StartAdvertising(
service_id, advertisement_bytes, fast_pair_service_uuid);
TEST_F(FastPairScannerImplTest, DeviceFoundWithNoServiceData) {;
TriggerOnDeviceFound(kTestBleDeviceAddress, "");
EXPECT_FALSE(scanner_observer_->DoesDeviceListContainTestDevice(
kTestBleDeviceAddress));
}
// Fast Pair scanner startScanning
scanner->StartScanning();
// Notify device found
EXPECT_TRUE(accept_latch.Await(kTaskWaitTimeout).result());
TEST_F(FastPairScannerImplTest, RemoveObserver) {
scanner_->RemoveObserver(scanner_observer_.get());
TriggerOnDeviceFound(kTestBleDeviceAddress, kTestModelId);
EXPECT_FALSE(scanner_observer_->DoesDeviceListContainTestDevice(
kTestBleDeviceAddress));
}
// Advertiser stopAdvertising
mediums_2.GetBle().getMedium().StopAdvertising(service_id);
// Notify device lost
EXPECT_TRUE(lost_latch.Await(kTaskWaitTimeout).result());
env_.Stop();
}
} // namespace
} // namespace fastpair
} // namespace nearby
+2 -2
View File
@@ -35,13 +35,13 @@ class MockScannerBroker : public ScannerBroker {
observers_.RemoveObserver(observer);
}
void NotifyDeviceFound(const FastPairDevice& device) {
void NotifyDeviceFound(FastPairDevice& device) {
for (auto& observer : observers_.GetObservers()) {
observer->OnDeviceFound(device);
}
}
void NotifyDeviceLost(const FastPairDevice& device) {
void NotifyDeviceLost(FastPairDevice& device) {
for (auto& observer : observers_.GetObservers()) {
observer->OnDeviceLost(device);
}
+2 -2
View File
@@ -32,8 +32,8 @@ class ScannerBroker {
public:
virtual ~Observer() = default;
virtual void OnDeviceFound(const FastPairDevice& device) = 0;
virtual void OnDeviceLost(const FastPairDevice& device) = 0;
virtual void OnDeviceFound(FastPairDevice& device) = 0;
virtual void OnDeviceLost(FastPairDevice& device) = 0;
};
virtual ~ScannerBroker() = default;
+7 -10
View File
@@ -15,21 +15,17 @@
#include "fastpair/scanning/scanner_broker_impl.h"
#include <memory>
#include <utility>
#include "absl/functional/bind_front.h"
#include "fastpair/common/fast_pair_device.h"
#include "fastpair/scanning/fastpair/fast_pair_discoverable_scanner.h"
#include "fastpair/scanning/fastpair/fast_pair_discoverable_scanner_impl.h"
#include "fastpair/scanning/fastpair/fast_pair_scanner_impl.h"
#include "internal/platform/bluetooth_adapter.h"
#include "internal/platform/logging.h"
#include "internal/platform/task_runner_impl.h"
namespace nearby {
namespace fastpair {
ScannerBrokerImpl::ScannerBrokerImpl() {
adapter_ = std::make_shared<BluetoothAdapter>();
ScannerBrokerImpl::ScannerBrokerImpl(Mediums& mediums) : mediums_(mediums) {
task_runner_ = std::make_unique<TaskRunnerImpl>(1);
}
@@ -50,16 +46,17 @@ void ScannerBrokerImpl::StopScanning(Protocol protocol) {
NEARBY_LOGS(VERBOSE) << __func__ << ": protocol=" << protocol;
task_runner_->PostTask([this]() { StopFastPairScanning(); });
}
void ScannerBrokerImpl::StartFastPairScanning() {
DCHECK(!fast_pair_discoverable_scanner_);
DCHECK(adapter_);
NEARBY_LOGS(VERBOSE) << "Starting Fast Pair Scanning.";
scanner_ = std::make_shared<FastPairScannerImpl>();
scanner_ = std::make_unique<FastPairScannerImpl>(mediums_);
fast_pair_discoverable_scanner_ =
FastPairDiscoverableScannerImpl::Factory::Create(
scanner_, adapter_,
*scanner_,
absl::bind_front(&ScannerBrokerImpl::NotifyDeviceFound, this),
absl::bind_front(&ScannerBrokerImpl::NotifyDeviceLost, this));
scanner_->StartScanning();
}
void ScannerBrokerImpl::StopFastPairScanning() {
@@ -69,7 +66,7 @@ void ScannerBrokerImpl::StopFastPairScanning() {
NEARBY_LOGS(VERBOSE) << __func__ << "Stopping Fast Pair Scanning.";
}
void ScannerBrokerImpl::NotifyDeviceFound(const FastPairDevice& device) {
void ScannerBrokerImpl::NotifyDeviceFound(FastPairDevice& device) {
NEARBY_LOGS(INFO) << __func__ << ": Notifying device found, model id = "
<< device.GetModelId();
for (auto& observer : observers_.GetObservers()) {
@@ -77,7 +74,7 @@ void ScannerBrokerImpl::NotifyDeviceFound(const FastPairDevice& device) {
}
}
void ScannerBrokerImpl::NotifyDeviceLost(const FastPairDevice& device) {
void ScannerBrokerImpl::NotifyDeviceLost(FastPairDevice& device) {
NEARBY_LOGS(INFO) << __func__ << ": Notifying device lost, model id = "
<< device.GetModelId();
for (auto& observer : observers_.GetObservers()) {
+6 -8
View File
@@ -15,16 +15,14 @@
#ifndef THIRD_PARTY_NEARBY_FASTPAIR_SCANNING_SCANNER_BROKER_IMPL_H_
#define THIRD_PARTY_NEARBY_FASTPAIR_SCANNING_SCANNER_BROKER_IMPL_H_
#include <functional>
#include <memory>
#include <vector>
#include "fastpair/common/fast_pair_device.h"
#include "fastpair/internal/mediums/mediums.h"
#include "fastpair/scanning/fastpair/fast_pair_discoverable_scanner.h"
#include "fastpair/scanning/fastpair/fast_pair_scanner.h"
#include "fastpair/scanning/scanner_broker.h"
#include "internal/base/observer_list.h"
#include "internal/platform/bluetooth_adapter.h"
#include "internal/platform/task_runner.h"
namespace nearby {
@@ -32,7 +30,7 @@ namespace fastpair {
class ScannerBrokerImpl : public ScannerBroker {
public:
explicit ScannerBrokerImpl();
explicit ScannerBrokerImpl(Mediums& mediums);
~ScannerBrokerImpl() override = default;
// ScannerBroker:
@@ -44,12 +42,12 @@ class ScannerBrokerImpl : public ScannerBroker {
private:
void StartFastPairScanning();
void StopFastPairScanning();
void NotifyDeviceFound(const FastPairDevice& device);
void NotifyDeviceLost(const FastPairDevice& device);
void NotifyDeviceFound(FastPairDevice& device);
void NotifyDeviceLost(FastPairDevice& device);
Mediums& mediums_;
std::unique_ptr<TaskRunner> task_runner_;
std::shared_ptr<FastPairScanner> scanner_;
std::shared_ptr<BluetoothAdapter> adapter_;
std::unique_ptr<FastPairScanner> scanner_;
std::unique_ptr<FastPairDiscoverableScanner> fast_pair_discoverable_scanner_;
ObserverList<Observer> observers_;
};
+65 -157
View File
@@ -16,190 +16,98 @@
#include <memory>
#include <string>
#include <utility>
#include "gtest/gtest.h"
#include "absl/strings/escaping.h"
#include "absl/strings/string_view.h"
#include "fastpair/common/fast_pair_device.h"
#include "fastpair/common/protocol.h"
#include "fastpair/scanning/fastpair/fake_fast_pair_discoverable_scanner.h"
#include "fastpair/scanning/fastpair/fake_fast_pair_scanner.h"
#include "fastpair/scanning/fastpair/fast_pair_discoverable_scanner.h"
#include "fastpair/scanning/fastpair/fast_pair_discoverable_scanner_impl.h"
#include "fastpair/scanning/fastpair/fast_pair_scanner.h"
#include "fastpair/scanning/fastpair/fast_pair_scanner_impl.h"
#include "internal/platform/implementation/system_clock.h"
#include "fastpair/internal/mediums/mediums.h"
#include "fastpair/proto/fastpair_rpcs.proto.h"
#include "fastpair/scanning/scanner_broker.h"
#include "fastpair/server_access/fake_fast_pair_repository.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/count_down_latch.h"
#include "internal/platform/medium_environment.h"
namespace nearby {
namespace fastpair {
namespace {
constexpr absl::string_view kTestDeviceAddress("11:12:13:14:15:16");
constexpr absl::string_view kValidModelId("718c17");
constexpr absl::Duration kTaskWaitTimeout = absl::Milliseconds(200);
class FakeFastPairScannerFactory : public FastPairScannerImpl::Factory {
constexpr absl::Duration kTaskWaitTimeout = absl::Milliseconds(1000);
constexpr absl::string_view kServiceID{"Fast Pair"};
constexpr absl::string_view kModelId{"718c17"};
constexpr absl::string_view kFastPairServiceUuid{
"0000FE2C-0000-1000-8000-00805F9B34FB"};
constexpr absl::string_view kPublicAntiSpoof =
"Wuyr48lD3txnUhGiMF1IfzlTwRxxe+wMB1HLzP+"
"0wVcljfT3XPoiy1fntlneziyLD5knDVAJSE+RM/zlPRP/Jg==";
class ScannerBrokerObserver : public ScannerBroker::Observer {
public:
// FastPairScannerImpl::Factory:
std::shared_ptr<FastPairScanner> CreateInstance() override {
auto fake_fast_pair_scanner = std::shared_ptr<FakeFastPairScanner>();
fake_fast_pair_scanner_ = fake_fast_pair_scanner.get();
return fake_fast_pair_scanner;
explicit ScannerBrokerObserver(ScannerBroker* scanner_broker,
CountDownLatch* accept_latch,
CountDownLatch* lost_latch) {
accept_latch_ = accept_latch;
lost_latch_ = lost_latch;
scanner_broker->AddObserver(this);
}
~FakeFastPairScannerFactory() override = default;
FakeFastPairScanner* fake_fast_pair_scanner() {
return fake_fast_pair_scanner_;
void OnDeviceFound(FastPairDevice& device) override {
accept_latch_->CountDown();
}
private:
FakeFastPairScanner* fake_fast_pair_scanner_ = nullptr;
void OnDeviceLost(FastPairDevice& device) override {
lost_latch_->CountDown();
}
CountDownLatch* accept_latch_ = nullptr;
CountDownLatch* lost_latch_ = nullptr;
};
class FakeFastPairDiscoverableScannerFactory
: public FastPairDiscoverableScannerImpl::Factory {
public:
// FastPairDiscoverableScannerImpl::Factory:
std::unique_ptr<FastPairDiscoverableScanner> CreateInstance(
std::shared_ptr<FastPairScanner> scanner,
std::shared_ptr<BluetoothAdapter> adapter, DeviceCallback found_callback,
DeviceCallback lost_callback) override {
create_instance_ = true;
auto fake_fast_pair_discoverable_scanner =
std::make_unique<FakeFastPairDiscoverableScanner>(
std::move(found_callback), std::move(lost_callback));
fake_fast_pair_discoverable_scanner_ =
fake_fast_pair_discoverable_scanner.get();
return fake_fast_pair_discoverable_scanner;
}
FakeFastPairDiscoverableScanner* fake_fast_pair_discoverable_scanner() {
return fake_fast_pair_discoverable_scanner_;
}
bool create_instance() { return create_instance_; }
class ScannerBrokerImplTest : public testing::Test {
protected:
bool create_instance_ = false;
FakeFastPairDiscoverableScanner* fake_fast_pair_discoverable_scanner_ =
nullptr;
MediumEnvironment& env_{MediumEnvironment::Instance()};
};
class ScannerBrokerImplTest : public testing::Test,
public ScannerBroker::Observer {
public:
void SetUp() override {
adapter_ = std::shared_ptr<BluetoothAdapter>();
TEST_F(ScannerBrokerImplTest, CanStartScanning) {
env_.Start();
// Setup FakeFastPairRepository
std::string decoded_key;
absl::Base64Unescape(kPublicAntiSpoof, &decoded_key);
proto::Device metadata;
auto repository_ = std::make_unique<FakeFastPairRepository>();
metadata.mutable_anti_spoofing_key_pair()->set_public_key(decoded_key);
repository_->SetFakeMetadata(kModelId, metadata);
scanner_factory_ = std::make_unique<FakeFastPairScannerFactory>();
FastPairScannerImpl::Factory::SetFactoryForTesting(scanner_factory_.get());
// Create Fast Pair Scanner and add its observer
Mediums mediums_1;
auto scanner_broker = std::make_unique<ScannerBrokerImpl>(mediums_1);
CountDownLatch accept_latch(1);
CountDownLatch lost_latch(1);
ScannerBrokerObserver observer(scanner_broker.get(), &accept_latch,
&lost_latch);
discoverable_scanner_factory_ =
std::make_unique<FakeFastPairDiscoverableScannerFactory>();
FastPairDiscoverableScannerImpl::Factory::SetFactoryForTesting(
discoverable_scanner_factory_.get());
// Create Advertiser and startAdvertising
Mediums mediums_2;
std::string service_id(kServiceID);
ByteArray advertisement_bytes{absl::HexStringToBytes(kModelId)};
std::string fast_pair_service_uuid(kFastPairServiceUuid);
mediums_2.GetBle().getMedium().StartAdvertising(
service_id, advertisement_bytes, fast_pair_service_uuid);
scanner_broker_ = std::make_unique<ScannerBrokerImpl>();
scanner_broker_->AddObserver(this);
}
// Fast Pair scanner startScanning
scanner_broker->StartScanning(Protocol::kFastPairInitialPairing);
void TearDown() override {
scanner_broker_->RemoveObserver(this);
scanner_broker_.reset();
scanner_factory_.reset();
discoverable_scanner_factory_.reset();
FastPairScannerImpl::Factory::SetFactoryForTesting(nullptr);
FastPairDiscoverableScannerImpl::Factory::SetFactoryForTesting(nullptr);
adapter_.reset();
}
// Notify device found
EXPECT_TRUE(accept_latch.Await(kTaskWaitTimeout).result());
void TriggerDiscoverableDeviceFound() {
FastPairDevice device(std::string(kValidModelId),
std::string(kTestDeviceAddress),
Protocol::kFastPairInitialPairing);
discoverable_scanner_factory_->fake_fast_pair_discoverable_scanner()
->TriggerDeviceFoundCallback(device);
}
// Advertiser stopAdvertising
mediums_2.GetBle().getMedium().StopAdvertising(service_id);
void TriggerDiscoverableDeviceLost() {
FastPairDevice device(std::string(kValidModelId),
std::string(kTestDeviceAddress),
Protocol::kFastPairInitialPairing);
discoverable_scanner_factory_->fake_fast_pair_discoverable_scanner()
->TriggerDeviceLostCallback(device);
}
void OnDeviceFound(const FastPairDevice& device) override {
device_found_ = true;
}
void OnDeviceLost(const FastPairDevice& device) override {
device_lost_ = true;
}
protected:
bool device_found_ = false;
bool device_lost_ = false;
std::shared_ptr<BluetoothAdapter> adapter_;
std::unique_ptr<FakeFastPairScannerFactory> scanner_factory_;
std::unique_ptr<FakeFastPairDiscoverableScannerFactory>
discoverable_scanner_factory_;
std::unique_ptr<ScannerBroker> scanner_broker_;
};
TEST_F(ScannerBrokerImplTest, DiscoverableFound) {
EXPECT_FALSE(discoverable_scanner_factory_->create_instance());
scanner_broker_->StartScanning(Protocol::kFastPairInitialPairing);
SystemClock::Sleep(kTaskWaitTimeout);
EXPECT_FALSE(device_found_);
EXPECT_TRUE(discoverable_scanner_factory_->create_instance());
TriggerDiscoverableDeviceFound();
EXPECT_TRUE(device_found_);
// Notify device lost
EXPECT_TRUE(lost_latch.Await(kTaskWaitTimeout).result());
env_.Stop();
}
TEST_F(ScannerBrokerImplTest, DiscoverableLost) {
EXPECT_FALSE(discoverable_scanner_factory_->create_instance());
scanner_broker_->StartScanning(Protocol::kFastPairInitialPairing);
SystemClock::Sleep(kTaskWaitTimeout);
EXPECT_FALSE(device_found_);
EXPECT_TRUE(discoverable_scanner_factory_->create_instance());
TriggerDiscoverableDeviceLost();
EXPECT_TRUE(device_lost_);
}
TEST_F(ScannerBrokerImplTest, RemoveObserver) {
EXPECT_FALSE(discoverable_scanner_factory_->create_instance());
scanner_broker_->StartScanning(Protocol::kFastPairInitialPairing);
SystemClock::Sleep(kTaskWaitTimeout);
EXPECT_FALSE(device_found_);
EXPECT_TRUE(discoverable_scanner_factory_->create_instance());
scanner_broker_->RemoveObserver(this);
TriggerDiscoverableDeviceLost();
EXPECT_FALSE(device_lost_);
}
TEST_F(ScannerBrokerImplTest, StopScanning) {
EXPECT_FALSE(discoverable_scanner_factory_->create_instance());
scanner_broker_->StartScanning(Protocol::kFastPairInitialPairing);
SystemClock::Sleep(kTaskWaitTimeout);
EXPECT_TRUE(discoverable_scanner_factory_->create_instance());
scanner_broker_->StopScanning(Protocol::kFastPairInitialPairing);
SystemClock::Sleep(kTaskWaitTimeout);
scanner_broker_->StartScanning(Protocol::kFastPairInitialPairing);
SystemClock::Sleep(kTaskWaitTimeout);
EXPECT_TRUE(discoverable_scanner_factory_->create_instance());
}
} // namespace
} // namespace fastpair
} // namespace nearby
+67
View File
@@ -0,0 +1,67 @@
licenses(["notice"])
cc_library(
name = "fast_pair_ui",
srcs = [
"fast_pair/fast_pair_notification_controller.cc",
"fast_pair/fast_pair_presenter_impl.cc",
"ui_broker_impl.cc",
],
hdrs = [
"actions.h",
"fast_pair/fast_pair_notification_controller.h",
"fast_pair/fast_pair_presenter.h",
"fast_pair/fast_pair_presenter_impl.h",
"ui_broker.h",
"ui_broker_impl.h",
],
compatible_with = ["//buildenv/target:non_prod"],
visibility = [
"//fastpair:__subpackages__",
],
deps = [
"//fastpair/common",
"//fastpair/repository",
"//fastpair/server_access",
"//internal/base",
"//internal/platform:logging",
"@com_google_absl//absl/functional:any_invocable",
"@com_google_absl//absl/strings",
],
)
cc_library(
name = "fake_fast_pair_ui",
hdrs = [
"fast_pair/fake_fast_pair_notification_controller_observer.h",
"fast_pair/fake_fast_pair_presenter.h",
],
visibility = [
"//fastpair:__subpackages__",
],
deps = [
":fast_pair_ui",
"//fastpair/repository",
],
)
cc_test(
name = "fast_pair_ui_test",
srcs = [
"fast_pair/fast_pair_notification_controller_test.cc",
"fast_pair/fast_pair_presenter_impl_test.cc",
"ui_broker_impl_test.cc",
],
deps = [
":fake_fast_pair_ui",
":fast_pair_ui",
"//fastpair/common",
"//fastpair/proto:fastpair_cc_proto",
"//fastpair/repository",
"//fastpair/server_access:test_support",
"//internal/network:types",
"//internal/platform/implementation/g3",
"@com_github_protobuf_matchers//protobuf-matchers",
"@com_google_googletest//:gtest_main",
],
)
+32
View File
@@ -0,0 +1,32 @@
// Copyright 2023 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 THIRD_PARTY_NEARBY_FASTPAIR_UI_ACTIONS_H_
#define THIRD_PARTY_NEARBY_FASTPAIR_UI_ACTIONS_H_
namespace nearby {
namespace fastpair {
enum class DiscoveryAction {
kPairToDevice = 0,
kDismissedByUser = 1,
kDismissedByOs = 2,
kLearnMore = 3,
kDismissedByTimeout = 4,
};
} // namespace fastpair
} // namespace nearby
#endif // THIRD_PARTY_NEARBY_FASTPAIR_UI_ACTIONS_H_
@@ -17,6 +17,8 @@
#include <memory>
#include "fastpair/ui/actions.h"
#include "fastpair/ui/fast_pair/fast_pair_notification_controller.h"
#include "fastpair/ui/fast_pair/fast_pair_presenter_impl.h"
namespace nearby {
@@ -24,10 +26,11 @@ namespace fastpair {
class FakeFastPairPresenter : public FastPairPresenter {
public:
void ShowDiscovery(
const FastPairDevice& device,
FastPairNotificationController& notification_controller) override {
void ShowDiscovery(const FastPairDevice& device,
FastPairNotificationController& notification_controller,
DiscoveryCallback callback) override {
show_discovery_ = true;
callback(DiscoveryAction::kPairToDevice);
}
bool show_deiscovery() { return show_discovery_; }
@@ -14,7 +14,13 @@
#include "fastpair/ui/fast_pair/fast_pair_notification_controller.h"
#include <utility>
#include "absl/functional/any_invocable.h"
#include "fastpair/repository/device_metadata.h"
#include "fastpair/ui/actions.h"
#include "internal/platform/logging.h"
namespace nearby {
namespace fastpair {
void FastPairNotificationController::AddObserver(Observer* observer) {
@@ -33,9 +39,19 @@ void FastPairNotificationController::NotifyShowDiscovery(
}
void FastPairNotificationController::ShowGuestDiscoveryNotification(
const DeviceMetadata& device) {
const DeviceMetadata& device, DiscoveryCallback callback) {
callback_ = std::move(callback);
NEARBY_LOGS(INFO) << __func__ << "Notify show guest discovery notification. ";
NotifyShowDiscovery(device);
}
void FastPairNotificationController::OnDiscoveryClicked(
DiscoveryAction action) {
NEARBY_LOGS(INFO) << __func__
<< "Discovery action button is clicked in the app.";
DCHECK(callback_);
callback_(action);
}
} // namespace fastpair
} // namespace nearby
@@ -18,17 +18,19 @@
#include "absl/functional/any_invocable.h"
#include "absl/strings/string_view.h"
#include "fastpair/repository/device_metadata.h"
#include "fastpair/ui/actions.h"
#include "internal/base/observer_list.h"
namespace nearby {
namespace fastpair {
using RepeatingClosure = absl::AnyInvocable<void()>;
using DiscoveryCallback = absl::AnyInvocable<void(DiscoveryAction) const>;
enum class FastPairNotificationDismissReason {
kDismissedByUser,
kDismissedByOs,
kDismissedByTimeout,
};
// This controller creates and manages messages for each FastPair corresponding
// notification event.
class FastPairNotificationController {
@@ -52,9 +54,14 @@ class FastPairNotificationController {
void NotifyShowDiscovery(const DeviceMetadata& device);
// Creates and displays corresponding notification.
void ShowGuestDiscoveryNotification(const DeviceMetadata& device_metadata);
void ShowGuestDiscoveryNotification(const DeviceMetadata& device_metadata,
DiscoveryCallback callback);
// Triggers callback when the related action is clicked.
void OnDiscoveryClicked(DiscoveryAction action);
private:
DiscoveryCallback callback_;
ObserverList<Observer> observers_;
};
} // namespace fastpair
@@ -14,15 +14,15 @@
#include "fastpair/ui/fast_pair/fast_pair_notification_controller.h"
#include <algorithm>
#include <memory>
#include <string>
#include <vector>
#include <utility>
#include <memory>
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
#include "fastpair/repository/device_metadata.h"
#include "fastpair/ui/actions.h"
#include "fastpair/ui/fast_pair/fake_fast_pair_notification_controller_observer.h"
namespace nearby {
@@ -39,12 +39,19 @@ class FastPairNotificationControllerTest : public ::testing::Test {
notification_controller_.AddObserver(&notification_controller_obsesrver_);
}
void TriggerOnUpdateDevice(DeviceMetadata& device) {
notification_controller_.ShowGuestDiscoveryNotification(device);
void TriggerOnUpdateDevice(DeviceMetadata& device,
DiscoveryCallback callback) {
notification_controller_.ShowGuestDiscoveryNotification(
device, std::move(callback));
}
void DiscoveryActionClicked(DiscoveryAction action) {
discovery_action_ = action;
}
FastPairNotificationController notification_controller_;
FakeFastPairNotificationControllerObserver notification_controller_obsesrver_;
DiscoveryAction discovery_action_;
};
TEST_F(FastPairNotificationControllerTest, ShowGuestDiscoveryNotification) {
@@ -52,10 +59,14 @@ TEST_F(FastPairNotificationControllerTest, ShowGuestDiscoveryNotification) {
response.mutable_device()->set_id(kDeviceId);
response.mutable_device()->set_name(kDeviceName);
DeviceMetadata device_metadata(response);
TriggerOnUpdateDevice(device_metadata);
TriggerOnUpdateDevice(device_metadata, [this](DiscoveryAction action) {
DiscoveryActionClicked(action);
});
EXPECT_TRUE(notification_controller_obsesrver_
.CheckDeviceMetadataListContainTestDevice(kDeviceName));
EXPECT_EQ(1, notification_controller_obsesrver_.on_update_device_count());
notification_controller_.OnDiscoveryClicked(DiscoveryAction::kPairToDevice);
EXPECT_EQ(DiscoveryAction::kPairToDevice, discovery_action_);
}
} // namespace
+6 -1
View File
@@ -15,7 +15,11 @@
#ifndef THIRD_PARTY_NEARBY_FASTPAIR_UI_FAST_PAIR_FAST_PAIR_PRESENTER_H_
#define THIRD_PARTY_NEARBY_FASTPAIR_UI_FAST_PAIR_FAST_PAIR_PRESENTER_H_
#include <functional>
#include "absl/functional/any_invocable.h"
#include "fastpair/common/fast_pair_device.h"
#include "fastpair/ui/actions.h"
#include "fastpair/ui/fast_pair/fast_pair_notification_controller.h"
namespace nearby {
@@ -27,7 +31,8 @@ class FastPairPresenter {
// observer_list of notification_controller is updated
virtual void ShowDiscovery(
const FastPairDevice& device,
FastPairNotificationController& notification_controller) = 0;
FastPairNotificationController& notification_controller,
DiscoveryCallback callback) = 0;
virtual ~FastPairPresenter() = default;
};
@@ -15,10 +15,13 @@
#include "fastpair/ui/fast_pair/fast_pair_presenter_impl.h"
#include <memory>
#include <utility>
#include "absl/functional/any_invocable.h"
#include "absl/strings/string_view.h"
#include "fastpair/repository/device_metadata.h"
#include "fastpair/server_access/fast_pair_repository.h"
#include "fastpair/ui/actions.h"
#include "fastpair/ui/fast_pair/fast_pair_notification_controller.h"
#include "internal/platform/logging.h"
@@ -47,22 +50,24 @@ FastPairPresenterImpl::Factory::~Factory() = default;
void FastPairPresenterImpl::ShowDiscovery(
const FastPairDevice& device,
FastPairNotificationController& notification_controller) {
FastPairNotificationController& notification_controller,
DiscoveryCallback callback) {
callback_ = std::move(callback);
FastPairRepository::Get()->GetDeviceMetadata(
device.GetModelId(),
[&notification_controller, this](const DeviceMetadata& device_metadata) {
device.GetModelId(), [&device, &notification_controller,
this](const DeviceMetadata& device_metadata) {
NEARBY_LOGS(INFO) << __func__
<< "Retrieved metadata to notification controller.";
FastPairPresenterImpl::OnDiscoveryMetadataRetrieved(
device_metadata, notification_controller);
OnDiscoveryMetadataRetrieved(device, device_metadata,
notification_controller);
});
}
void FastPairPresenterImpl::OnDiscoveryMetadataRetrieved(
const DeviceMetadata& device_metadata,
const FastPairDevice& device, const DeviceMetadata& device_metadata,
FastPairNotificationController& notification_controller) {
notification_controller.ShowGuestDiscoveryNotification(device_metadata);
notification_controller.ShowGuestDiscoveryNotification(device_metadata,
std::move(callback_));
}
} // namespace fastpair
} // namespace nearby
@@ -19,6 +19,7 @@
#include "fastpair/common/fast_pair_device.h"
#include "fastpair/repository/device_metadata.h"
#include "fastpair/ui/actions.h"
#include "fastpair/ui/fast_pair/fast_pair_notification_controller.h"
#include "fastpair/ui/fast_pair/fast_pair_presenter.h"
@@ -45,15 +46,16 @@ class FastPairPresenterImpl : public FastPairPresenter {
FastPairPresenterImpl(const FastPairPresenterImpl&) = delete;
FastPairPresenterImpl& operator=(const FastPairPresenterImpl&) = delete;
void ShowDiscovery(
const FastPairDevice& device,
FastPairNotificationController& notification_controller) override;
void ShowDiscovery(const FastPairDevice& device,
FastPairNotificationController& notification_controller,
DiscoveryCallback callback) override;
private:
// observer_list of notification_controller is updated
void OnDiscoveryMetadataRetrieved(
const DeviceMetadata& device_metadata,
const FastPairDevice& device, const DeviceMetadata& device_metadata,
FastPairNotificationController& notification_controller);
DiscoveryCallback callback_;
};
} // namespace fastpair
} // namespace nearby
@@ -22,9 +22,9 @@
#include "fastpair/common/fast_pair_device.h"
#include "fastpair/proto/fastpair_rpcs.proto.h"
#include "fastpair/server_access/fake_fast_pair_repository.h"
#include "fastpair/ui/actions.h"
#include "fastpair/ui/fast_pair/fake_fast_pair_notification_controller_observer.h"
#include "fastpair/ui/fast_pair/fast_pair_notification_controller.h"
#include "fastpair/ui/fast_pair/fast_pair_presenter.h"
namespace nearby {
namespace fastpair {
@@ -42,7 +42,11 @@ class FastPairPresenterImplTest : public ::testing::Test {
controller_.AddObserver(&notification_controller_observer_);
}
void OnDiscoveryAction(DiscoveryAction action) { discovery_action_ = action; }
protected:
DiscoveryAction discovery_action_;
FakeFastPairRepository repository_;
FastPairPresenterImpl fast_pair_presenter_;
FastPairNotificationController controller_;
@@ -54,8 +58,12 @@ TEST_F(FastPairPresenterImplTest, ShowDiscovery) {
Protocol::kFastPairInitialPairing);
EXPECT_EQ(0, notification_controller_observer_.on_update_device_count());
fast_pair_presenter_.ShowDiscovery(device, controller_);
fast_pair_presenter_.ShowDiscovery(
device, controller_,
[this](DiscoveryAction action) { OnDiscoveryAction(action); });
EXPECT_EQ(1, notification_controller_observer_.on_update_device_count());
controller_.OnDiscoveryClicked(DiscoveryAction::kPairToDevice);
EXPECT_EQ(DiscoveryAction::kPairToDevice, discovery_action_);
}
} // namespace
} // namespace fastpair
+50
View File
@@ -0,0 +1,50 @@
// Copyright 2023 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 THIRD_PARTY_NEARBY_FASTPAIR_UI_UI_BROKER_H_
#define THIRD_PARTY_NEARBY_FASTPAIR_UI_UI_BROKER_H_
#include "fastpair/common/fast_pair_device.h"
#include "fastpair/ui/actions.h"
#include "fastpair/ui/fast_pair/fast_pair_notification_controller.h"
namespace nearby {
namespace fastpair {
// The UIBroker is the entry point for the UI component in the FastPair system.
// It is responsible for brokering the 'show UI' calls to the correct Presenter
// implementation, and exposing user actions taken on that UI.
class UIBroker {
public:
class Observer {
public:
virtual ~Observer() = default;
virtual void OnDiscoveryAction(const FastPairDevice& device,
DiscoveryAction action) = 0;
};
virtual ~UIBroker() = default;
virtual void AddObserver(Observer* observer) = 0;
virtual void RemoveObserver(Observer* observer) = 0;
virtual void ShowDiscovery(
const FastPairDevice& device,
FastPairNotificationController& notification_controller) = 0;
};
} // namespace fastpair
} // namespace nearby
#endif // THIRD_PARTY_NEARBY_FASTPAIR_UI_UI_BROKER_H_
+69
View File
@@ -0,0 +1,69 @@
// Copyright 2023 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 "fastpair/ui/ui_broker_impl.h"
#include <memory>
#include "fastpair/common/fast_pair_device.h"
#include "fastpair/common/protocol.h"
#include "fastpair/ui/actions.h"
#include "fastpair/ui/fast_pair/fast_pair_presenter.h"
#include "fastpair/ui/fast_pair/fast_pair_presenter_impl.h"
#include "internal/platform/logging.h"
namespace nearby {
namespace fastpair {
UIBrokerImpl::UIBrokerImpl()
: fast_pair_presenter_(FastPairPresenterImpl::Factory::Create()) {}
void UIBrokerImpl::AddObserver(Observer* observer) {
observers_.AddObserver(observer);
}
void UIBrokerImpl::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer);
}
void UIBrokerImpl::ShowDiscovery(
const FastPairDevice& device,
FastPairNotificationController& notification_controller) {
switch (device.GetProtocol()) {
case Protocol::kFastPairInitialPairing:
case Protocol::kFastPairSubsequentPairing:
fast_pair_presenter_->ShowDiscovery(
device, notification_controller,
[&device, this](DiscoveryAction action) {
NEARBY_LOGS(INFO)
<< __func__ << ": Notify discovery action to all observers.";
NotifyDiscoveryAction(device, action);
});
break;
case Protocol::kFastPairRetroactivePairing:
NEARBY_LOGS(ERROR)
<< __func__
<< ": Retroactive Pairing should not show discovery Halfsheet.";
break;
}
}
void UIBrokerImpl::NotifyDiscoveryAction(const FastPairDevice& device,
DiscoveryAction action) {
for (auto& observer : observers_.GetObservers())
observer->OnDiscoveryAction(device, action);
}
} // namespace fastpair
} // namespace nearby
+52
View File
@@ -0,0 +1,52 @@
// Copyright 2023 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 THIRD_PARTY_NEARBY_FASTPAIR_UI_BROKER_IMPL_H_
#define THIRD_PARTY_NEARBY_FASTPAIR_UI_BROKER_IMPL_H_
#include <memory>
#include "fastpair/common/fast_pair_device.h"
#include "fastpair/ui/actions.h"
#include "fastpair/ui/fast_pair/fast_pair_presenter.h"
#include "fastpair/ui/ui_broker.h"
#include "internal/base/observer_list.h"
namespace nearby {
namespace fastpair {
class UIBrokerImpl : public UIBroker {
public:
UIBrokerImpl();
UIBrokerImpl(const UIBrokerImpl &) = delete;
UIBrokerImpl &operator=(const UIBrokerImpl &) = delete;
void AddObserver(Observer *observer) override;
void RemoveObserver(Observer *observer) override;
void ShowDiscovery(
const FastPairDevice &device,
FastPairNotificationController &notification_controller) override;
private:
void NotifyDiscoveryAction(const FastPairDevice &device,
DiscoveryAction action);
std::unique_ptr<FastPairPresenter> fast_pair_presenter_;
ObserverList<Observer> observers_;
};
} // namespace fastpair
} // namespace nearby
#endif // THIRD_PARTY_NEARBY_FASTPAIR_UI_BROKER_IMPL_H_
+76
View File
@@ -0,0 +1,76 @@
// Copyright 2023 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 "fastpair/ui/ui_broker_impl.h"
#include <memory>
#include <string>
#include "gtest/gtest.h"
#include "fastpair/ui/actions.h"
#include "fastpair/ui/fast_pair/fake_fast_pair_presenter.h"
#include "fastpair/ui/fast_pair/fast_pair_notification_controller.h"
#include "fastpair/ui/ui_broker.h"
namespace nearby {
namespace fastpair {
namespace {
constexpr absl::string_view kModelId = "718C17";
constexpr absl::string_view kAddress = "74:74:46:01:6C:21";
class UIBrokerImplTest : public ::testing::Test, public UIBroker::Observer {
protected:
UIBrokerImplTest() {
presenter_factory_ = std::make_unique<FakeFastPairPresenterFactory>();
FastPairPresenterImpl::Factory::SetFactoryForTesting(
presenter_factory_.get());
ui_broker_ = std::make_unique<UIBrokerImpl>();
ui_broker_->AddObserver(this);
}
void OnDiscoveryAction(const FastPairDevice& device,
DiscoveryAction action) override {
on_discovery_action_notified_ = true;
discovery_action_ = action;
}
std::unique_ptr<UIBroker> ui_broker_;
FastPairNotificationController notification_controller_;
std::unique_ptr<FakeFastPairPresenterFactory> presenter_factory_;
DiscoveryAction discovery_action_;
bool on_discovery_action_notified_ = false;
};
TEST_F(UIBrokerImplTest, ShowDiscovery) {
FastPairDevice device(kModelId, kAddress, Protocol::kFastPairInitialPairing);
ui_broker_->ShowDiscovery(device, notification_controller_);
EXPECT_TRUE(
presenter_factory_->fake_fast_pair_presenter()->show_deiscovery());
EXPECT_TRUE(on_discovery_action_notified_);
EXPECT_EQ(DiscoveryAction::kPairToDevice, discovery_action_);
}
TEST_F(UIBrokerImplTest, ShowDiscoveryWithoutObserver) {
FastPairDevice device(kModelId, kAddress, Protocol::kFastPairInitialPairing);
ui_broker_->RemoveObserver(this);
ui_broker_->ShowDiscovery(device, notification_controller_);
EXPECT_TRUE(
presenter_factory_->fake_fast_pair_presenter()->show_deiscovery());
EXPECT_FALSE(on_discovery_action_notified_);
}
} // namespace
} // namespace fastpair
} // namespace nearby
+1 -3
View File
@@ -12,9 +12,8 @@ cc_library(
],
visibility = [
"//fastpair:__subpackages__",
"//internal:__pkg__",
"//internal/interop:__pkg__",
"//internal/platform:__pkg__",
"//location/nearby/cpp/fastpair:__subpackages__",
"//location/nearby/cpp/sharing:__subpackages__",
],
deps = [
@@ -38,7 +37,6 @@ cc_library(
visibility = [
"//fastpair:__subpackages__",
"//internal:__subpackages__",
"//location/nearby/cpp/fastpair:__subpackages__",
"//location/nearby/cpp/sharing:__subpackages__",
],
deps = [
+5
View File
@@ -28,6 +28,11 @@ class ObserverList {
using const_iterator =
typename absl::flat_hash_set<ObserverType*>::const_iterator;
~ObserverList() ABSL_LOCKS_EXCLUDED(mutex_) {
MutexLock lock(&mutex_);
observers_.clear();
}
void AddObserver(ObserverType* observer) ABSL_LOCKS_EXCLUDED(mutex_) {
MutexLock lock(&mutex_);
observers_.insert(observer);
+1
View File
@@ -98,6 +98,7 @@ cc_test(
],
deps = [
":crypto",
"//internal/platform/implementation:types",
"@com_github_protobuf_matchers//protobuf-matchers",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/types:span",
+1 -1
View File
@@ -22,7 +22,7 @@
#include <vector>
#ifdef NEARBY_CHROMIUM
#include "base/check.h"
#include "internal/platform/logging.h"
#elif defined(NEARBY_SWIFTPM)
#include "internal/platform/logging.h"
#else
+1 -1
View File
@@ -24,7 +24,7 @@
#include <vector>
#ifdef NEARBY_CHROMIUM
#include "base/check.h"
#include "internal/platform/logging.h"
#elif defined(NEARBY_SWIFTPM)
#include "internal/platform/logging.h"
#else
+1 -1
View File
@@ -23,7 +23,7 @@
#include <vector>
#ifdef NEARBY_CHROMIUM
#include "base/check.h"
#include "internal/platform/logging.h"
#elif defined(NEARBY_SWIFTPM)
#include "internal/platform/logging.h"
#else
+1 -1
View File
@@ -20,7 +20,7 @@
#include <string>
#ifdef NEARBY_CHROMIUM
#include "base/check.h"
#include "internal/platform/logging.h"
#elif defined(NEARBY_SWIFTPM)
#include "internal/platform/logging.h"
#else
+1 -1
View File
@@ -19,7 +19,7 @@
#include <string>
#ifdef NEARBY_CHROMIUM
#include "base/check.h"
#include "internal/platform/logging.h"
#elif defined(NEARBY_SWIFTPM)
#include "internal/platform/logging.h"
#else
+3 -19
View File
@@ -19,7 +19,9 @@
#include <string>
#ifdef NEARBY_SWIFTPM
#ifdef NEARBY_CHROMIUM
#include "internal/platform/logging.h"
#elif defined(NEARBY_SWIFTPM)
#include "internal/platform/logging.h"
#else
#include "absl/log/log.h" // nogncheck
@@ -30,24 +32,6 @@
namespace crypto {
namespace {
// Callback routine for OpenSSL to print error messages. |str| is a
// NULL-terminated string of length |len| containing diagnostic information
// such as the library, function and reason for the error, the file and line
// where the error originated, plus potentially any context-specific
// information about the error. |context| contains a pointer to user-supplied
// data, which is currently unused.
// If this callback returns a value <= 0, OpenSSL will stop processing the
// error queue and return, otherwise it will continue calling this function
// until all errors have been removed from the queue.
int OpenSSLErrorCallback(const char* str, size_t len, void* context) {
LOG(INFO) << "\t" << absl::string_view(str, len);
return 1;
}
} // namespace
void EnsureOpenSSLInit() {
// CRYPTO_library_init may be safely called concurrently.
CRYPTO_library_init();
-7
View File
@@ -30,11 +30,4 @@ void RandBytes(absl::Span<uint8_t> bytes) {
RandBytes(bytes.data(), bytes.size());
}
std::string RandBytes(size_t length) {
std::string result(length, 0);
RandBytes(const_cast<std::string::value_type *>(result.data()),
result.size());
return result;
}
} // namespace crypto
+4 -12
View File
@@ -12,6 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//*** WARNING!!! Do not add more functions and Data types to this file. ***
// This file needs to be in sync with:
// https://source.chromium.org/chromium/chromium/src/+/main:crypto/random.h
#ifndef THIRD_PARTY_NEARBY_INTERNAL_CRYPTO_RANDOM_H_
#define THIRD_PARTY_NEARBY_INTERNAL_CRYPTO_RANDOM_H_
@@ -32,18 +36,6 @@ CRYPTO_EXPORT void RandBytes(void *bytes, size_t length);
// Fills |bytes| with cryptographically-secure random bits.
CRYPTO_EXPORT void RandBytes(absl::Span<uint8_t> bytes);
// Returns |length| random bytes.
CRYPTO_EXPORT std::string RandBytes(size_t length);
// Creates an object of type T initialized with random data.
// This template should be used for simple data types: int, char, etc.
template <typename T>
T RandData() {
T data;
RandBytes(&data, sizeof(data));
return data;
}
} // namespace crypto
#endif // THIRD_PARTY_NEARBY_INTERNAL_CRYPTO_RANDOM_H_
+5 -3
View File
@@ -20,6 +20,7 @@
#include "gtest/gtest.h"
#include "internal/crypto/nearby_base.h"
#include "internal/platform/implementation/crypto.h"
// Basic functionality tests. Does NOT test the security of the random data.
@@ -46,15 +47,16 @@ TEST(RandBytes, RandBytes) {
TEST(RandBytes, RandomString) {
constexpr size_t kSize = 30;
std::string bytes = RandBytes(kSize);
std::string bytes(kSize, 0);
RandBytes(const_cast<std::string::value_type*>(bytes.data()), bytes.size());
EXPECT_EQ(bytes.size(), kSize);
EXPECT_TRUE(!IsTrivial(bytes));
}
TEST(RandBytes, RandData) {
uint64_t x = RandData<uint64_t>();
uint64_t y = RandData<uint64_t>();
uint64_t x = nearby::RandData<uint64_t>();
uint64_t y = nearby::RandData<uint64_t>();
// Once in a billion years, consecutively generated random numbers will be
// the same and the test will fail.
+1 -1
View File
@@ -17,7 +17,7 @@
#include <memory>
#ifdef NEARBY_CHROMIUM
#include "base/check.h"
#include "internal/platform/logging.h"
#elif defined(NEARBY_SWIFTPM)
#include "internal/platform/logging.h"
#else

Some files were not shown because too many files have changed in this diff Show More