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

Commit d09df39f authored by Erwin Jansen's avatar Erwin Jansen Committed by Gerrit Code Review
Browse files

Merge "Use abstract datachannels in Root Canal."

parents 250ff9a2 4c604a29
Loading
Loading
Loading
Loading
+51 −106
Original line number Diff line number Diff line
@@ -18,13 +18,13 @@

#include "bluetooth_hci.h"

#include "log/log.h"
#include <cutils/properties.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>

#include "hci_internals.h"
#include "log/log.h"

namespace android {
namespace hardware {
@@ -58,18 +58,15 @@ class BluetoothDeathRecipient : public hidl_death_recipient {
    mHci->close();
  }
  sp<IBluetoothHci> mHci;
  bool getHasDied() const {
    return has_died_;
  }
  void setHasDied(bool has_died) {
    has_died_ = has_died;
  }
  bool getHasDied() const { return has_died_; }
  void setHasDied(bool has_died) { has_died_ = has_died; }

 private:
  bool has_died_;
};

BluetoothHci::BluetoothHci() : death_recipient_(new BluetoothDeathRecipient(this)) {}
BluetoothHci::BluetoothHci()
    : death_recipient_(new BluetoothDeathRecipient(this)) {}

Return<void> BluetoothHci::initialize(
    const sp<V1_0::IBluetoothHciCallbacks>& cb) {
@@ -104,7 +101,8 @@ Return<void> BluetoothHci::initialize_impl(
  controller_ = std::make_shared<DualModeController>();

  char mac_property[PROPERTY_VALUE_MAX] = "";
  property_get("vendor.bt.rootcanal_mac_address", mac_property, "3C:5A:B4:01:02:03");
  property_get("vendor.bt.rootcanal_mac_address", mac_property,
               "3C:5A:B4:01:02:03");
  controller_->Initialize({"dmc", std::string(mac_property)});

  controller_->RegisterEventChannel(
@@ -193,11 +191,25 @@ Return<void> BluetoothHci::initialize_impl(
  });

  if (BtTestConsoleEnabled()) {
    SetUpTestChannel(6111);
    SetUpHciServer(6211,
                   [this](int fd) { test_model_.IncomingHciConnection(fd); });
    SetUpLinkLayerServer(
        6311, [this](int fd) { test_model_.IncomingLinkLayerConnection(fd); });
    test_socket_server_ =
        std::make_shared<net::PosixAsyncSocketServer>(6111, &async_manager_);
    hci_socket_server_ =
        std::make_shared<net::PosixAsyncSocketServer>(6211, &async_manager_);
    link_socket_server_ =
        std::make_shared<net::PosixAsyncSocketServer>(6311, &async_manager_);
    connector_ =
        std::make_shared<net::PosixAsyncSocketConnector>(&async_manager_);
    SetUpTestChannel();
    SetUpHciServer([this](std::shared_ptr<AsyncDataChannel> socket,
                          AsyncDataChannelServer* srv) {
      test_model_.IncomingHciConnection(socket);
      srv->StartListening();
    });
    SetUpLinkLayerServer([this](std::shared_ptr<AsyncDataChannel> socket,
                                AsyncDataChannelServer* srv) {
      test_model_.IncomingLinkLayerConnection(socket);
      srv->StartListening();
    });
  } else {
    // This should be configurable in the future.
    LOG_INFO("Adding Beacons so the scan list is not empty.");
@@ -283,122 +295,55 @@ Return<void> BluetoothHci::sendIsoData(const hidl_vec<uint8_t>& packet) {
  return Void();
}

void BluetoothHci::SetUpHciServer(int port, const std::function<void(int)>& connection_callback) {
  int socket_fd = remote_hci_transport_.SetUp(port);

void BluetoothHci::SetUpHciServer(ConnectCallback connection_callback) {
  test_channel_.RegisterSendResponse([](const std::string& response) {
    LOG_INFO("No HCI Response channel: %s", response.c_str());
  });

  if (socket_fd == -1) {
    LOG_ERROR("Remote HCI channel SetUp(%d) failed.", port);
  if (!remote_hci_transport_.SetUp(hci_socket_server_, connection_callback)) {
    LOG_ERROR("Remote HCI channel SetUp failed.");
    return;
  }

  async_manager_.WatchFdForNonBlockingReads(socket_fd, [this, connection_callback](int socket_fd) {
    int conn_fd = remote_hci_transport_.Accept(socket_fd);
    if (conn_fd < 0) {
      LOG_ERROR("Error watching remote HCI channel fd.");
      return;
}
    int flags = fcntl(conn_fd, F_GETFL, NULL);
    int ret;
    ret = fcntl(conn_fd, F_SETFL, flags | O_NONBLOCK);
    ASSERT_LOG(ret != -1, "Error setting O_NONBLOCK %s", strerror(errno));

    connection_callback(conn_fd);
  });
}

void BluetoothHci::SetUpLinkLayerServer(int port, const std::function<void(int)>& connection_callback) {
  int socket_fd = remote_link_layer_transport_.SetUp(port);
void BluetoothHci::SetUpLinkLayerServer(ConnectCallback connection_callback) {
  remote_link_layer_transport_.SetUp(link_socket_server_, connection_callback);

  test_channel_.RegisterSendResponse([](const std::string& response) {
    LOG_INFO("No LinkLayer Response channel: %s", response.c_str());
  });

  if (socket_fd == -1) {
    LOG_ERROR("Remote LinkLayer channel SetUp(%d) failed.", port);
    return;
}

  async_manager_.WatchFdForNonBlockingReads(socket_fd, [this, connection_callback](int socket_fd) {
    int conn_fd = remote_link_layer_transport_.Accept(socket_fd);
    if (conn_fd < 0) {
      LOG_ERROR("Error watching remote LinkLayer channel fd.");
      return;
std::shared_ptr<AsyncDataChannel> BluetoothHci::ConnectToRemoteServer(
    const std::string& server, int port) {
  return connector_->ConnectToRemoteServer(server, port);
}
    int flags = fcntl(conn_fd, F_GETFL, NULL);
    int ret = fcntl(conn_fd, F_SETFL, flags | O_NONBLOCK);
    ASSERT_LOG(ret != -1, "Error setting O_NONBLOCK %s", strerror(errno));

    connection_callback(conn_fd);
void BluetoothHci::SetUpTestChannel() {
  bool transport_configured = test_channel_transport_.SetUp(
      test_socket_server_, [this](std::shared_ptr<AsyncDataChannel> conn_fd,
                                  AsyncDataChannelServer*) {
        LOG_INFO("Test channel connection accepted.");
        test_channel_.RegisterSendResponse(
            [this, conn_fd](const std::string& response) {
              test_channel_transport_.SendResponse(conn_fd, response);
            });
}

int BluetoothHci::ConnectToRemoteServer(const std::string& server, int port) {
  int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
  if (socket_fd < 1) {
    LOG_INFO("socket() call failed: %s", strerror(errno));
    return -1;
  }

  struct hostent* host;
  host = gethostbyname(server.c_str());
  if (host == NULL) {
    LOG_INFO("gethostbyname() failed for %s: %s", server.c_str(),
             strerror(errno));
    return -1;
  }

  struct sockaddr_in serv_addr;
  memset((void*)&serv_addr, 0, sizeof(serv_addr));
  serv_addr.sin_family = AF_INET;
  serv_addr.sin_addr.s_addr = INADDR_ANY;
  serv_addr.sin_port = htons(port);

  int result = connect(socket_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
  if (result < 0) {
    LOG_INFO("connect() failed for %s@%d: %s", server.c_str(), port,
             strerror(errno));
    return -1;
  }

  int flags = fcntl(socket_fd, F_GETFL, NULL);
  int ret = fcntl(socket_fd, F_SETFL, flags | O_NONBLOCK);
  ASSERT_LOG(ret != -1, "Error setting O_NONBLOCK %s", strerror(errno));

  return socket_fd;
}

void BluetoothHci::SetUpTestChannel(int port) {
  int socket_fd = test_channel_transport_.SetUp(port);

        conn_fd->WatchForNonBlockingRead([this](AsyncDataChannel* conn_fd) {
          test_channel_transport_.OnCommandReady(conn_fd, []() {});
        });
        return false;
      });
  test_channel_.RegisterSendResponse([](const std::string& response) {
    LOG_INFO("No test channel: %s", response.c_str());
  });

  if (socket_fd == -1) {
    LOG_ERROR("Test channel SetUp(%d) failed.", port);
  if (!transport_configured) {
    LOG_ERROR("Test channel SetUp failed.");
    return;
  }

  LOG_INFO("Test channel SetUp() successful");
  async_manager_.WatchFdForNonBlockingReads(socket_fd, [this](int socket_fd) {
    int conn_fd = test_channel_transport_.Accept(socket_fd);
    if (conn_fd < 0) {
      LOG_ERROR("Error watching test channel fd.");
      return;
    }
    LOG_INFO("Test channel connection accepted.");
    test_channel_.RegisterSendResponse(
        [this, conn_fd](const std::string& response) { test_channel_transport_.SendResponse(conn_fd, response); });

    async_manager_.WatchFdForNonBlockingReads(conn_fd, [this](int conn_fd) {
      test_channel_transport_.OnCommandReady(conn_fd,
                                             [this, conn_fd]() { async_manager_.StopWatchingFileDescriptor(conn_fd); });
    });
  });
}

/* Fallback to shared library if there is no service. */
+25 −14
Original line number Diff line number Diff line
@@ -16,19 +16,18 @@

#pragma once

#include "os/log.h"

#include <android/hardware/bluetooth/1.1/IBluetoothHci.h>

#include <hidl/MQDescriptor.h>

#include "hci_packetizer.h"

#include "model/controller/dual_mode_controller.h"
#include "model/setup/async_manager.h"
#include "model/setup/test_channel_transport.h"
#include "model/setup/test_command_handler.h"
#include "model/setup/test_model.h"
#include "net/posix/posix_async_socket_connector.h"
#include "net/posix/posix_async_socket_server.h"
#include "os/log.h"

namespace android {
namespace hardware {
@@ -38,6 +37,11 @@ namespace sim {

class BluetoothDeathRecipient;

using android::net::AsyncDataChannel;
using android::net::AsyncDataChannelConnector;
using android::net::AsyncDataChannelServer;
using android::net::ConnectCallback;

class BluetoothHci : public IBluetoothHci {
 public:
  BluetoothHci();
@@ -47,11 +51,14 @@ class BluetoothHci : public IBluetoothHci {
  ::android::hardware::Return<void> initialize_1_1(
      const sp<V1_1::IBluetoothHciCallbacks>& cb) override;

  ::android::hardware::Return<void> sendHciCommand(const ::android::hardware::hidl_vec<uint8_t>& packet) override;
  ::android::hardware::Return<void> sendHciCommand(
      const ::android::hardware::hidl_vec<uint8_t>& packet) override;

  ::android::hardware::Return<void> sendAclData(const ::android::hardware::hidl_vec<uint8_t>& packet) override;
  ::android::hardware::Return<void> sendAclData(
      const ::android::hardware::hidl_vec<uint8_t>& packet) override;

  ::android::hardware::Return<void> sendScoData(const ::android::hardware::hidl_vec<uint8_t>& packet) override;
  ::android::hardware::Return<void> sendScoData(
      const ::android::hardware::hidl_vec<uint8_t>& packet) override;

  ::android::hardware::Return<void> sendIsoData(
      const ::android::hardware::hidl_vec<uint8_t>& packet) override;
@@ -73,12 +80,17 @@ class BluetoothHci : public IBluetoothHci {

  void HandleIncomingPacket();

  std::shared_ptr<AsyncDataChannelServer> test_socket_server_;
  std::shared_ptr<AsyncDataChannelServer> hci_socket_server_;
  std::shared_ptr<AsyncDataChannelServer> link_socket_server_;
  std::shared_ptr<AsyncDataChannelConnector> connector_;
  test_vendor_lib::AsyncManager async_manager_;

  void SetUpTestChannel(int port);
  void SetUpHciServer(int port, const std::function<void(int)>& on_connect);
  void SetUpLinkLayerServer(int port, const std::function<void(int)>& on_connect);
  int ConnectToRemoteServer(const std::string& server, int port);
  void SetUpTestChannel();
  void SetUpHciServer(ConnectCallback on_connect);
  void SetUpLinkLayerServer(ConnectCallback on_connect);
  std::shared_ptr<AsyncDataChannel> ConnectToRemoteServer(
      const std::string& server, int port);

  std::shared_ptr<test_vendor_lib::DualModeController> controller_;

@@ -102,8 +114,8 @@ class BluetoothHci : public IBluetoothHci {
                                                    task);
      },

      [this](test_vendor_lib::AsyncUserId user_id) {
        async_manager_.CancelAsyncTasksFromUser(user_id);
      [this](test_vendor_lib::AsyncUserId user) {
        async_manager_.CancelAsyncTasksFromUser(user);
      },

      [this](test_vendor_lib::AsyncTaskId task) {
@@ -113,7 +125,6 @@ class BluetoothHci : public IBluetoothHci {
      [this](const std::string& server, int port) {
        return ConnectToRemoteServer(server, port);
      }};

  test_vendor_lib::TestCommandHandler test_channel_{test_model_};
};

+0 −1
Original line number Diff line number Diff line
@@ -39,7 +39,6 @@ cc_library_static {
        "model/devices/keyboard.cc",
        "model/devices/link_layer_socket_device.cc",
        "model/devices/loopback.cc",
        "model/devices/polled_socket.cc",
        "model/devices/remote_loopback_device.cc",
        "model/devices/scripted_beacon.cc",
        "model/devices/sniffer.cc",
+16 −10
Original line number Diff line number Diff line
@@ -13,21 +13,24 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "test_environment.h"

#include <future>

#include <client/linux/handler/exception_handler.h>

#include <backtrace/Backtrace.h>
#include <backtrace/backtrace_constants.h>

#include <client/linux/handler/exception_handler.h>
#include <gflags/gflags.h>

#include <future>

#include "model/setup/async_manager.h"
#include "net/posix/posix_async_socket_connector.h"
#include "net/posix/posix_async_socket_server.h"
#include "os/log.h"

using ::android::bluetooth::root_canal::TestEnvironment;
using ::android::net::PosixAsyncSocketConnector;
using ::android::net::PosixAsyncSocketServer;
using test_vendor_lib::AsyncManager;

DEFINE_string(controller_properties_file, "",
              "controller_properties.json file path");
@@ -111,10 +114,13 @@ int main(int argc, char** argv) {
      }
    }
  }

  TestEnvironment root_canal(test_port, hci_server_port, link_server_port,
                             FLAGS_controller_properties_file,
                             FLAGS_default_commands_file);
  AsyncManager am;
  TestEnvironment root_canal(
      std::make_shared<PosixAsyncSocketServer>(test_port, &am),
      std::make_shared<PosixAsyncSocketServer>(hci_server_port, &am),
      std::make_shared<PosixAsyncSocketServer>(link_server_port, &am),
      std::make_shared<PosixAsyncSocketConnector>(&am),
      FLAGS_controller_properties_file, FLAGS_default_commands_file);
  std::promise<void> barrier;
  std::future<void> barrier_future = barrier.get_future();
  root_canal.initialize(std::move(barrier));
+53 −117
Original line number Diff line number Diff line
@@ -16,14 +16,12 @@

#include "test_environment.h"

#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <type_traits>  // for remove_extent_t
#include <utility>      // for move
#include <vector>       // for vector

#include "os/log.h"
#include "net/async_data_channel.h"  // for AsyncDataChannel
#include "os/log.h"                  // for LOG_INFO, LOG_ERROR, LOG_WARN

namespace android {
namespace bluetooth {
@@ -52,13 +50,16 @@ void TestEnvironment::initialize(std::promise<void> barrier) {
      });

  SetUpTestChannel();
  SetUpHciServer([this](int fd) { test_model_.IncomingHciConnection(fd); });
  SetUpLinkLayerServer([this](int fd) { test_model_.IncomingLinkLayerConnection(fd); });

  // In case the client socket is closed, and rootcanal doesn't detect it due to
  // TimerTick not fired, writing to the socket causes a SIGPIPE and we need to
  // catch it to prevent rootcanal from crash
  signal(SIGPIPE, SIG_IGN);
  SetUpHciServer([this](std::shared_ptr<AsyncDataChannel> socket,
                        AsyncDataChannelServer* srv) {
    test_model_.IncomingHciConnection(socket);
    srv->StartListening();
  });
  SetUpLinkLayerServer([this](std::shared_ptr<AsyncDataChannel> socket,
                              AsyncDataChannelServer* srv) {
    test_model_.IncomingLinkLayerConnection(socket);
    srv->StartListening();
  });

  LOG_INFO("%s: Finished", __func__);
}
@@ -68,92 +69,54 @@ void TestEnvironment::close() {
  test_model_.Reset();
}

void TestEnvironment::SetUpHciServer(const std::function<void(int)>& connection_callback) {
  int socket_fd = remote_hci_transport_.SetUp(hci_server_port_);

  test_channel_.RegisterSendResponse(
      [](const std::string& response) { LOG_INFO("No HCI Response channel: %s", response.c_str()); });

  if (socket_fd == -1) {
    LOG_ERROR("Remote HCI channel SetUp(%d) failed.", hci_server_port_);
    return;
  }

  async_manager_.WatchFdForNonBlockingReads(socket_fd, [this, connection_callback](int socket_fd) {
    int conn_fd = remote_hci_transport_.Accept(socket_fd);
    if (conn_fd < 0) {
      LOG_ERROR("Error watching remote HCI channel fd.");
      return;
    }
    int flags = fcntl(conn_fd, F_GETFL, NULL);
    int ret;
    ret = fcntl(conn_fd, F_SETFL, flags | O_NONBLOCK);
    ASSERT_LOG(ret != -1, "Error setting O_NONBLOCK %s", strerror(errno));

    connection_callback(conn_fd);
void TestEnvironment::SetUpHciServer(ConnectCallback connection_callback) {
  test_channel_.RegisterSendResponse([](const std::string& response) {
    LOG_INFO("No HCI Response channel: %s", response.c_str());
  });
}

void TestEnvironment::SetUpLinkLayerServer(const std::function<void(int)>& connection_callback) {
  int socket_fd = remote_link_layer_transport_.SetUp(link_server_port_);

  test_channel_.RegisterSendResponse(
      [](const std::string& response) { LOG_INFO("No LinkLayer Response channel: %s", response.c_str()); });

  if (socket_fd == -1) {
    LOG_ERROR("Remote LinkLayer channel SetUp(%d) failed.", link_server_port_);
  if (!remote_hci_transport_.SetUp(hci_socket_server_, connection_callback)) {
    LOG_ERROR("Remote HCI channel SetUp failed.");
    return;
  }

  async_manager_.WatchFdForNonBlockingReads(socket_fd, [this, connection_callback](int socket_fd) {
    int conn_fd = remote_link_layer_transport_.Accept(socket_fd);
    if (conn_fd < 0) {
      LOG_ERROR("Error watching remote LinkLayer channel fd.");
      return;
    }
    int flags = fcntl(conn_fd, F_GETFL, NULL);
    int ret = fcntl(conn_fd, F_SETFL, flags | O_NONBLOCK);
    ASSERT_LOG(ret != -1, "Error setting O_NONBLOCK %s", strerror(errno));

    connection_callback(conn_fd);
  });
}

int TestEnvironment::ConnectToRemoteServer(const std::string& server, int port) {
  int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
  if (socket_fd < 1) {
    LOG_INFO("socket() call failed: %s", strerror(errno));
    return -1;
  }
void TestEnvironment::SetUpLinkLayerServer(
    ConnectCallback connection_callback) {
  remote_link_layer_transport_.SetUp(link_socket_server_, connection_callback);

  struct hostent* host;
  host = gethostbyname(server.c_str());
  if (host == NULL) {
    LOG_INFO("gethostbyname() failed for %s: %s", server.c_str(), strerror(errno));
    return -1;
  test_channel_.RegisterSendResponse([](const std::string& response) {
    LOG_INFO("No LinkLayer Response channel: %s", response.c_str());
  });
}

  struct sockaddr_in serv_addr {};
  memset((void*)&serv_addr, 0, sizeof(serv_addr));
  serv_addr.sin_family = AF_INET;
  serv_addr.sin_addr.s_addr = INADDR_ANY;
  serv_addr.sin_port = htons(port);

  int result = connect(socket_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
  if (result < 0) {
    LOG_INFO("connect() failed for %s@%d: %s", server.c_str(), port, strerror(errno));
    return -1;
std::shared_ptr<AsyncDataChannel> TestEnvironment::ConnectToRemoteServer(
    const std::string& server, int port) {
  return connector_->ConnectToRemoteServer(server, port);
}

  int flags = fcntl(socket_fd, F_GETFL, NULL);
  int ret = fcntl(socket_fd, F_SETFL, flags | O_NONBLOCK);
  ASSERT_LOG(ret != -1, "Error setting O_NONBLOCK %s", strerror(errno));

  return socket_fd;
void TestEnvironment::SetUpTestChannel() {
  bool transport_configured = test_channel_transport_.SetUp(
      test_socket_server_, [this](std::shared_ptr<AsyncDataChannel> conn_fd,
                                  AsyncDataChannelServer*) {
        LOG_INFO("Test channel connection accepted.");
        if (test_channel_open_) {
          LOG_WARN("Only one connection at a time is supported");
          test_channel_transport_.SendResponse(conn_fd,
                                               "The connection is broken");
          return false;
        }
        test_channel_open_ = true;
        test_channel_.RegisterSendResponse(
            [this, conn_fd](const std::string& response) {
              test_channel_transport_.SendResponse(conn_fd, response);
            });

void TestEnvironment::SetUpTestChannel() {
  int socket_fd = test_channel_transport_.SetUp(test_port_);
        conn_fd->WatchForNonBlockingRead([this](AsyncDataChannel* conn_fd) {
          test_channel_transport_.OnCommandReady(
              conn_fd, [this]() { test_channel_open_ = false; });
        });
        return false;
      });
  test_channel_.RegisterSendResponse([](const std::string& response) {
    LOG_INFO("No test channel: %s", response.c_str());
  });
@@ -164,39 +127,12 @@ void TestEnvironment::SetUpTestChannel() {

  test_channel_.FromFile(default_commands_file_);

  if (socket_fd == -1) {
    LOG_ERROR("Test channel SetUp(%d) failed.", test_port_);
  if (!transport_configured) {
    LOG_ERROR("Test channel SetUp failed.");
    return;
  }

  LOG_INFO("Test channel SetUp() successful");
  async_manager_.WatchFdForNonBlockingReads(socket_fd, [this](int socket_fd) {
    int conn_fd = test_channel_transport_.Accept(socket_fd);
    if (conn_fd < 0) {
      LOG_ERROR("Error watching test channel fd.");
      barrier_.set_value();
      return;
    }
    LOG_INFO("Test channel connection accepted.");
    if (test_channel_open_) {
      LOG_WARN("Only one connection at a time is supported");
      async_manager_.StopWatchingFileDescriptor(conn_fd);
      test_channel_transport_.SendResponse(conn_fd, "The connection is broken");
      return;
    }
    test_channel_open_ = true;
    test_channel_.RegisterSendResponse(
        [this, conn_fd](const std::string& response) {
          test_channel_transport_.SendResponse(conn_fd, response);
        });

    async_manager_.WatchFdForNonBlockingReads(conn_fd, [this](int conn_fd) {
      test_channel_transport_.OnCommandReady(conn_fd, [this, conn_fd]() {
        async_manager_.StopWatchingFileDescriptor(conn_fd);
        test_channel_open_ = false;
      });
    });
  });
}

}  // namespace root_canal
Loading