Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 017e56fa authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Propagate connection failures to client"

parents df98c010 03214899
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ filegroup {
        "classic/internal/dynamic_channel_service_manager_test.cc",
        "classic/internal/fixed_channel_impl_test.cc",
        "classic/internal/fixed_channel_service_manager_test.cc",
        "classic/internal/link_test.cc",
        "classic/internal/link_manager_test.cc",
        "classic/internal/signalling_manager_test.cc",
        "internal/basic_mode_channel_data_controller_test.cc",
+20 −4
Original line number Diff line number Diff line
@@ -47,8 +47,18 @@ Link::Link(os::Handler* l2cap_handler, std::unique_ptr<hci::AclConnection> acl_c
}

void Link::OnAclDisconnected(hci::ErrorCode status) {
  signalling_manager_.CancelAlarm();
  fixed_channel_allocator_.OnAclDisconnected(status);
  dynamic_channel_allocator_.OnAclDisconnected(status);
  DynamicChannelManager::ConnectionResult result{
      .connection_result_code = DynamicChannelManager::ConnectionResultCode::FAIL_HCI_ERROR,
      .hci_error = status,
      .l2cap_connection_response_result = ConnectionResponseResult::SUCCESS,
  };
  while (!local_cid_to_pending_dynamic_channel_connection_map_.empty()) {
    auto entry = local_cid_to_pending_dynamic_channel_connection_map_.begin();
    NotifyChannelFail(entry->first, result);
  }
}

void Link::Disconnect() {
@@ -96,7 +106,15 @@ void Link::SendConnectionRequest(Psm psm, Cid local_cid,
}

void Link::OnOutgoingConnectionRequestFail(Cid local_cid) {
  local_cid_to_pending_dynamic_channel_connection_map_.erase(local_cid);
  if (local_cid_to_pending_dynamic_channel_connection_map_.find(local_cid) !=
      local_cid_to_pending_dynamic_channel_connection_map_.end()) {
    DynamicChannelManager::ConnectionResult result{
        .connection_result_code = DynamicChannelManager::ConnectionResultCode::FAIL_HCI_ERROR,
        .hci_error = hci::ErrorCode::CONNECTION_TIMEOUT,
        .l2cap_connection_response_result = ConnectionResponseResult::SUCCESS,
    };
    NotifyChannelFail(local_cid, result);
  }
  dynamic_channel_allocator_.FreeChannel(local_cid);
}

@@ -169,12 +187,10 @@ void Link::NotifyChannelCreation(Cid cid, std::unique_ptr<DynamicChannel> user_c
  local_cid_to_pending_dynamic_channel_connection_map_.erase(cid);
}

void Link::NotifyChannelFail(Cid cid) {
void Link::NotifyChannelFail(Cid cid, DynamicChannelManager::ConnectionResult result) {
  ASSERT(local_cid_to_pending_dynamic_channel_connection_map_.find(cid) !=
         local_cid_to_pending_dynamic_channel_connection_map_.end());
  auto& pending_dynamic_channel_connection = local_cid_to_pending_dynamic_channel_connection_map_[cid];
  // TODO(cmanton) Pass proper connection falure result to user
  DynamicChannelManager::ConnectionResult result;
  pending_dynamic_channel_connection.handler_->Post(
      common::BindOnce(std::move(pending_dynamic_channel_connection.on_fail_callback_), result));
  local_cid_to_pending_dynamic_channel_connection_map_.erase(cid);
+1 −1
Original line number Diff line number Diff line
@@ -108,7 +108,7 @@ class Link : public l2cap::internal::ILink {
  virtual void RefreshRefCount();

  virtual void NotifyChannelCreation(Cid cid, std::unique_ptr<DynamicChannel> channel);
  virtual void NotifyChannelFail(Cid cid);
  virtual void NotifyChannelFail(Cid cid, DynamicChannelManager::ConnectionResult result);

  // Information received from signaling channel
  virtual void SetRemoteConnectionlessMtu(Mtu mtu);
+137 −0
Original line number Diff line number Diff line
/*
 * Copyright 2020 The Android Open Source Project
 *
 * 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
 *
 *      http://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 "l2cap/classic/internal/link.h"

#include "hci/acl_manager_mock.h"
#include "hci/address.h"
#include "l2cap/classic/internal/dynamic_channel_service_manager_impl_mock.h"
#include "l2cap/classic/internal/fixed_channel_service_manager_impl_mock.h"
#include "l2cap/internal/parameter_provider_mock.h"

#include <gmock/gmock-nice-strict.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

using ::testing::NiceMock;

namespace bluetooth {
namespace l2cap {
namespace classic {
namespace internal {
namespace {

constexpr Psm kPsm = 123;
constexpr Cid kCid = 456;

using classic::internal::testing::MockDynamicChannelServiceManagerImpl;
using hci::testing::MockAclConnection;
using l2cap::internal::testing::MockParameterProvider;
using testing::MockFixedChannelServiceManagerImpl;

class L2capClassicLinkTest : public ::testing::Test {
 public:
  void OnOpen(std::unique_ptr<DynamicChannel> channel) {
    on_open_promise_.set_value();
  }

  void OnFail(DynamicChannelManager::ConnectionResult result) {
    on_fail_promise_.set_value();
  }

  void OnDequeueCallbackForTest() {
    std::unique_ptr<BasePacketBuilder> data = raw_acl_connection_->acl_queue_.GetDownEnd()->TryDequeue();
    if (data != nullptr) {
      dequeue_promise_.set_value();
    }
  }

  void EnqueueCallbackForTest() {
    raw_acl_connection_->acl_queue_.GetDownEnd()->RegisterDequeue(
        handler_, common::Bind(&L2capClassicLinkTest::OnDequeueCallbackForTest, common::Unretained(this)));
  }

  void DequeueCallback() {
    raw_acl_connection_->acl_queue_.GetDownEnd()->UnregisterDequeue();
  }

 protected:
  void SetUp() override {
    thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL);
    handler_ = new os::Handler(thread_);
    signalling_handler_ = new os::Handler(thread_);

    raw_acl_connection_ = new NiceMock<MockAclConnection>();
    link_ = new Link(signalling_handler_, std::unique_ptr<MockAclConnection>(raw_acl_connection_),
                     &mock_parameter_provider_, &mock_classic_dynamic_channel_service_manager_,
                     &mock_classic_fixed_channel_service_manager_);
  }

  void TearDown() override {
    delete link_;

    signalling_handler_->Clear();
    delete signalling_handler_;

    handler_->Clear();
    delete handler_;

    delete thread_;
  }

  os::Thread* thread_ = nullptr;
  os::Handler* handler_ = nullptr;
  os::Handler* signalling_handler_ = nullptr;

  MockAclConnection* raw_acl_connection_ = nullptr;
  std::unique_ptr<MockAclConnection> acl_connection_;

  NiceMock<MockParameterProvider> mock_parameter_provider_;
  MockFixedChannelServiceManagerImpl mock_classic_fixed_channel_service_manager_;
  MockDynamicChannelServiceManagerImpl mock_classic_dynamic_channel_service_manager_;

  std::promise<void> on_open_promise_;
  std::promise<void> on_fail_promise_;
  std::promise<void> dequeue_promise_;

  Link* link_;
};

TEST_F(L2capClassicLinkTest, pending_channels_get_notified_on_acl_disconnect) {
  EnqueueCallbackForTest();

  Link::PendingDynamicChannelConnection pending_dynamic_channel_connection{
      .handler_ = handler_,
      .on_open_callback_ = common::Bind(&L2capClassicLinkTest::OnOpen, common::Unretained(this)),
      .on_fail_callback_ = common::Bind(&L2capClassicLinkTest::OnFail, common::Unretained(this)),
      .configuration_ = DynamicChannelConfigurationOption(),
  };
  auto future = on_fail_promise_.get_future();

  link_->SendConnectionRequest(kPsm, kCid, std::move(pending_dynamic_channel_connection));
  link_->OnAclDisconnected(hci::ErrorCode::UNKNOWN_HCI_COMMAND);
  future.wait();

  auto dequeue_future = dequeue_promise_.get_future();
  dequeue_future.wait();
  DequeueCallback();
}

}  // namespace
}  // namespace internal
}  // namespace classic
}  // namespace l2cap
}  // namespace bluetooth
+4 −0
Original line number Diff line number Diff line
@@ -111,6 +111,10 @@ void ClassicSignallingManager::SendEchoRequest(std::unique_ptr<packet::RawBuilde
  LOG_WARN("Not supported");
}

void ClassicSignallingManager::CancelAlarm() {
  alarm_.Cancel();
}

void ClassicSignallingManager::OnConnectionRequest(SignalId signal_id, Psm psm, Cid remote_cid) {
  if (!IsPsmValid(psm)) {
    LOG_WARN("Invalid psm received from remote psm:%d remote_cid:%d", psm, remote_cid);
Loading