Implement FastPairHandshakeLookup

PiperOrigin-RevId: 524915633
This commit is contained in:
Qin Wang
2023-04-17 12:19:18 -07:00
committed by Copybara-Service
parent 2e7f7a7d90
commit 74def10d7c
4 changed files with 326 additions and 0 deletions
+23
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__",
@@ -47,9 +49,11 @@ cc_library(
"//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",
],
)
@@ -142,3 +146,22 @@ 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",
"//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",
],
)
@@ -0,0 +1,89 @@
// 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"
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, OnCompleteCallback on_complete) {
absl::MutexLock lock(&mutex_);
auto it = fast_pair_handshakes_.emplace(
&device,
std::make_unique<FastPairHandshakeImpl>(device, std::move(on_complete)));
DCHECK(it.second);
return it.first->second.get();
}
} // 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.
#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"
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,
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,128 @@
// 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 "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#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 "internal/platform/count_down_latch.h"
#include "internal/platform/medium_environment.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);
EXPECT_TRUE(FastPairHandshakeLookup::GetInstance()->Create(
device,
[&](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