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

Commit 8c8edf61 authored by Jack He's avatar Jack He
Browse files

Use the same fixed channel allocator for both Classic and LE connections

* Merge identical logic for fixed channel allocation among Classic and
  LE fixed channel connections
* Use Classic mocks as a place holder to write tests for
  L2capFixedChannelAllocatorTest

Test: bluetooth_test_gd
Bug: 140938432
Change-Id: Ibff6cb2c3120d967efe828e91cb8f9f2bdefc398
parent ad242dce
Loading
Loading
Loading
Loading
+1 −4
Original line number Diff line number Diff line
@@ -11,11 +11,9 @@ filegroup {
        "classic_fixed_channel_service.cc",
        "internal/classic_dynamic_channel_allocator.cc",
        "internal/classic_dynamic_channel_impl.cc",
        "internal/classic_fixed_channel_allocator.cc",
        "internal/classic_fixed_channel_impl.cc",
        "internal/classic_fixed_channel_service_manager_impl.cc",
        "internal/classic_link_manager.cc",
        "internal/le_fixed_channel_allocator.cc",
        "internal/le_fixed_channel_impl.cc",
        "internal/le_fixed_channel_service_manager_impl.cc",
        "internal/le_link_manager.cc",
@@ -32,11 +30,10 @@ filegroup {
        "l2cap_packet_test.cc",
        "internal/classic_dynamic_channel_allocator_test.cc",
        "internal/classic_dynamic_channel_impl_test.cc",
        "internal/classic_fixed_channel_allocator_test.cc",
        "internal/classic_fixed_channel_impl_test.cc",
        "internal/classic_fixed_channel_service_manager_test.cc",
        "internal/classic_link_manager_test.cc",
        "internal/le_fixed_channel_allocator_test.cc",
        "internal/fixed_channel_allocator_test.cc",
        "internal/le_fixed_channel_impl_test.cc",
        "internal/le_fixed_channel_service_manager_test.cc",
        "internal/le_link_manager_test.cc",
+0 −81
Original line number Diff line number Diff line
/*
 * Copyright 2019 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 <unordered_map>

#include "classic_fixed_channel_allocator.h"
#include "l2cap/cid.h"
#include "l2cap/internal/classic_fixed_channel_allocator.h"
#include "l2cap/internal/classic_link.h"
#include "l2cap/security_policy.h"
#include "os/handler.h"
#include "os/log.h"

namespace bluetooth {
namespace l2cap {
namespace internal {

std::shared_ptr<ClassicFixedChannelImpl> ClassicFixedChannelAllocator::AllocateChannel(Cid cid,
                                                                                       SecurityPolicy security_policy) {
  ASSERT_LOG(!IsChannelAllocated((cid)), "Cid 0x%x for device %s is already in use", cid,
             link_->GetDevice().ToString().c_str());
  ASSERT_LOG(cid >= kFirstFixedChannel && cid <= kLastFixedChannel, "Cid %d out of bound", cid);
  auto elem = channels_.try_emplace(cid, std::make_shared<ClassicFixedChannelImpl>(cid, link_, l2cap_handler_));
  ASSERT_LOG(elem.second, "Failed to create channel for cid 0x%x device %s", cid,
             link_->GetDevice().ToString().c_str());
  ASSERT(elem.first->second != nullptr);
  return elem.first->second;
}

void ClassicFixedChannelAllocator::FreeChannel(Cid cid) {
  ASSERT_LOG(IsChannelAllocated(cid), "Channel is not in use: cid %d, device %s", cid,
             link_->GetDevice().ToString().c_str());
  channels_.erase(cid);
}

bool ClassicFixedChannelAllocator::IsChannelAllocated(Cid cid) const {
  return channels_.find(cid) != channels_.end();
}

std::shared_ptr<ClassicFixedChannelImpl> ClassicFixedChannelAllocator::FindChannel(Cid cid) {
  ASSERT_LOG(IsChannelAllocated(cid), "Channel is not in use: cid %d, device %s", cid,
             link_->GetDevice().ToString().c_str());
  return channels_.find(cid)->second;
}

size_t ClassicFixedChannelAllocator::NumberOfChannels() const {
  return channels_.size();
}

void ClassicFixedChannelAllocator::OnAclDisconnected(hci::ErrorCode reason) {
  for (auto& elem : channels_) {
    elem.second->OnClosed(reason);
  }
}

int ClassicFixedChannelAllocator::GetRefCount() {
  int ref_count = 0;
  for (auto& elem : channels_) {
    if (elem.second->IsAcquired()) {
      ref_count++;
    }
  }
  return ref_count;
}

}  // namespace internal
}  // namespace l2cap
}  // namespace bluetooth
+0 −69
Original line number Diff line number Diff line
/*
 * Copyright 2019 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.
 */

#pragma once

#include <hci/hci_packets.h>
#include <unordered_map>

#include "l2cap/cid.h"
#include "l2cap/internal/classic_fixed_channel_impl.h"
#include "l2cap/security_policy.h"
#include "os/handler.h"
#include "os/log.h"

namespace bluetooth {
namespace l2cap {
namespace internal {

class ClassicLink;

// Helper class for keeping channels in a Link. It allocates and frees Channel object, and supports querying whether a
// channel is in use
class ClassicFixedChannelAllocator {
 public:
  ClassicFixedChannelAllocator(ClassicLink* link, os::Handler* l2cap_handler)
      : link_(link), l2cap_handler_(l2cap_handler) {
    ASSERT(link_ != nullptr);
    ASSERT(l2cap_handler_ != nullptr);
  }

  // Allocates a channel. If cid is used, return nullptr. NOTE: The returned ClassicFixedChannelImpl object is still
  // owned by the channel allocator, NOT the client.
  std::shared_ptr<ClassicFixedChannelImpl> AllocateChannel(Cid cid, SecurityPolicy security_policy);

  // Frees a channel. If cid doesn't exist, it will crash
  void FreeChannel(Cid cid);

  bool IsChannelAllocated(Cid cid) const;

  std::shared_ptr<ClassicFixedChannelImpl> FindChannel(Cid cid);

  size_t NumberOfChannels() const;

  void OnAclDisconnected(hci::ErrorCode hci_status);

  int GetRefCount();

 private:
  ClassicLink* link_;
  os::Handler* l2cap_handler_;
  std::unordered_map<Cid, std::shared_ptr<ClassicFixedChannelImpl>> channels_;
};

}  // namespace internal
}  // namespace l2cap
}  // namespace bluetooth
+2 −0
Original line number Diff line number Diff line
@@ -27,6 +27,8 @@ namespace testing {

class MockClassicFixedChannelImpl : public ClassicFixedChannelImpl {
 public:
  MockClassicFixedChannelImpl(Cid cid, ClassicLink* link, os::Handler* l2cap_handler)
      : ClassicFixedChannelImpl(cid, link, l2cap_handler) {}
  MOCK_METHOD(void, RegisterOnCloseCallback,
              (os::Handler * user_handler, ClassicFixedChannel::OnCloseCallback on_close_callback), (override));
  MOCK_METHOD(void, Acquire, (), (override));
+2 −2
Original line number Diff line number Diff line
@@ -20,8 +20,8 @@
#include <memory>

#include "hci/acl_manager.h"
#include "l2cap/internal/classic_fixed_channel_allocator.h"
#include "l2cap/internal/classic_fixed_channel_impl.h"
#include "l2cap/internal/fixed_channel_allocator.h"
#include "l2cap/internal/parameter_provider.h"
#include "l2cap/internal/scheduler.h"
#include "os/alarm.h"
@@ -89,7 +89,7 @@ class ClassicLink {

 private:
  os::Handler* l2cap_handler_;
  ClassicFixedChannelAllocator fixed_channel_allocator_{this, l2cap_handler_};
  FixedChannelAllocator<ClassicFixedChannelImpl, ClassicLink> fixed_channel_allocator_{this, l2cap_handler_};
  std::unique_ptr<hci::AclConnection> acl_connection_;
  std::unique_ptr<Scheduler> scheduler_;
  ParameterProvider* parameter_provider_;
Loading