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

Commit 8cb25df1 authored by Hansong Zhang's avatar Hansong Zhang
Browse files

Revert "L2CAP Classic dynamic channel and allocator impl"

This reverts commit d539cc98.

Reason for revert: Broke test!

Change-Id: If0ef8fc64ba16c7bded9d4849d5b09a4217489bf
parent d539cc98
Loading
Loading
Loading
Loading
+0 −4
Original line number Diff line number Diff line
@@ -9,8 +9,6 @@ filegroup {
        "classic_fixed_channel.cc",
        "classic_fixed_channel_manager.cc",
        "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",
@@ -23,8 +21,6 @@ filegroup {
    name: "BluetoothL2capTestSources",
    srcs: [
        "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",
+0 −92
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_dynamic_channel_allocator.h"
#include "l2cap/cid.h"
#include "l2cap/internal/classic_dynamic_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<ClassicDynamicChannelImpl> ClassicDynamicChannelAllocator::AllocateChannel(
    Psm psm, Cid remote_cid, SecurityPolicy security_policy) {
  if (IsChannelAllocated((psm))) {
    LOG_INFO("Psm 0x%x for device %s is already in use", psm, link_->GetDevice().ToString().c_str());
    return nullptr;
  }
  if (!IsPsmValid(psm)) {
    LOG_INFO("Psm 0x%x is invalid", psm);
    return nullptr;
  }
  if (used_remote_cid_.find(remote_cid) != used_remote_cid_.end()) {
    LOG_INFO("Remote cid 0x%x is used", remote_cid);
    return nullptr;
  }
  Cid cid = kFirstDynamicChannel;
  for (; cid <= kLastDynamicChannel; cid++) {
    LOG_INFO();
    if (used_cid_.count(cid) == 0) break;
  }
  if (cid > kLastDynamicChannel) {
    LOG_WARN("All cid are used");
    return nullptr;
  }
  auto elem = channels_.try_emplace(
      psm, std::make_shared<ClassicDynamicChannelImpl>(psm, cid, remote_cid, link_, l2cap_handler_));
  ASSERT_LOG(elem.second, "Failed to create channel for psm 0x%x device %s", psm,
             link_->GetDevice().ToString().c_str());
  ASSERT(elem.first->second != nullptr);
  used_cid_.insert(cid);
  used_remote_cid_.insert(remote_cid);
  return elem.first->second;
}

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

bool ClassicDynamicChannelAllocator::IsChannelAllocated(Psm psm) const {
  return channels_.find(psm) != channels_.end();
}

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

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

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

}  // namespace internal
}  // namespace l2cap
}  // namespace bluetooth
+0 −70
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 <set>
#include <unordered_map>

#include "l2cap/cid.h"
#include "l2cap/internal/classic_dynamic_channel_impl.h"
#include "l2cap/psm.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 ClassicDynamicChannelAllocator {
 public:
  ClassicDynamicChannelAllocator(ClassicLink* link, os::Handler* l2cap_handler)
      : link_(link), l2cap_handler_(l2cap_handler) {
    ASSERT(link_ != nullptr);
    ASSERT(l2cap_handler_ != nullptr);
  }

  // Allocates a channel. If psm is used, OR the remote cid already exists, return nullptr.
  // NOTE: The returned ClassicDynamicChannelImpl object is still owned by the channel allocator, NOT the client.
  std::shared_ptr<ClassicDynamicChannelImpl> AllocateChannel(Psm psm, Cid remote_cid, SecurityPolicy security_policy);

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

  bool IsChannelAllocated(Psm psm) const;

  std::shared_ptr<ClassicDynamicChannelImpl> FindChannel(Psm psm);

  size_t NumberOfChannels() const;

  void OnAclDisconnected(hci::ErrorCode hci_status);

 private:
  ClassicLink* link_;
  os::Handler* l2cap_handler_;
  std::unordered_map<Psm, std::shared_ptr<ClassicDynamicChannelImpl>> channels_;
  std::set<Cid> used_cid_;
  std::set<Cid> used_remote_cid_;
};

}  // namespace internal
}  // namespace l2cap
}  // namespace bluetooth
+0 −78
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 "l2cap/internal/classic_dynamic_channel_allocator.h"
#include "l2cap/internal/classic_link_mock.h"
#include "l2cap/internal/parameter_provider_mock.h"

#include <gmock/gmock.h>
#include <gtest/gtest.h>

namespace bluetooth {
namespace l2cap {
namespace internal {

using testing::MockClassicLink;
using testing::MockParameterProvider;
using ::testing::Return;

const hci::Address device{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}};

class L2capClassicDynamicChannelAllocatorTest : public ::testing::Test {
 protected:
  void SetUp() override {
    thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL);
    handler_ = new os::Handler(thread_);
    mock_parameter_provider_ = new MockParameterProvider();
    mock_classic_link_ = new MockClassicLink(handler_, mock_parameter_provider_);
    EXPECT_CALL(*mock_classic_link_, GetDevice()).WillRepeatedly(Return(device));
    channel_allocator_ = std::make_unique<ClassicDynamicChannelAllocator>(mock_classic_link_, handler_);
  }

  void TearDown() override {
    channel_allocator_.reset();
    delete mock_classic_link_;
    delete mock_parameter_provider_;
    handler_->Clear();
    delete handler_;
    delete thread_;
  }

  os::Thread* thread_{nullptr};
  os::Handler* handler_{nullptr};
  MockParameterProvider* mock_parameter_provider_{nullptr};
  MockClassicLink* mock_classic_link_{nullptr};
  std::unique_ptr<ClassicDynamicChannelAllocator> channel_allocator_;
};

TEST_F(L2capClassicDynamicChannelAllocatorTest, precondition) {
  Psm psm = 0x03;
  EXPECT_FALSE(channel_allocator_->IsChannelAllocated(psm));
}

TEST_F(L2capClassicDynamicChannelAllocatorTest, allocate_and_free_channel) {
  Psm psm = 0x03;
  Cid remote_cid = kFirstDynamicChannel;
  auto channel = channel_allocator_->AllocateChannel(psm, remote_cid, {});
  EXPECT_TRUE(channel_allocator_->IsChannelAllocated(psm));
  EXPECT_EQ(channel, channel_allocator_->FindChannel(psm));
  ASSERT_NO_FATAL_FAILURE(channel_allocator_->FreeChannel(psm));
  EXPECT_FALSE(channel_allocator_->IsChannelAllocated(psm));
}

}  // namespace internal
}  // namespace l2cap
}  // namespace bluetooth
+0 −83
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 "l2cap/cid.h"
#include "l2cap/internal/classic_dynamic_channel_impl.h"
#include "l2cap/internal/classic_link.h"
#include "l2cap/psm.h"
#include "l2cap/security_policy.h"
#include "os/handler.h"
#include "os/log.h"

namespace bluetooth {
namespace l2cap {
namespace internal {

ClassicDynamicChannelImpl::ClassicDynamicChannelImpl(Psm psm, Cid cid, Cid remote_cid, ClassicLink* link,
                                                     os::Handler* l2cap_handler)
    : psm_(psm), cid_(cid), remote_cid_(remote_cid), link_(link), l2cap_handler_(l2cap_handler) {
  ASSERT(IsPsmValid(psm_));
  ASSERT(cid_ > 0);
  ASSERT(remote_cid_ > 0);
  ASSERT(link_ != nullptr);
  ASSERT(l2cap_handler_ != nullptr);
}

hci::Address ClassicDynamicChannelImpl::GetDevice() const {
  return link_->GetDevice();
}

void ClassicDynamicChannelImpl::RegisterOnCloseCallback(os::Handler* user_handler,
                                                        ClassicDynamicChannel::OnCloseCallback on_close_callback) {
  ASSERT_LOG(user_handler_ == nullptr, "OnCloseCallback can only be registered once");
  // If channel is already closed, call the callback immediately without saving it
  if (closed_) {
    user_handler->Post(common::BindOnce(std::move(on_close_callback), close_reason_));
    return;
  }
  user_handler_ = user_handler;
  on_close_callback_ = std::move(on_close_callback);
}

void ClassicDynamicChannelImpl::Close() {}

void ClassicDynamicChannelImpl::OnClosed(hci::ErrorCode status) {
  ASSERT_LOG(!closed_, "Device %s Cid 0x%x closed twice, old status 0x%x, new status 0x%x",
             link_->GetDevice().ToString().c_str(), cid_, static_cast<int>(close_reason_), static_cast<int>(status));
  closed_ = true;
  close_reason_ = status;
  link_ = nullptr;
  l2cap_handler_ = nullptr;
  if (user_handler_ == nullptr) {
    return;
  }
  // On close callback can only be called once
  user_handler_->Post(common::BindOnce(std::move(on_close_callback_), status));
  user_handler_ = nullptr;
  on_close_callback_.Reset();
}

std::string ClassicDynamicChannelImpl::ToString() {
  std::ostringstream ss;
  ss << "Device " << link_->GetDevice().ToString() << "Psm 0x" << std::hex << psm_ << " Cid 0x" << std::hex << cid_;
  return ss.str();
}

}  // namespace internal
}  // namespace l2cap
}  // namespace bluetooth
Loading