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

Commit 7852886c authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "gd shim l2cap_test"

parents d0997f9f d3dec7b2
Loading
Loading
Loading
Loading
+12 −6
Original line number Diff line number Diff line
@@ -94,7 +94,7 @@ class DynamicChannelManager {
   *
   * Returns: true if connection was able to be initiated, false otherwise.
   */
  bool ConnectChannel(hci::Address device, DynamicChannelConfigurationOption configuration_option, Psm psm,
  virtual bool ConnectChannel(hci::Address device, DynamicChannelConfigurationOption configuration_option, Psm psm,
                              OnConnectionOpenCallback on_connection_open, OnConnectionFailureCallback on_fail_callback,
                              os::Handler* handler);

@@ -119,12 +119,18 @@ class DynamicChannelManager {
   * @param handler: The handler context in which to execute the @callback parameter.
   * @param configuration_option: The configuration options for this channel
   */
  bool RegisterService(Psm psm, DynamicChannelConfigurationOption configuration_option,
                       const SecurityPolicy& security_policy, OnRegistrationCompleteCallback on_registration_complete,
  virtual bool RegisterService(Psm psm, DynamicChannelConfigurationOption configuration_option,
                               const SecurityPolicy& security_policy,
                               OnRegistrationCompleteCallback on_registration_complete,
                               OnConnectionOpenCallback on_connection_open, os::Handler* handler);

  friend class L2capClassicModule;

  virtual ~DynamicChannelManager() = default;

 protected:
  DynamicChannelManager() = default;

 private:
  // The constructor is not to be used by user code
  DynamicChannelManager(internal::DynamicChannelServiceManagerImpl* service_manager,
+1 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ filegroup {
filegroup {
    name: "BluetoothShimTestSources",
    srcs: [
            "l2cap_test.cc",
    ],
}

+9 −2
Original line number Diff line number Diff line
@@ -137,6 +137,10 @@ class ConnectionInterface {
  void OnConnectionClosed(hci::ErrorCode error_code) {
    LOG_DEBUG("Channel interface closed reason:%s cid:%hd device:%s", hci::ErrorCodeText(error_code).c_str(), cid_,
              address_.ToString().c_str());
    if (dequeue_registered_) {
      channel_->GetQueueUpEnd()->UnregisterDequeue();
      dequeue_registered_ = false;
    }
    ASSERT(on_connection_closed_callback_ != nullptr);
    on_connection_closed_callback_(cid_, static_cast<int>(error_code));
    deleter_(cid_);
@@ -261,8 +265,11 @@ void ConnectionInterfaceManager::AddConnection(ConnectionInterfaceDescriptor cid
}

void ConnectionInterfaceManager::RemoveConnection(ConnectionInterfaceDescriptor cid) {
  ASSERT(cid_to_interface_map_.count(cid) == 1);
  if (cid_to_interface_map_.count(cid) == 1) {
    cid_to_interface_map_.find(cid)->second->Close();
  } else {
    LOG_WARN("Closing a pending connection cid:%hd", cid);
  }
}

bool ConnectionInterfaceManager::HasResources() const {
+180 −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 "shim/l2cap.h"

#include <algorithm>
#include <chrono>
#include <future>
#include <map>
#include <memory>

#include <unistd.h>

#include <gtest/gtest.h>

#include "common/bind.h"
#include "hci/address.h"
#include "l2cap/classic/dynamic_channel_configuration_option.h"
#include "l2cap/classic/l2cap_classic_module.h"
#include "l2cap/psm.h"
#include "l2cap/security_policy.h"
#include "module.h"
#include "os/handler.h"

namespace bluetooth {
namespace shim {
namespace {

constexpr uint16_t kPsm = 123;
constexpr char device_address[] = "11:22:33:44:55:66";

class TestDynamicChannelManagerImpl {
 public:
  bool ConnectChannel(hci::Address device, l2cap::classic::DynamicChannelConfigurationOption configuration_option,
                      l2cap::Psm psm,
                      l2cap::classic::DynamicChannelManager::OnConnectionOpenCallback on_connection_open,
                      l2cap::classic::DynamicChannelManager::OnConnectionFailureCallback on_fail_callback,
                      os::Handler* handler) {
    connections_++;
    if (psm_to_connected_map_.find(psm) != psm_to_connected_map_.end()) {
      psm_to_connected_map_[psm]->set_value();
    }
    return true;
  }

  bool RegisterService(l2cap::Psm psm, l2cap::classic::DynamicChannelConfigurationOption configuration_option,
                       const l2cap::SecurityPolicy& security_policy,
                       l2cap::classic::DynamicChannelManager::OnRegistrationCompleteCallback on_registration_complete,
                       l2cap::classic::DynamicChannelManager::OnConnectionOpenCallback on_connection_open,
                       os::Handler* handler) {
    services_++;
    return true;
  }

  std::map<uint16_t, std::promise<void>*> psm_to_connected_map_;
  int connections_{0};
  int services_{0};

  ~TestDynamicChannelManagerImpl() {
    for (auto& entry : psm_to_connected_map_) {
      delete (entry.second);
    }
    psm_to_connected_map_.clear();
  }

  TestDynamicChannelManagerImpl() = default;
};

class TestDynamicChannelManager : public l2cap::classic::DynamicChannelManager {
 public:
  bool ConnectChannel(hci::Address device, l2cap::classic::DynamicChannelConfigurationOption configuration_option,
                      l2cap::Psm psm,
                      l2cap::classic::DynamicChannelManager::OnConnectionOpenCallback on_connection_open,
                      l2cap::classic::DynamicChannelManager::OnConnectionFailureCallback on_fail_callback,
                      os::Handler* handler) override {
    return impl_.ConnectChannel(device, configuration_option, psm, std::move(on_connection_open),
                                std::move(on_fail_callback), handler);
  }

  bool RegisterService(l2cap::Psm psm, l2cap::classic::DynamicChannelConfigurationOption configuration_option,
                       const l2cap::SecurityPolicy& security_policy,
                       l2cap::classic::DynamicChannelManager::OnRegistrationCompleteCallback on_registration_complete,
                       l2cap::classic::DynamicChannelManager::OnConnectionOpenCallback on_connection_open,
                       os::Handler* handler) override {
    return impl_.RegisterService(psm, configuration_option, security_policy, std::move(on_registration_complete),
                                 std::move(on_connection_open), handler);
  }
  TestDynamicChannelManager(TestDynamicChannelManagerImpl& impl) : impl_(impl) {}
  TestDynamicChannelManagerImpl& impl_;
};

class TestL2capClassicModule : public l2cap::classic::L2capClassicModule {
 public:
  std::unique_ptr<l2cap::classic::DynamicChannelManager> GetDynamicChannelManager() override {
    ASSERT(impl_ != nullptr);
    return std::make_unique<TestDynamicChannelManager>(*impl_);
  }

  void ListDependencies(ModuleList* list) override {}
  void Start() override;
  void Stop() override;

  TestDynamicChannelManagerImpl* impl_{nullptr};
};

void TestL2capClassicModule::Start() {
  impl_ = new TestDynamicChannelManagerImpl();
}

void TestL2capClassicModule::Stop() {
  delete impl_;
}

class ShimL2capTest : public ::testing::Test {
 public:
  void OnConnectionComplete(std::string string_address, uint16_t psm, uint16_t cid, bool connected) {}

  shim::L2cap* shim_l2cap_ = nullptr;
  TestL2capClassicModule* test_l2cap_classic_module_{nullptr};

 protected:
  void SetUp() override {
    test_l2cap_classic_module_ = new TestL2capClassicModule();
    test_l2cap_classic_module_->Start();
    fake_registry_.InjectTestModule(&l2cap::classic::L2capClassicModule::Factory, test_l2cap_classic_module_);

    fake_registry_.Start<shim::L2cap>(&thread_);
    shim_l2cap_ = static_cast<shim::L2cap*>(fake_registry_.GetModuleUnderTest(&shim::L2cap::Factory));
  }

  void TearDown() override {
    fake_registry_.StopAll();
  }

 private:
  TestModuleRegistry fake_registry_;
  os::Thread& thread_ = fake_registry_.GetTestThread();
};

TEST_F(ShimL2capTest, Module) {}

TEST_F(ShimL2capTest, ConnectThenDisconnectBeforeCompletion) {
  std::promise<uint16_t> promise;
  auto future = promise.get_future();

  test_l2cap_classic_module_->impl_->psm_to_connected_map_[kPsm] = new std::promise<void>();
  auto connection_started = test_l2cap_classic_module_->impl_->psm_to_connected_map_[kPsm]->get_future();

  shim_l2cap_->CreateConnection(
      kPsm, device_address,
      std::bind(&bluetooth::shim::ShimL2capTest::OnConnectionComplete, this, std::placeholders::_1,
                std::placeholders::_2, std::placeholders::_3, std::placeholders::_4),
      std::move(promise));
  uint16_t cid = future.get();

  ASSERT(cid != 0);

  connection_started.wait();

  ASSERT(test_l2cap_classic_module_->impl_->connections_ == 1);

  shim_l2cap_->CloseConnection(cid);
}

}  // namespace
}  // namespace shim
}  // namespace bluetooth
+30 −21
Original line number Diff line number Diff line
@@ -170,8 +170,8 @@ void bluetooth::shim::legacy::L2cap::RegisterService(
  }
  Classic().RegisterPsm(psm, callbacks);

  std::promise<void> register_completed;
  auto completed = register_completed.get_future();
  std::promise<void> register_pending;
  auto registered = register_pending.get_future();
  bool use_ertm = false;
  if (p_ertm_info != nullptr &&
      p_ertm_info->preferred_mode == L2CAP_FCR_ERTM_MODE) {
@@ -184,8 +184,8 @@ void bluetooth::shim::legacy::L2cap::RegisterService(
          &bluetooth::shim::legacy::L2cap::OnRemoteInitiatedConnectionCreated,
          this, std::placeholders::_1, std::placeholders::_2,
          std::placeholders::_3),
      std::move(register_completed));
  completed.wait();
      std::move(register_pending));
  registered.wait();
  LOG_DEBUG(LOG_TAG, "Successfully registered service on psm:%hd", psm);
}

@@ -233,10 +233,9 @@ uint16_t bluetooth::shim::legacy::L2cap::CreateConnection(
    return kInvalidConnectionInterfaceDescriptor;
  }

  std::promise<uint16_t> connect_completed;
  auto completed = connect_completed.get_future();
  LOG_DEBUG(LOG_TAG,
            "Starting local initiated connection to psm:%hd address:%s", psm,
  std::promise<uint16_t> create_pending;
  auto created = create_pending.get_future();
  LOG_DEBUG(LOG_TAG, "Initiating local connection to psm:%hd address:%s", psm,
            raw_address.ToString().c_str());

  bluetooth::shim::GetL2cap()->CreateConnection(
@@ -245,16 +244,16 @@ uint16_t bluetooth::shim::legacy::L2cap::CreateConnection(
          &bluetooth::shim::legacy::L2cap::OnLocalInitiatedConnectionCreated,
          this, std::placeholders::_1, std::placeholders::_2,
          std::placeholders::_3, std::placeholders::_4),
      std::move(connect_completed));
      std::move(create_pending));

  uint16_t cid = completed.get();
  uint16_t cid = created.get();
  if (cid == kInvalidConnectionInterfaceDescriptor) {
    LOG_WARN(LOG_TAG,
             "Failed to allocate resources to connect to psm:%hd address:%s",
             "Failed to initiate connection interface to psm:%hd address:%s",
             psm, raw_address.ToString().c_str());
  } else {
    LOG_DEBUG(LOG_TAG,
              "Successfully started connection to psm:%hd address:%s"
              "Successfully initiated connection to psm:%hd address:%s"
              " connection_interface_descriptor:%hd",
              psm, raw_address.ToString().c_str(), cid);
    CHECK(!ConnectionExists(cid));
@@ -265,15 +264,25 @@ uint16_t bluetooth::shim::legacy::L2cap::CreateConnection(

void bluetooth::shim::legacy::L2cap::OnLocalInitiatedConnectionCreated(
    std::string string_address, uint16_t psm, uint16_t cid, bool connected) {
  LOG_DEBUG(LOG_TAG,
            "Sending connection confirm to the upper stack but really "
            "a connection to %s has already been done cid:%hd",
            string_address.c_str(), cid);
  if (cid_closing_set_.count(cid) == 0) {
    if (connected) {
      SetDownstreamCallbacks(cid);
    } else {
      LOG_WARN(LOG_TAG,
               "Failed intitiating connection remote:%s psm:%hd cid:%hd",
               string_address.c_str(), psm, cid);
    }
    Classic().Callbacks(psm)->pL2CA_ConnectCfm_Cb(
        cid, connected ? (kConnectionSuccess) : (kConnectionFail));
  } else {
    LOG_DEBUG(LOG_TAG, "Connection Closed before presentation to upper layer");
    if (connected) {
      SetDownstreamCallbacks(cid);
      bluetooth::shim::GetL2cap()->CloseConnection(cid);
    } else {
      LOG_DEBUG(LOG_TAG, "Connection failed after initiator closed");
    }
  }
}

bool bluetooth::shim::legacy::L2cap::Write(uint16_t cid, BT_HDR* bt_hdr) {
@@ -370,7 +379,7 @@ bool bluetooth::shim::legacy::L2cap::DisconnectRequest(uint16_t cid) {
             cid);
    return false;
  }
  LOG_DEBUG(LOG_TAG, "%s cid:%hu", __func__, cid);
  LOG_DEBUG(LOG_TAG, "%s initiated locally cid:%hu", __func__, cid);
  cid_closing_set_.insert(cid);
  bluetooth::shim::GetL2cap()->CloseConnection(cid);
  return true;