From 5bc1c83472d9b445cc6c56b759a2f4ecdb7ffc9f Mon Sep 17 00:00:00 2001 From: hai007 Date: Mon, 25 Mar 2024 15:31:19 -0700 Subject: [PATCH] Pure Refactor: move filtering logic into AdvertisementFilter class - this decouples filtering logic from advertisement decoding logic in preparation for introducing a Rust backed impl of AdvertisementDecoder - this change is only a refactor and does not change functionality in any way PiperOrigin-RevId: 618978564 --- presence/implementation/BUILD | 24 ++++ .../implementation/advertisement_decoder.cc | 89 ------------ .../implementation/advertisement_decoder.h | 11 -- .../advertisement_decoder_test.cc | 95 ------------- .../implementation/advertisement_filter.cc | 97 +++++++++++++ .../implementation/advertisement_filter.h | 45 ++++++ .../advertisement_filter_test.cc | 134 ++++++++++++++++++ presence/implementation/scan_manager.cc | 84 +++++++---- presence/implementation/scan_manager.h | 2 + 9 files changed, 355 insertions(+), 226 deletions(-) create mode 100644 presence/implementation/advertisement_filter.cc create mode 100644 presence/implementation/advertisement_filter.h create mode 100644 presence/implementation/advertisement_filter_test.cc diff --git a/presence/implementation/BUILD b/presence/implementation/BUILD index c5bb96b7..b2011183 100644 --- a/presence/implementation/BUILD +++ b/presence/implementation/BUILD @@ -54,6 +54,7 @@ cc_library( "action_factory.cc", "advertisement_decoder.cc", "advertisement_factory.cc", + "advertisement_filter.cc", "base_broadcast_request.cc", "broadcast_manager.cc", "connection_authenticator_impl.cc", @@ -66,6 +67,7 @@ cc_library( "action_factory.h", "advertisement_decoder.h", "advertisement_factory.h", + "advertisement_filter.h", "base_broadcast_request.h", "broadcast_manager.h", "connection_authenticator.h", @@ -180,6 +182,28 @@ cc_test( }), ) +cc_test( + name = "advertisement_filter_test", + size = "small", + srcs = ["advertisement_filter_test.cc"], + deps = [ + ":internal", + "//internal/platform:base", + "//internal/proto:credential_cc_proto", + "//presence:types", + "@com_github_protobuf_matchers//protobuf-matchers", + "@com_google_absl//absl/strings", + "@com_google_googletest//:gtest_main", + ] + select({ + "@platforms//os:windows": [ + "//internal/platform/implementation/windows", + ], + "//conditions:default": [ + "//internal/platform/implementation/g3", + ], + }), +) + cc_test( name = "advertisement_factory_test", size = "small", diff --git a/presence/implementation/advertisement_decoder.cc b/presence/implementation/advertisement_decoder.cc index 53102ac9..8428fb88 100644 --- a/presence/implementation/advertisement_decoder.cc +++ b/presence/implementation/advertisement_decoder.cc @@ -14,7 +14,6 @@ #include "presence/implementation/advertisement_decoder.h" -#include #include #include #include @@ -154,36 +153,6 @@ absl::StatusOr ParseDataElement(const absl::string_view input, << absl::BytesToHexString(input.substr(start, length)); return DataElement(data_type, input.substr(start, length)); } - -bool Contains(const std::vector& data_elements, - const DataElement& data_element) { - return std::find(data_elements.begin(), data_elements.end(), data_element) != - data_elements.end(); -} - -bool ContainsAll(const std::vector& data_elements, - const std::vector& extended_properties) { - for (const auto& filter_element : extended_properties) { - if (!Contains(data_elements, filter_element)) { - return false; - } - } - return true; -} - -bool ContainsAny(const std::vector& data_elements, - const std::vector& actions) { - if (actions.empty()) { - return true; - } - for (int action : actions) { - if (Contains(data_elements, DataElement(ActionBit(action)))) { - return true; - } - } - return false; -} - } // namespace void AdvertisementDecoder::DecodeBaseAction( @@ -374,63 +343,5 @@ absl::StatusOr AdvertisementDecoder::DecodeAdvertisement( return std::move(decoded_advertisement_); } -bool AdvertisementDecoder::MatchesScanFilter( - const std::vector& data_elements) { - // The advertisement matches the scan request when it matches at least - // one of the filters in the request. - if (scan_request_.scan_filters.empty()) { - return true; - } - for (const auto& filter : scan_request_.scan_filters) { - if (absl::holds_alternative(filter)) { - if (MatchesScanFilter(data_elements, - absl::get(filter))) { - return true; - } - } else if (absl::holds_alternative(filter)) { - if (MatchesScanFilter(data_elements, - absl::get(filter))) { - return true; - } - } - } - return false; -} - -bool AdvertisementDecoder::MatchesScanFilter( - const std::vector& data_elements, - const PresenceScanFilter& filter) { - // The advertisement must contain all Data Elements in scan request. - return ContainsAll(data_elements, filter.extended_properties); -} - -bool AdvertisementDecoder::MatchesScanFilter( - const std::vector& data_elements, - const LegacyPresenceScanFilter& filter) { - // The advertisement must: - // * contain any Action from scan request, - // * contain all Data Elements in scan request. - return ContainsAny(data_elements, filter.actions) && - ContainsAll(data_elements, filter.extended_properties); -} - -std::vector AdvertisementDecoder::GetCredentialSelectors( - const ScanRequest& scan_request) { - std::vector all_types = { - IdentityType::IDENTITY_TYPE_PRIVATE, IdentityType::IDENTITY_TYPE_TRUSTED, - IdentityType::IDENTITY_TYPE_PUBLIC, - IdentityType::IDENTITY_TYPE_PROVISIONED}; - std::vector selectors; - for (auto identity_type : - (scan_request.identity_types.empty() ? all_types - : scan_request.identity_types)) { - selectors.push_back( - CredentialSelector{.manager_app_id = scan_request.manager_app_id, - .account_name = scan_request.account_name, - .identity_type = identity_type}); - } - return selectors; -} - } // namespace presence } // namespace nearby diff --git a/presence/implementation/advertisement_decoder.h b/presence/implementation/advertisement_decoder.h index e4c59dbf..b801ff8c 100644 --- a/presence/implementation/advertisement_decoder.h +++ b/presence/implementation/advertisement_decoder.h @@ -57,19 +57,12 @@ class AdvertisementDecoder { AddBannedDataTypes(); } - static std::vector GetCredentialSelectors( - const ScanRequest& scan_request); - // Returns a list of Data Elements decoded from the advertisement. // Returns an error if the advertisement is misformatted or if it couldn't be // decrypted. absl::StatusOr DecodeAdvertisement( absl::string_view advertisement); - // Returns true if the decoded advertisement in `data_elements` matches the - // filters in `scan_request`. - bool MatchesScanFilter(const std::vector& data_elements); - private: // Decrypts data elements stored inside encrypted `elem` and appends them to // `decoded_advertisement_`. @@ -81,10 +74,6 @@ class AdvertisementDecoder { const std::vector& credentials, absl::string_view salt, absl::string_view data_elements); void AddBannedDataTypes(); - bool MatchesScanFilter(const std::vector& data_elements, - const PresenceScanFilter& filter); - bool MatchesScanFilter(const std::vector& data_elements, - const LegacyPresenceScanFilter& filter); ScanRequest scan_request_; absl::flat_hash_map>* diff --git a/presence/implementation/advertisement_decoder_test.cc b/presence/implementation/advertisement_decoder_test.cc index 8b532ef7..f3cf9793 100644 --- a/presence/implementation/advertisement_decoder_test.cc +++ b/presence/implementation/advertisement_decoder_test.cc @@ -329,101 +329,6 @@ TEST(AdvertisementDecoder, UnsupportedAdvertisementVersion) { StatusIs(absl::StatusCode::kUnimplemented)); } -TEST(AdvertisementDecoder, MatchesScanFilterNoFilterPasses) { - std::vector adv = { - DataElement(DataElement::kPrivateIdentityFieldType, "payload")}; - ScanRequest empty_scan_request = {}; - AdvertisementDecoder decoder(empty_scan_request); - - // A scan request without scan filters matches any advertisement - EXPECT_TRUE(decoder.MatchesScanFilter( - {DataElement(DataElement::kPrivateIdentityFieldType, "payload")})); - EXPECT_TRUE(decoder.MatchesScanFilter({})); -} - -TEST(AdvertisementDecoder, MatchesPresenceScanFilter) { - std::vector adv = { - DataElement(DataElement::kPrivateIdentityFieldType, "payload")}; - DataElement model_id = - DataElement(DataElement::kModelIdFieldType, "model id"); - DataElement salt = DataElement(DataElement::kSaltFieldType, "salt"); - DataElement salt2 = DataElement(DataElement::kSaltFieldType, "salt 2"); - PresenceScanFilter filter = {.extended_properties = {model_id, salt}}; - - AdvertisementDecoder decoder( - - ScanRequestBuilder().AddScanFilter(filter).Build()); - - EXPECT_FALSE(decoder.MatchesScanFilter({})); - EXPECT_FALSE(decoder.MatchesScanFilter({salt})); - EXPECT_TRUE(decoder.MatchesScanFilter({salt, model_id})); - EXPECT_TRUE(decoder.MatchesScanFilter({salt, salt2, model_id})); - EXPECT_FALSE(decoder.MatchesScanFilter({salt2, model_id})); -} - -TEST(AdvertisementDecoder, MatchesLegacyPresenceScanFilter) { - std::vector adv = { - DataElement(DataElement::kPrivateIdentityFieldType, "payload")}; - DataElement model_id = - DataElement(DataElement::kModelIdFieldType, "model id"); - DataElement salt = DataElement(DataElement::kSaltFieldType, "salt"); - DataElement salt2 = DataElement(DataElement::kSaltFieldType, "salt 2"); - LegacyPresenceScanFilter filter = {.extended_properties = {model_id, salt}}; - - AdvertisementDecoder decoder( - - ScanRequestBuilder().AddScanFilter(filter).Build()); - - EXPECT_FALSE(decoder.MatchesScanFilter({})); - EXPECT_FALSE(decoder.MatchesScanFilter({salt})); - EXPECT_TRUE(decoder.MatchesScanFilter({salt, model_id})); - EXPECT_TRUE(decoder.MatchesScanFilter({salt, salt2, model_id})); - EXPECT_FALSE(decoder.MatchesScanFilter({salt2, model_id})); -} - -TEST(AdvertisementDecoder, MatchesLegacyPresenceScanFilterWithActions) { - std::vector adv = { - DataElement(DataElement::kPrivateIdentityFieldType, "payload")}; - DataElement model_id = - DataElement(DataElement::kModelIdFieldType, "model id"); - DataElement salt = DataElement(DataElement::kSaltFieldType, "salt"); - DataElement ttt_action = DataElement(ActionBit::kTapToTransferAction); - LegacyPresenceScanFilter filter = { - .actions = {static_cast(ActionBit::kActiveUnlockAction), - static_cast(ActionBit::kTapToTransferAction)}, - .extended_properties = {model_id, salt}}; - - AdvertisementDecoder decoder( - - ScanRequestBuilder().AddScanFilter(filter).Build()); - - EXPECT_FALSE(decoder.MatchesScanFilter({salt, model_id})); - EXPECT_TRUE(decoder.MatchesScanFilter({salt, ttt_action, model_id})); -} - -TEST(AdvertisementDecoder, MatchesMultipleFilters) { - std::vector adv = { - DataElement(DataElement::kPrivateIdentityFieldType, "payload")}; - DataElement model_id = - DataElement(DataElement::kModelIdFieldType, "model id"); - DataElement salt = DataElement(DataElement::kSaltFieldType, "salt"); - DataElement ttt_action = DataElement(ActionBit::kTapToTransferAction); - PresenceScanFilter presence_filter = {.extended_properties = {model_id}}; - LegacyPresenceScanFilter legacy_filter = { - .actions = {static_cast(ActionBit::kActiveUnlockAction), - static_cast(ActionBit::kTapToTransferAction)}, - .extended_properties = {salt}}; - - AdvertisementDecoder decoder(ScanRequestBuilder() - .AddScanFilter(presence_filter) - .AddScanFilter(legacy_filter) - .Build()); - - EXPECT_TRUE(decoder.MatchesScanFilter({model_id})); - EXPECT_TRUE(decoder.MatchesScanFilter({salt, ttt_action})); - EXPECT_FALSE(decoder.MatchesScanFilter({ttt_action})); -} - } // namespace } // namespace presence } // namespace nearby diff --git a/presence/implementation/advertisement_filter.cc b/presence/implementation/advertisement_filter.cc new file mode 100644 index 00000000..4bf0c1ba --- /dev/null +++ b/presence/implementation/advertisement_filter.cc @@ -0,0 +1,97 @@ +// Copyright 2024 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 "presence/implementation/advertisement_filter.h" + +#include +#include + +#include "absl/types/variant.h" +#include "presence/data_element.h" +#include "presence/scan_request.h" + +namespace nearby { +namespace presence { + +bool Contains(const std::vector& data_elements, + const DataElement& data_element) { + return std::find(data_elements.begin(), data_elements.end(), data_element) != + data_elements.end(); +} + +bool ContainsAll(const std::vector& data_elements, + const std::vector& extended_properties) { + for (const auto& filter_element : extended_properties) { + if (!Contains(data_elements, filter_element)) { + return false; + } + } + return true; +} + +bool ContainsAny(const std::vector& data_elements, + const std::vector& actions) { + if (actions.empty()) { + return true; + } + for (int action : actions) { + if (Contains(data_elements, DataElement(ActionBit(action)))) { + return true; + } + } + return false; +} + +bool AdvertisementFilter::MatchesScanFilter( + const std::vector& data_elements) { + // The advertisement matches the scan request when it matches at least + // one of the filters in the request. + if (scan_request_.scan_filters.empty()) { + return true; + } + for (const auto& filter : scan_request_.scan_filters) { + if (absl::holds_alternative(filter)) { + if (MatchesScanFilter(data_elements, + absl::get(filter))) { + return true; + } + } else if (absl::holds_alternative(filter)) { + if (MatchesScanFilter(data_elements, + absl::get(filter))) { + return true; + } + } + } + return false; +} + +bool AdvertisementFilter::MatchesScanFilter( + const std::vector& data_elements, + const PresenceScanFilter& filter) { + // The advertisement must contain all Data Elements in scan request. + return ContainsAll(data_elements, filter.extended_properties); +} + +bool AdvertisementFilter::MatchesScanFilter( + const std::vector& data_elements, + const LegacyPresenceScanFilter& filter) { + // The advertisement must: + // * contain any Action from scan request, + // * contain all Data Elements in scan request. + return ContainsAny(data_elements, filter.actions) && + ContainsAll(data_elements, filter.extended_properties); +} + +} // namespace presence +} // namespace nearby diff --git a/presence/implementation/advertisement_filter.h b/presence/implementation/advertisement_filter.h new file mode 100644 index 00000000..a70bd8f2 --- /dev/null +++ b/presence/implementation/advertisement_filter.h @@ -0,0 +1,45 @@ +// Copyright 2024 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_PRESENCE_IMPLEMENTATION_ADVERTISEMENT_FILTER_H_ +#define THIRD_PARTY_NEARBY_PRESENCE_IMPLEMENTATION_ADVERTISEMENT_FILTER_H_ + +#include + +#include "presence/data_element.h" +#include "presence/scan_request.h" + +namespace nearby { +namespace presence { +class AdvertisementFilter { + public: + explicit AdvertisementFilter(ScanRequest scan_request) + : scan_request_(scan_request) {} + + // Returns true if the decoded advertisement in `data_elements` matches the + // filters in `scan_request`. + bool MatchesScanFilter(const std::vector& data_elements); + + private: + bool MatchesScanFilter(const std::vector& data_elements, + const PresenceScanFilter& filter); + bool MatchesScanFilter(const std::vector& data_elements, + const LegacyPresenceScanFilter& filter); + ScanRequest scan_request_; +}; + +} // namespace presence +} // namespace nearby + +#endif // THIRD_PARTY_NEARBY_PRESENCE_IMPLEMENTATION_ADVERTISEMENT_FILTER_H_ diff --git a/presence/implementation/advertisement_filter_test.cc b/presence/implementation/advertisement_filter_test.cc new file mode 100644 index 00000000..9ff7fc5e --- /dev/null +++ b/presence/implementation/advertisement_filter_test.cc @@ -0,0 +1,134 @@ +// Copyright 2024 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 "presence/implementation/advertisement_filter.h" + +#include +#include +#include + +#include "gmock/gmock.h" +#include "protobuf-matchers/protocol-buffer-matchers.h" +#include "gtest/gtest.h" +#include "absl/strings/escaping.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" +#include "internal/platform/byte_array.h" +#include "internal/proto/credential.pb.h" +#include "presence/data_element.h" +#include "presence/scan_request.h" +#include "presence/scan_request_builder.h" + +namespace nearby { +namespace presence { +namespace { + +TEST(AdvertisementFilter, MatchesScanFilterNoFilterPasses) { + std::vector adv = { + DataElement(DataElement::kPrivateIdentityFieldType, "payload")}; + ScanRequest empty_scan_request = {}; + AdvertisementFilter adv_filter(empty_scan_request); + + // A scan request without scan filters matches any advertisement + EXPECT_TRUE(adv_filter.MatchesScanFilter( + {DataElement(DataElement::kPrivateIdentityFieldType, "payload")})); + EXPECT_TRUE(adv_filter.MatchesScanFilter({})); +} + +TEST(AdvertisementFilter, MatchesPresenceScanFilter) { + std::vector adv = { + DataElement(DataElement::kPrivateIdentityFieldType, "payload")}; + DataElement model_id = + DataElement(DataElement::kModelIdFieldType, "model id"); + DataElement salt = DataElement(DataElement::kSaltFieldType, "salt"); + DataElement salt2 = DataElement(DataElement::kSaltFieldType, "salt 2"); + PresenceScanFilter filter = {.extended_properties = {model_id, salt}}; + + AdvertisementFilter adv_filter( + + ScanRequestBuilder().AddScanFilter(filter).Build()); + + EXPECT_FALSE(adv_filter.MatchesScanFilter({})); + EXPECT_FALSE(adv_filter.MatchesScanFilter({salt})); + EXPECT_TRUE(adv_filter.MatchesScanFilter({salt, model_id})); + EXPECT_TRUE(adv_filter.MatchesScanFilter({salt, salt2, model_id})); + EXPECT_FALSE(adv_filter.MatchesScanFilter({salt2, model_id})); +} + +TEST(AdvertisementFilter, MatchesLegacyPresenceScanFilter) { + std::vector adv = { + DataElement(DataElement::kPrivateIdentityFieldType, "payload")}; + DataElement model_id = + DataElement(DataElement::kModelIdFieldType, "model id"); + DataElement salt = DataElement(DataElement::kSaltFieldType, "salt"); + DataElement salt2 = DataElement(DataElement::kSaltFieldType, "salt 2"); + LegacyPresenceScanFilter filter = {.extended_properties = {model_id, salt}}; + + AdvertisementFilter adv_filter( + + ScanRequestBuilder().AddScanFilter(filter).Build()); + + EXPECT_FALSE(adv_filter.MatchesScanFilter({})); + EXPECT_FALSE(adv_filter.MatchesScanFilter({salt})); + EXPECT_TRUE(adv_filter.MatchesScanFilter({salt, model_id})); + EXPECT_TRUE(adv_filter.MatchesScanFilter({salt, salt2, model_id})); + EXPECT_FALSE(adv_filter.MatchesScanFilter({salt2, model_id})); +} + +TEST(AdvertisementFilter, MatchesLegacyPresenceScanFilterWithActions) { + std::vector adv = { + DataElement(DataElement::kPrivateIdentityFieldType, "payload")}; + DataElement model_id = + DataElement(DataElement::kModelIdFieldType, "model id"); + DataElement salt = DataElement(DataElement::kSaltFieldType, "salt"); + DataElement ttt_action = DataElement(ActionBit::kTapToTransferAction); + LegacyPresenceScanFilter filter = { + .actions = {static_cast(ActionBit::kActiveUnlockAction), + static_cast(ActionBit::kTapToTransferAction)}, + .extended_properties = {model_id, salt}}; + + AdvertisementFilter adv_filter( + + ScanRequestBuilder().AddScanFilter(filter).Build()); + + EXPECT_FALSE(adv_filter.MatchesScanFilter({salt, model_id})); + EXPECT_TRUE(adv_filter.MatchesScanFilter({salt, ttt_action, model_id})); +} + +TEST(AdvertisementFilter, MatchesMultipleFilters) { + std::vector adv = { + DataElement(DataElement::kPrivateIdentityFieldType, "payload")}; + DataElement model_id = + DataElement(DataElement::kModelIdFieldType, "model id"); + DataElement salt = DataElement(DataElement::kSaltFieldType, "salt"); + DataElement ttt_action = DataElement(ActionBit::kTapToTransferAction); + PresenceScanFilter presence_filter = {.extended_properties = {model_id}}; + LegacyPresenceScanFilter legacy_filter = { + .actions = {static_cast(ActionBit::kActiveUnlockAction), + static_cast(ActionBit::kTapToTransferAction)}, + .extended_properties = {salt}}; + + AdvertisementFilter adv_filter(ScanRequestBuilder() + .AddScanFilter(presence_filter) + .AddScanFilter(legacy_filter) + .Build()); + + EXPECT_TRUE(adv_filter.MatchesScanFilter({model_id})); + EXPECT_TRUE(adv_filter.MatchesScanFilter({salt, ttt_action})); + EXPECT_FALSE(adv_filter.MatchesScanFilter({ttt_action})); +} + +} // namespace +} // namespace presence +} // namespace nearby diff --git a/presence/implementation/scan_manager.cc b/presence/implementation/scan_manager.cc index 7aff0cd1..9e0759d7 100644 --- a/presence/implementation/scan_manager.cc +++ b/presence/implementation/scan_manager.cc @@ -28,6 +28,7 @@ #include "internal/platform/implementation/credential_callbacks.h" #include "internal/platform/implementation/crypto.h" #include "internal/platform/uuid.h" +#include "presence//implementation/advertisement_filter.h" #include "presence/data_types.h" #include "presence/implementation/advertisement_decoder.h" #include "presence/implementation/mediums/ble.h" @@ -49,35 +50,36 @@ ScanSessionId ScanManager::StartScan(ScanRequest scan_request, ScanSessionId id = nearby::RandData(); RunOnServiceControllerThread( "start-scan", - [this, id, scan_request, scan_callback = std::move(cb)]() - ABSL_EXCLUSIVE_LOCKS_REQUIRED(*executor_) mutable { - ScanningCallback callback = ScanningCallback{ - .start_scanning_result = - [start_scan_client = - std::move(scan_callback.start_scan_cb)]( - absl::Status ble_status) mutable { - start_scan_client(ble_status); - }, - .advertisement_found_cb = - [this, id](BlePeripheral& peripheral, - BleAdvertisementData data) { - RunOnServiceControllerThread( - "notify-found-ble", - [this, id, data = std::move(data), - address = peripheral.GetAddress()]() - ABSL_EXCLUSIVE_LOCKS_REQUIRED(*executor_) { - NotifyFoundBle(id, data, address); - }); - }}; - FetchCredentials(id, scan_request); - scan_sessions_.insert( - {id, ScanSessionState{ - .request = scan_request, - .callback = std::move(scan_callback), - .decoder = AdvertisementDecoder(scan_request), - .scanning_session = mediums_->GetBle().StartScanning( - scan_request, std::move(callback))}}); - }); + [this, id, scan_request, + scan_callback = + std::move(cb)]() ABSL_EXCLUSIVE_LOCKS_REQUIRED(*executor_) mutable { + ScanningCallback callback = ScanningCallback{ + .start_scanning_result = + [start_scan_client = std::move(scan_callback.start_scan_cb)]( + absl::Status ble_status) mutable { + start_scan_client(ble_status); + }, + .advertisement_found_cb = + [this, id](BlePeripheral& peripheral, + BleAdvertisementData data) { + RunOnServiceControllerThread( + "notify-found-ble", + [this, id, data = std::move(data), + address = peripheral.GetAddress()]() + ABSL_EXCLUSIVE_LOCKS_REQUIRED(*executor_) { + NotifyFoundBle(id, data, address); + }); + }}; + FetchCredentials(id, scan_request); + scan_sessions_.insert( + {id, ScanSessionState{ + .request = scan_request, + .callback = std::move(scan_callback), + .decoder = AdvertisementDecoder(scan_request), + .advertisement_filter = AdvertisementFilter(scan_request), + .scanning_session = mediums_->GetBle().StartScanning( + scan_request, std::move(callback))}}); + }); return id; } @@ -111,7 +113,8 @@ void ScanManager::NotifyFoundBle(ScanSessionId id, BleAdvertisementData data, // This advertisement is not relevant to the current element, skip. return; } - if (it->second.decoder.MatchesScanFilter(advert->data_elements)) { + if (it->second.advertisement_filter.MatchesScanFilter( + advert->data_elements)) { internal::DeviceIdentityMetaData device_identity_metadata; device_identity_metadata.set_bluetooth_mac_address( std::string(remote_address)); @@ -132,10 +135,29 @@ void ScanManager::NotifyFoundBle(ScanSessionId id, BleAdvertisementData data, } } +std::vector GetCredentialSelectors( + const ScanRequest& scan_request) { + std::vector all_types = { + nearby::internal::IdentityType::IDENTITY_TYPE_PRIVATE, + nearby::internal::IdentityType::IDENTITY_TYPE_TRUSTED, + nearby::internal::IdentityType::IDENTITY_TYPE_PUBLIC, + nearby::internal::IdentityType::IDENTITY_TYPE_PROVISIONED}; + std::vector selectors; + for (auto identity_type : + (scan_request.identity_types.empty() ? all_types + : scan_request.identity_types)) { + selectors.push_back( + CredentialSelector{.manager_app_id = scan_request.manager_app_id, + .account_name = scan_request.account_name, + .identity_type = identity_type}); + } + return selectors; +} + void ScanManager::FetchCredentials(ScanSessionId id, const ScanRequest& scan_request) { std::vector credential_selectors = - AdvertisementDecoder::GetCredentialSelectors(scan_request); + GetCredentialSelectors(scan_request); for (const CredentialSelector& selector : credential_selectors) { // Not fetching for PUBLIC. if (selector.identity_type == internal::IDENTITY_TYPE_UNSPECIFIED || diff --git a/presence/implementation/scan_manager.h b/presence/implementation/scan_manager.h index 9262c09b..7eee940b 100644 --- a/presence/implementation/scan_manager.h +++ b/presence/implementation/scan_manager.h @@ -26,6 +26,7 @@ #include "internal/proto/credential.pb.h" #include "presence/data_types.h" #include "presence/implementation/advertisement_decoder.h" +#include "presence/implementation/advertisement_filter.h" #include "presence/implementation/credential_manager.h" #include "presence/implementation/mediums/mediums.h" #include "presence/scan_request.h" @@ -66,6 +67,7 @@ class ScanManager { absl::flat_hash_map> credentials; AdvertisementDecoder decoder; + AdvertisementFilter advertisement_filter; std::unique_ptr scanning_session; }; void NotifyFoundBle(ScanSessionId id, BleAdvertisementData data,