Implement start advertising in service controller.

PiperOrigin-RevId: 489584407
This commit is contained in:
Janusz Sobczak
2022-11-18 16:17:55 -08:00
committed by Copybara-Service
parent d4551b7187
commit a11733988f
6 changed files with 216 additions and 3 deletions
+1
View File
@@ -726,6 +726,7 @@ MediumEnvironment::GetBleV2MediumStatus(const api::ble_v2::BleMedium& medium) {
return;
}
BleV2MediumContext context = it->second;
result = BleV2MediumStatus{.is_advertising = context.advertising,
.is_scanning = context.scanning};
latch.CountDown();
+1 -1
View File
@@ -83,7 +83,7 @@ struct BroadcastSession {
// Nearby library would provide the implementation of this callback in
// runtime. Assiging with a default value NotImplemented to surface potential
// issue where library failed to provide the implementation.
std::function<Status(void)> stop_broadcast_callback = []() {
absl::AnyInvocable<Status(void)> stop_broadcast_callback = []() {
return Status{Status::Value::kNotImplemented};
};
};
+16
View File
@@ -135,6 +135,22 @@ cc_test(
],
)
cc_test(
name = "service_controller_impl_test",
size = "small",
srcs = ["service_controller_impl_test.cc"],
deps = [
":internal",
"//internal/platform:base",
"//internal/platform:test_util",
"//internal/platform:types",
"//internal/platform/implementation/g3", # build_cleaner: keep
"//internal/proto:credential_cc_proto",
"@com_github_protobuf_matchers//protobuf-matchers",
"@com_google_googletest//:gtest_main",
],
)
cc_test(
name = "encryption_test",
size = "small",
@@ -15,18 +15,75 @@
#include "presence/implementation/service_controller_impl.h"
#include <memory>
#include <string>
#include <utility>
#include "absl/status/statusor.h"
#include "internal/platform/implementation/ble_v2.h"
#include "presence/implementation/advertisement_factory.h"
#include "presence/implementation/base_broadcast_request.h"
#include "presence/implementation/mediums/advertisement_data.h"
#include "presence/status.h"
namespace nearby {
namespace presence {
namespace {
using ::location::nearby::api::ble_v2::BleOperationStatus;
using AdvertisingCallback =
::location::nearby::api::ble_v2::BleMedium::AdvertisingCallback;
using AdvertisingSession =
::location::nearby::api::ble_v2::BleMedium::AdvertisingSession;
Status ConvertBleStatus(BleOperationStatus status) {
return status == BleOperationStatus::kSucceeded
? Status{Status::Value::kSuccess}
: Status{Status::Value::kError};
}
} // namespace
std::unique_ptr<ScanSession> ServiceControllerImpl::StartScan(
ScanRequest scan_request, ScanCallback callback) {
return scan_manager_.StartScan(scan_request, callback);
}
std::unique_ptr<BroadcastSession> ServiceControllerImpl::StartBroadcast(
BroadcastRequest broadcast_request, BroadcastCallback callback) {
callback.start_broadcast_cb({Status::Value::kError});
return nullptr;
absl::StatusOr<BaseBroadcastRequest> request =
BaseBroadcastRequest::Create(broadcast_request);
if (!request.ok()) {
NEARBY_LOGS(WARNING) << "Invalid broadcast request, reason: "
<< request.status();
callback.start_broadcast_cb(Status{Status::Value::kError});
return nullptr;
}
absl::StatusOr<AdvertisementData> advertisement =
AdvertisementFactory(&credential_manager_).CreateAdvertisement(*request);
if (!advertisement.ok()) {
NEARBY_LOGS(WARNING) << "Can't create advertisement, reason: "
<< advertisement.status();
callback.start_broadcast_cb(Status{Status::Value::kError});
return nullptr;
}
std::unique_ptr<AdvertisingSession> session =
mediums_.GetBle().StartAdvertising(
*advertisement, broadcast_request.power_mode,
AdvertisingCallback{.start_advertising_result =
[callback](BleOperationStatus status) {
callback.start_broadcast_cb(
ConvertBleStatus(status));
}});
if (!session) {
NEARBY_LOGS(WARNING) << "Failed to start broadcasting";
callback.start_broadcast_cb(Status{Status::Value::kError});
return nullptr;
}
return std::make_unique<BroadcastSession>(BroadcastSession{
.stop_broadcast_callback = [session = std::move(session)]() {
return ConvertBleStatus(session->stop_advertising());
}});
}
} // namespace presence
@@ -39,6 +39,9 @@ class ServiceControllerImpl : public ServiceController {
std::unique_ptr<BroadcastSession> StartBroadcast(
BroadcastRequest broadcast_request, BroadcastCallback callback) override;
// Gives tests access to mediums.
Mediums& GetMediums() { return mediums_; }
private:
Mediums mediums_; // NOLINT: further impl will use it.
CredentialManagerImpl
@@ -0,0 +1,136 @@
// Copyright 2022 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/service_controller_impl.h"
#include <memory>
#include <string>
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
#include "internal/platform/feature_flags.h"
#include "internal/platform/future.h"
#include "internal/platform/medium_environment.h"
#include "internal/proto/credential.pb.h"
namespace nearby {
namespace presence {
namespace {
using FeatureFlags = location::nearby::FeatureFlags::Flags;
using internal::IdentityType;
using location::nearby::MediumEnvironment;
constexpr FeatureFlags kTestCases[] = {
FeatureFlags{},
};
constexpr absl::string_view kAccountName = "Test account";
constexpr int8_t kTxPower = 30;
BroadcastRequest CreateBroadcastRequest(IdentityType identity) {
PresenceBroadcast::BroadcastSection section = {
.identity = identity,
.extended_properties = {DataElement(
DataElement(ActionBit::kActiveUnlockAction))},
.account_name = std::string(kAccountName)};
PresenceBroadcast presence_request = {.sections = {section}};
BroadcastRequest request = {.tx_power = kTxPower,
.variant = presence_request};
return request;
}
class MediumEnvironmentStarter {
public:
MediumEnvironmentStarter() { MediumEnvironment::Instance().Start(); }
~MediumEnvironmentStarter() { MediumEnvironment::Instance().Stop(); }
};
class ServiceControllerImplTest : public testing::TestWithParam<FeatureFlags> {
protected:
// The medium environment must be initialized (started) before the service
// controller.
MediumEnvironmentStarter env_;
ServiceControllerImpl service_controller_;
location::nearby::Future<Status> start_broadcast_status_;
BroadcastCallback broadcast_callback_{
.start_broadcast_cb = [this](Status status) {
start_broadcast_status_.Set(status);
}};
};
INSTANTIATE_TEST_SUITE_P(ParametrisedServiceControllerImplTest,
ServiceControllerImplTest,
testing::ValuesIn(kTestCases));
TEST_P(ServiceControllerImplTest, StartBroadcastPublicIdentity) {
std::unique_ptr<BroadcastSession> session =
service_controller_.StartBroadcast(
CreateBroadcastRequest(internal::IDENTITY_TYPE_PUBLIC),
broadcast_callback_);
EXPECT_TRUE(session);
EXPECT_TRUE(start_broadcast_status_.Get().ok());
EXPECT_EQ(start_broadcast_status_.Get().GetResult(),
Status{Status::Value::kSuccess});
EXPECT_TRUE(MediumEnvironment::Instance()
.GetBleV2MediumStatus(
*service_controller_.GetMediums().GetBle().GetImpl())
->is_advertising);
}
TEST_P(ServiceControllerImplTest, StartAndStopBroadcast) {
std::unique_ptr<BroadcastSession> session =
service_controller_.StartBroadcast(
CreateBroadcastRequest(internal::IDENTITY_TYPE_PUBLIC),
broadcast_callback_);
ASSERT_TRUE(session);
EXPECT_EQ(session->stop_broadcast_callback(),
Status{Status::Value::kSuccess});
MediumEnvironment::Instance().Sync();
EXPECT_FALSE(MediumEnvironment::Instance()
.GetBleV2MediumStatus(
*service_controller_.GetMediums().GetBle().GetImpl())
->is_advertising);
}
TEST_P(ServiceControllerImplTest, StartBroadcastInvalidRequestFails) {
std::unique_ptr<BroadcastSession> session =
service_controller_.StartBroadcast(BroadcastRequest{},
broadcast_callback_);
EXPECT_FALSE(session);
EXPECT_TRUE(start_broadcast_status_.Get().ok());
EXPECT_EQ(start_broadcast_status_.Get().GetResult(),
Status{Status::Value::kError});
}
TEST_P(ServiceControllerImplTest, StartBroadcastPrivateIdentityFails) {
// TODO(b/256249404): Support private identity.
std::unique_ptr<BroadcastSession> session =
service_controller_.StartBroadcast(
CreateBroadcastRequest(internal::IDENTITY_TYPE_PRIVATE),
broadcast_callback_);
EXPECT_FALSE(session);
EXPECT_TRUE(start_broadcast_status_.Get().ok());
EXPECT_EQ(start_broadcast_status_.Get().GetResult(),
Status{Status::Value::kError});
}
} // namespace
} // namespace presence
} // namespace nearby