Commit b38f9e32 authored by Kyle Horimoto's avatar Kyle Horimoto Committed by Commit Bot

[CrOS MultiDevice] Implement BleInitiatorOperation.

This operation attempts to connect to a remote device over BLE via the
initiator role via BleConnectionManager.

Bug: 824568, 752273
Change-Id: Ifa3f161f8e0493707be83a217ed8aeb370bfe195
Reviewed-on: https://chromium-review.googlesource.com/1103192
Commit-Queue: Kyle Horimoto <khorimoto@chromium.org>
Reviewed-by: default avatarRyan Hansberry <hansberry@chromium.org>
Cr-Commit-Position: refs/heads/master@{#568263}
parent 0446dd0f
...@@ -4,9 +4,12 @@ ...@@ -4,9 +4,12 @@
#include "chromeos/services/secure_channel/ble_initiator_operation.h" #include "chromeos/services/secure_channel/ble_initiator_operation.h"
#include "base/bind.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/no_destructor.h" #include "base/no_destructor.h"
#include "chromeos/services/secure_channel/ble_connection_manager.h"
#include "chromeos/services/secure_channel/public/cpp/shared/authenticated_channel.h"
namespace chromeos { namespace chromeos {
...@@ -35,6 +38,7 @@ BleInitiatorOperation::Factory::~Factory() = default; ...@@ -35,6 +38,7 @@ BleInitiatorOperation::Factory::~Factory() = default;
std::unique_ptr<ConnectToDeviceOperation<BleInitiatorFailureType>> std::unique_ptr<ConnectToDeviceOperation<BleInitiatorFailureType>>
BleInitiatorOperation::Factory::BuildInstance( BleInitiatorOperation::Factory::BuildInstance(
BleConnectionManager* ble_connection_manager,
ConnectToDeviceOperation<BleInitiatorFailureType>::ConnectionSuccessCallback ConnectToDeviceOperation<BleInitiatorFailureType>::ConnectionSuccessCallback
success_callback, success_callback,
const ConnectToDeviceOperation< const ConnectToDeviceOperation<
...@@ -43,13 +47,12 @@ BleInitiatorOperation::Factory::BuildInstance( ...@@ -43,13 +47,12 @@ BleInitiatorOperation::Factory::BuildInstance(
ConnectionPriority connection_priority, ConnectionPriority connection_priority,
scoped_refptr<base::TaskRunner> task_runner) { scoped_refptr<base::TaskRunner> task_runner) {
return base::WrapUnique(new BleInitiatorOperation( return base::WrapUnique(new BleInitiatorOperation(
std::move(success_callback), std::move(failure_callback), device_id_pair, ble_connection_manager, std::move(success_callback),
connection_priority, task_runner)); std::move(failure_callback), device_id_pair, connection_priority,
task_runner));
} }
BleInitiatorOperation::~BleInitiatorOperation() = default;
BleInitiatorOperation::BleInitiatorOperation( BleInitiatorOperation::BleInitiatorOperation(
BleConnectionManager* ble_connection_manager,
ConnectToDeviceOperation<BleInitiatorFailureType>::ConnectionSuccessCallback ConnectToDeviceOperation<BleInitiatorFailureType>::ConnectionSuccessCallback
success_callback, success_callback,
const ConnectToDeviceOperation< const ConnectToDeviceOperation<
...@@ -62,23 +65,44 @@ BleInitiatorOperation::BleInitiatorOperation( ...@@ -62,23 +65,44 @@ BleInitiatorOperation::BleInitiatorOperation(
std::move(failure_callback), std::move(failure_callback),
device_id_pair, device_id_pair,
connection_priority, connection_priority,
task_runner) {} task_runner),
ble_connection_manager_(ble_connection_manager),
weak_ptr_factory_(this) {}
BleInitiatorOperation::~BleInitiatorOperation() = default;
void BleInitiatorOperation::AttemptConnectionToDevice( void BleInitiatorOperation::AttemptConnectionToDevice(
ConnectionPriority connection_priority) { ConnectionPriority connection_priority) {
// TODO(khorimoto): Implement. is_attempt_active_ = true;
NOTIMPLEMENTED(); ble_connection_manager_->AttemptBleInitiatorConnection(
device_id_pair(), connection_priority,
base::BindOnce(&BleInitiatorOperation::OnSuccessfulConnection,
weak_ptr_factory_.GetWeakPtr()),
base::BindRepeating(&BleInitiatorOperation::OnConnectionFailure,
weak_ptr_factory_.GetWeakPtr()));
} }
void BleInitiatorOperation::PerformCancellation() { void BleInitiatorOperation::PerformCancellation() {
// TODO(khorimoto): Implement. is_attempt_active_ = false;
NOTIMPLEMENTED(); ble_connection_manager_->CancelBleInitiatorConnectionAttempt(
device_id_pair());
} }
void BleInitiatorOperation::PerformUpdateConnectionPriority( void BleInitiatorOperation::PerformUpdateConnectionPriority(
ConnectionPriority connection_priority) { ConnectionPriority connection_priority) {
// TODO(khorimoto): Implement. ble_connection_manager_->UpdateBleInitiatorConnectionPriority(
NOTIMPLEMENTED(); device_id_pair(), connection_priority);
}
void BleInitiatorOperation::OnSuccessfulConnection(
std::unique_ptr<AuthenticatedChannel> authenticated_channel) {
is_attempt_active_ = false;
OnSuccessfulConnectionAttempt(std::move(authenticated_channel));
}
void BleInitiatorOperation::OnConnectionFailure(
BleInitiatorFailureType failure_type) {
OnFailedConnectionAttempt(failure_type);
} }
} // namespace secure_channel } // namespace secure_channel
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <memory> #include <memory>
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "chromeos/services/secure_channel/ble_initiator_failure_type.h" #include "chromeos/services/secure_channel/ble_initiator_failure_type.h"
#include "chromeos/services/secure_channel/connect_to_device_operation.h" #include "chromeos/services/secure_channel/connect_to_device_operation.h"
...@@ -18,6 +19,8 @@ namespace chromeos { ...@@ -18,6 +19,8 @@ namespace chromeos {
namespace secure_channel { namespace secure_channel {
class BleConnectionManager;
// Attempts to connect to a remote device over BLE via the initiator role. // Attempts to connect to a remote device over BLE via the initiator role.
class BleInitiatorOperation class BleInitiatorOperation
: public ConnectToDeviceOperationBase<BleInitiatorFailureType> { : public ConnectToDeviceOperationBase<BleInitiatorFailureType> {
...@@ -28,7 +31,8 @@ class BleInitiatorOperation ...@@ -28,7 +31,8 @@ class BleInitiatorOperation
static void SetFactoryForTesting(Factory* test_factory); static void SetFactoryForTesting(Factory* test_factory);
virtual ~Factory(); virtual ~Factory();
virtual std::unique_ptr<ConnectToDeviceOperation<BleInitiatorFailureType>> virtual std::unique_ptr<ConnectToDeviceOperation<BleInitiatorFailureType>>
BuildInstance(ConnectToDeviceOperation<BleInitiatorFailureType>:: BuildInstance(BleConnectionManager* ble_connection_manager,
ConnectToDeviceOperation<BleInitiatorFailureType>::
ConnectionSuccessCallback success_callback, ConnectionSuccessCallback success_callback,
const ConnectToDeviceOperation<BleInitiatorFailureType>:: const ConnectToDeviceOperation<BleInitiatorFailureType>::
ConnectionFailedCallback& failure_callback, ConnectionFailedCallback& failure_callback,
...@@ -45,6 +49,7 @@ class BleInitiatorOperation ...@@ -45,6 +49,7 @@ class BleInitiatorOperation
private: private:
BleInitiatorOperation( BleInitiatorOperation(
BleConnectionManager* ble_connection_manager,
ConnectToDeviceOperation< ConnectToDeviceOperation<
BleInitiatorFailureType>::ConnectionSuccessCallback success_callback, BleInitiatorFailureType>::ConnectionSuccessCallback success_callback,
const ConnectToDeviceOperation< const ConnectToDeviceOperation<
...@@ -60,6 +65,15 @@ class BleInitiatorOperation ...@@ -60,6 +65,15 @@ class BleInitiatorOperation
void PerformUpdateConnectionPriority( void PerformUpdateConnectionPriority(
ConnectionPriority connection_priority) override; ConnectionPriority connection_priority) override;
void OnSuccessfulConnection(
std::unique_ptr<AuthenticatedChannel> authenticated_channel);
void OnConnectionFailure(BleInitiatorFailureType failure_type);
BleConnectionManager* ble_connection_manager_;
bool is_attempt_active_ = false;
base::WeakPtrFactory<BleInitiatorOperation> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(BleInitiatorOperation); DISALLOW_COPY_AND_ASSIGN(BleInitiatorOperation);
}; };
......
...@@ -6,29 +6,144 @@ ...@@ -6,29 +6,144 @@
#include <memory> #include <memory>
#include "base/bind.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/test/scoped_task_environment.h"
#include "base/test/test_simple_task_runner.h"
#include "chromeos/services/secure_channel/ble_initiator_failure_type.h"
#include "chromeos/services/secure_channel/device_id_pair.h"
#include "chromeos/services/secure_channel/fake_ble_connection_manager.h"
#include "chromeos/services/secure_channel/public/cpp/shared/connection_priority.h"
#include "chromeos/services/secure_channel/public/cpp/shared/fake_authenticated_channel.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
namespace chromeos { namespace chromeos {
namespace secure_channel { namespace secure_channel {
const char kTestRemoteDeviceId[] = "testRemoteDeviceId";
const char kTestLocalDeviceId[] = "testLocalDeviceId";
constexpr const ConnectionPriority kTestConnectionPriority =
ConnectionPriority::kLow;
class SecureChannelBleInitiatorOperationTest : public testing::Test { class SecureChannelBleInitiatorOperationTest : public testing::Test {
protected: protected:
SecureChannelBleInitiatorOperationTest() = default; SecureChannelBleInitiatorOperationTest()
: device_id_pair_(kTestRemoteDeviceId, kTestLocalDeviceId) {}
~SecureChannelBleInitiatorOperationTest() override = default; ~SecureChannelBleInitiatorOperationTest() override = default;
// testing::Test: // testing::Test:
void SetUp() override {} void SetUp() override {
fake_ble_connection_manager_ = std::make_unique<FakeBleConnectionManager>();
auto test_task_runner = base::MakeRefCounted<base::TestSimpleTaskRunner>();
operation_ = BleInitiatorOperation::Factory::Get()->BuildInstance(
fake_ble_connection_manager_.get(),
base::BindOnce(&SecureChannelBleInitiatorOperationTest::
OnSuccessfulConnectionAttempt,
base::Unretained(this)),
base::BindRepeating(
&SecureChannelBleInitiatorOperationTest::OnFailedConnectionAttempt,
base::Unretained(this)),
device_id_pair_, kTestConnectionPriority, test_task_runner);
test_task_runner->RunUntilIdle();
EXPECT_EQ(kTestConnectionPriority,
fake_ble_connection_manager_->GetPriorityForAttempt(
device_id_pair_, ConnectionRole::kInitiatorRole));
}
const DeviceIdPair& device_id_pair() { return device_id_pair_; }
void FailAttempt(BleInitiatorFailureType failure_type) {
fake_ble_connection_manager_->NotifyBleInitiatorFailure(device_id_pair_,
failure_type);
EXPECT_EQ(failure_type, failure_type_from_callback_);
}
void CompleteAttemptSuccessfully() {
auto fake_authenticated_channel =
std::make_unique<FakeAuthenticatedChannel>();
FakeAuthenticatedChannel* fake_authenticated_channel_raw =
fake_authenticated_channel.get();
fake_ble_connection_manager_->NotifyConnectionSuccess(
device_id_pair(), ConnectionRole::kInitiatorRole,
std::move(fake_authenticated_channel));
EXPECT_EQ(fake_authenticated_channel_raw, channel_from_callback_.get());
// The operation should no longer be present in BleConnectionManager.
EXPECT_FALSE(fake_ble_connection_manager()->DoesAttemptExist(
device_id_pair(), ConnectionRole::kInitiatorRole));
}
FakeBleConnectionManager* fake_ble_connection_manager() {
return fake_ble_connection_manager_.get();
}
ConnectToDeviceOperation<BleInitiatorFailureType>* operation() {
return operation_.get();
}
private: private:
std::unique_ptr<BleInitiatorOperation> operation_; void OnSuccessfulConnectionAttempt(
std::unique_ptr<AuthenticatedChannel> authenticated_channel) {
EXPECT_FALSE(channel_from_callback_);
channel_from_callback_ = std::move(authenticated_channel);
}
void OnFailedConnectionAttempt(BleInitiatorFailureType failure_type) {
failure_type_from_callback_ = failure_type;
}
const base::test::ScopedTaskEnvironment scoped_task_environment_;
std::unique_ptr<FakeBleConnectionManager> fake_ble_connection_manager_;
DeviceIdPair device_id_pair_;
std::unique_ptr<AuthenticatedChannel> channel_from_callback_;
base::Optional<BleInitiatorFailureType> failure_type_from_callback_;
std::unique_ptr<ConnectToDeviceOperation<BleInitiatorFailureType>> operation_;
DISALLOW_COPY_AND_ASSIGN(SecureChannelBleInitiatorOperationTest); DISALLOW_COPY_AND_ASSIGN(SecureChannelBleInitiatorOperationTest);
}; };
TEST_F(SecureChannelBleInitiatorOperationTest, Test) { TEST_F(SecureChannelBleInitiatorOperationTest, UpdateThenFail) {
// TODO(khorimoto): Add tests once implementation is complete. operation()->UpdateConnectionPriority(ConnectionPriority::kMedium);
EXPECT_EQ(ConnectionPriority::kMedium,
fake_ble_connection_manager()->GetPriorityForAttempt(
device_id_pair(), ConnectionRole::kInitiatorRole));
static const BleInitiatorFailureType all_types[] = {
BleInitiatorFailureType::kAuthenticationError,
BleInitiatorFailureType::kGattConnectionError,
BleInitiatorFailureType::kInterruptedByHigherPriorityConnectionAttempt,
BleInitiatorFailureType::kTimeoutContactingRemoteDevice,
BleInitiatorFailureType::kCouldNotGenerateAdvertisement};
for (const auto& failure_type : all_types) {
FailAttempt(failure_type);
// After failure, the attempt should still be present in
// BleConnectionManager.
EXPECT_EQ(ConnectionPriority::kMedium,
fake_ble_connection_manager()->GetPriorityForAttempt(
device_id_pair(), ConnectionRole::kInitiatorRole));
}
operation()->Cancel();
EXPECT_FALSE(fake_ble_connection_manager()->DoesAttemptExist(
device_id_pair(), ConnectionRole::kInitiatorRole));
}
TEST_F(SecureChannelBleInitiatorOperationTest, UpdateThenSucceed) {
operation()->UpdateConnectionPriority(ConnectionPriority::kMedium);
EXPECT_EQ(ConnectionPriority::kMedium,
fake_ble_connection_manager()->GetPriorityForAttempt(
device_id_pair(), ConnectionRole::kInitiatorRole));
CompleteAttemptSuccessfully();
} }
} // namespace secure_channel } // namespace secure_channel
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment