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

Commit 43b5bf1c authored by Automerger Merge Worker's avatar Automerger Merge Worker
Browse files

Merge "Propagate connection failures to client" am: 017e56fa

Change-Id: Id5995e906d70dec0d4ecba9b10e22188a9d2aa51
parents 5e206d74 017e56fa
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