OSDN Git Service

test_vendor: Refactor test channel
authorMyles Watson <mylesgw@google.com>
Fri, 20 May 2016 19:06:19 +0000 (12:06 -0700)
committerAndre Eisenbach <eisenbach@google.com>
Tue, 6 Sep 2016 19:20:30 +0000 (19:20 +0000)
The test channel can always be enabled when using the AsyncManager.
 - Remove enabled_ and port_
 - Allow multiple connections
 - Pass file descriptors as parameters instead of private variables
 - Add a clean up function to the Test Channel
 - Add a static class in bt_vendor.cc and always EXPORT the entry point
 - Move the vendor callbacks and the global pointer to the vendor
   manager object from vendor_manager to bt_vendor

Change-Id: I3e0dee846eb89f434893603a705c2b13219272be
Signed-off-by: Myles Watson <mylesgw@google.com>
Signed-off-by: Jorge E. Moreira <jemoreira@google.com>
vendor_libs/test_vendor_lib/Android.mk
vendor_libs/test_vendor_lib/include/test_channel_transport.h
vendor_libs/test_vendor_lib/include/vendor_manager.h
vendor_libs/test_vendor_lib/src/bt_vendor.cc
vendor_libs/test_vendor_lib/src/test_channel_transport.cc
vendor_libs/test_vendor_lib/src/vendor_manager.cc

index cc7e5cb..9c530ba 100644 (file)
@@ -56,6 +56,8 @@ LOCAL_CFLAGS += \
   -UNDEBUG \
   -DLOG_NDEBUG=1
 
+LOCAL_CFLAGS += -DEXPORT_SYMBOL="__attribute__((visibility(\"default\")))"
+
 include $(BUILD_SHARED_LIBRARY)
 
 # test-vendor unit tests for host
index 8f4d4e8..e7105df 100644 (file)
@@ -30,45 +30,34 @@ namespace test_vendor_lib {
 // HciTransport for the test channel.
 class TestChannelTransport {
  public:
-  TestChannelTransport(bool enabled, int port);
+  TestChannelTransport() {}
 
-  ~TestChannelTransport() = default;
+  ~TestChannelTransport() {}
 
-  // Waits for a connection request from the test channel program and
-  // allocates the file descriptor to watch for run-time parameters at. This
-  // file descriptor gets stored in |fd_|.
-  bool SetUp();
-
-  int GetFd();
+  // Opens a port and returns the file descriptor for the socket.
+  // Returns -1 on an error.
+  int SetUp(int port);
 
-  // Because it imposes a different flow of work, the test channel must be
-  // actively enabled to be used. |enabled_| is set by the vendor manager.
-  bool IsEnabled();
+  // Closes the port (if succesfully opened in SetUp).
+  void CleanUp();
 
-  // Turns the test channel off for use in circumstances where an error occurs
-  // and leaving the channel on would crash Bluetooth (e.g. if the test channel
-  // is unable to bind to its socket, Bluetooth should still start without the
-  // channel enabled).
-  void Disable();
+  // Waits for a connection request from the test channel program and
+  // returns the file descriptor to watch for run-time parameters.
+  // Returns -1 on an error.
+  int Accept(int listen_fd);
 
-  // Sets the callback that fires when data is read in
-  // |OnFileCanReadWithoutBlocking|.
+  // Sets the callback that fires when data is read in WatchFd().
   void RegisterCommandHandler(
       const std::function<void(const std::string&, const vector<std::string>&)>&
           callback);
 
-  void OnFileCanReadWithoutBlocking(int fd);
+  void OnCommandReady(int fd, std::function<void(void)> unwatch);
 
  private:
   std::function<void(const std::string&, const vector<std::string>&)>
       command_handler_;
 
-  // File descriptor to watch for test hook data.
-  std::unique_ptr<base::ScopedFD> fd_;
-
-  // TODO(dennischeng): Get port and enabled flag from a config file.
-  bool enabled_;
-  int port_;
+  int listen_fd_ = -1;
 
   TestChannelTransport(const TestChannelTransport& cmdPckt) = delete;
   TestChannelTransport& operator=(const TestChannelTransport& cmdPckt) = delete;
index 74c85e6..84bb779 100644 (file)
@@ -32,23 +32,20 @@ namespace test_vendor_lib {
 // Contains the three core objects that make up the test vendor library: the
 // HciTransport for communication, the HciHandler for processing commands, and
 // the Controller for actual command implementations. The VendorManager shall
-// operate as a global singleton and be used in bt_vendor.cc to perform vendor
-// specific operations, via |vendor_callbacks_|, and to provide access to the
-// test controller by setting up a message loop (on another thread) that the HCI
-// will talk to and controller methods will execute on.
+// be used in bt_vendor.cc to provide access to the test controller by setting
+// up a message loop (on another thread) that the HCI will talk to and
+// controller methods will execute on.
 class VendorManager {
  public:
-  // Functions that operate on the global manager instance. Initialize()
-  // is called by the vendor library's TestVendorInitialize() function to create
-  // the global manager and must be called before Get() and CleanUp().
-  // CleanUp() should be called when a call to TestVendorCleanUp() is made
-  // since the global manager should live throughout the entire time the test
-  // vendor library is in use.
-  static void CleanUp();
+  VendorManager();
+
+  ~VendorManager() = default;
 
-  static VendorManager* Get();
+  void CleanUp();
 
-  static void Initialize();
+  // Initializes the controller and sets up the test channel to wait for
+  // connections.
+  bool Initialize();
 
   void CloseHciFd();
 
@@ -60,17 +57,9 @@ class VendorManager {
   // the vendor library from the HCI in TestVendorInit().
   void SetVendorCallbacks(const bt_vendor_callbacks_t& callbacks);
 
-  // Returns true if |thread_| is able to be started and the
-  // StartingWatchingOnThread() task has been posted to the task runner.
-  bool Run();
-
  private:
-  VendorManager();
-
-  ~VendorManager() = default;
-
-  // Starts watching for incoming data from the HCI and the test hook.
-  void StartWatchingOnThread();
+  // Set up a test channel on _port_
+  void SetUpTestChannel(int port);
 
   // Creates the HCI's communication channel and overrides IO callbacks to
   // receive and send packets.
@@ -86,9 +75,6 @@ class VendorManager {
   // Configuration callbacks provided by the HCI for use in TestVendorOp().
   bt_vendor_callbacks_t vendor_callbacks_;
 
-  // True if the underlying message loop (in |thread_|) is running.
-  bool running_;
-
   // The object that manages asynchronous tasks such as watching a file
   // descriptor or doing something in the future
   AsyncManager async_manager_;
index ed97762..226dcec 100644 (file)
 
 #define LOG_TAG "bt_vendor"
 
-#include "vendor_manager.h"
+#include <unistd.h>
+#include <memory>
 
 #include "base/logging.h"
-
-extern "C" {
 #include "osi/include/log.h"
-
-#include <unistd.h>
-}  // extern "C"
+#include "vendor_manager.h"
 
 namespace test_vendor_lib {
 
-// Initializes vendor manager for test controller. |p_cb| are the callbacks to
-// be in TestVendorOp(). |local_bdaddr| points to the address of the Bluetooth
-// device. Returns 0 on success, -1 on error.
-static int TestVendorInitialize(const bt_vendor_callbacks_t* p_cb,
-                                unsigned char* /* local_bdaddr */) {
-  LOG_INFO(LOG_TAG, "Initializing test controller.");
-  CHECK(p_cb);
-
-  VendorManager::Initialize();
-  VendorManager* manager = VendorManager::Get();
-  manager->SetVendorCallbacks(*(const_cast<bt_vendor_callbacks_t*>(p_cb)));
-  return manager->Run() ? 0 : -1;
-}
-
-// Vendor specific operations. |opcode| is the opcode for Bluedroid's vendor op
-// definitions. |param| points to operation specific arguments. Return value is
-// dependent on the operation invoked, or -1 on error.
-static int TestVendorOp(bt_vendor_opcode_t opcode, void* param) {
-  LOG_INFO(LOG_TAG, "Opcode received in vendor library: %d", opcode);
-
-  VendorManager* manager = VendorManager::Get();
-  CHECK(manager);
-
-  switch (opcode) {
-    case BT_VND_OP_POWER_CTRL: {
-      LOG_INFO(LOG_TAG, "Doing op: BT_VND_OP_POWER_CTRL");
-      int* state = static_cast<int*>(param);
-      if (*state == BT_VND_PWR_OFF)
-        LOG_INFO(LOG_TAG, "Turning Bluetooth off.");
-      else if (*state == BT_VND_PWR_ON)
-        LOG_INFO(LOG_TAG, "Turning Bluetooth on.");
-      return 0;
-    }
+class BtVendor {
+ public:
+  // Initializes vendor manager for test controller. |p_cb| are the callbacks to
+  // be in TestVendorOp(). |local_bdaddr| points to the address of the Bluetooth
+  // device. Returns 0 on success, -1 on error.
+  static int Initialize(const bt_vendor_callbacks_t* p_cb,
+                        unsigned char* /* local_bdaddr */) {
+    LOG_INFO(LOG_TAG, "Initializing test controller.");
+    CHECK(p_cb);
+
+    vendor_callbacks_ = *p_cb;
+
+    vendor_manager_.reset(new VendorManager());
+    return vendor_manager_->Initialize() ? 0 : 1;
+  }
 
-    // Give the HCI its fd to communicate with the HciTransport.
-    case BT_VND_OP_USERIAL_OPEN: {
-      LOG_INFO(LOG_TAG, "Doing op: BT_VND_OP_USERIAL_OPEN");
-      int* fd_list = static_cast<int*>(param);
-      fd_list[0] = manager->GetHciFd();
-      LOG_INFO(LOG_TAG, "Setting HCI's fd to: %d", fd_list[0]);
-      return 1;
+  // Vendor specific operations. |opcode| is the opcode for Bluedroid's vendor
+  // op definitions. |param| points to operation specific arguments. Return
+  // value is dependent on the operation invoked, or -1 on error.
+  static int Op(bt_vendor_opcode_t opcode, void* param) {
+    LOG_INFO(LOG_TAG, "Opcode received in vendor library: %d", opcode);
+
+    CHECK(vendor_manager_);
+
+    switch (opcode) {
+      case BT_VND_OP_POWER_CTRL: {
+        LOG_INFO(LOG_TAG, "Doing op: BT_VND_OP_POWER_CTRL");
+        int* state = static_cast<int*>(param);
+        if (*state == BT_VND_PWR_OFF)
+          LOG_INFO(LOG_TAG, "Turning Bluetooth off.");
+        else if (*state == BT_VND_PWR_ON)
+          LOG_INFO(LOG_TAG, "Turning Bluetooth on.");
+        return 0;
+      }
+
+      // Give the HCI its fd to communicate with the HciTransport.
+      case BT_VND_OP_USERIAL_OPEN: {
+        LOG_INFO(LOG_TAG, "Doing op: BT_VND_OP_USERIAL_OPEN");
+        int* fd_list = static_cast<int*>(param);
+        fd_list[0] = vendor_manager_->GetHciFd();
+        LOG_INFO(LOG_TAG, "Setting HCI's fd to: %d", fd_list[0]);
+        return 1;
+      }
+
+      // Close the HCI's file descriptor.
+      case BT_VND_OP_USERIAL_CLOSE:
+        LOG_INFO(LOG_TAG, "Doing op: BT_VND_OP_USERIAL_CLOSE");
+        LOG_INFO(
+            LOG_TAG, "Closing HCI's fd (fd: %d)", vendor_manager_->GetHciFd());
+        vendor_manager_->CloseHciFd();
+        return 1;
+
+      case BT_VND_OP_FW_CFG:
+        LOG_INFO(LOG_TAG, "Unsupported op: BT_VND_OP_FW_CFG");
+        vendor_callbacks_.fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
+        return -1;
+
+      case BT_VND_OP_SCO_CFG:
+        LOG_INFO(LOG_TAG, "Unsupported op: BT_VND_OP_SCO_CFG");
+        vendor_callbacks_.scocfg_cb(BT_VND_OP_RESULT_SUCCESS);
+        return -1;
+
+      case BT_VND_OP_GET_LPM_IDLE_TIMEOUT:
+        LOG_INFO(LOG_TAG, "Doing op: BT_VND_OP_SCO_CFG");
+        *((uint32_t*)param) = 1000;
+        return 0;
+
+      case BT_VND_OP_LPM_SET_MODE:
+        LOG_INFO(LOG_TAG, "Unsupported op: BT_VND_OP_LPM_SET_MODE");
+        vendor_callbacks_.lpm_cb(BT_VND_OP_RESULT_SUCCESS);
+        return -1;
+
+      case BT_VND_OP_LPM_WAKE_SET_STATE:
+        LOG_INFO(LOG_TAG, "Unsupported op: BT_VND_OP_LPM_WAKE_SET_STATE");
+        return -1;
+
+      case BT_VND_OP_SET_AUDIO_STATE:
+        LOG_INFO(LOG_TAG, "Unsupported op: BT_VND_OP_SET_AUDIO_STATE");
+        return -1;
+
+      case BT_VND_OP_EPILOG:
+        LOG_INFO(LOG_TAG, "Unsupported op: BT_VND_OP_EPILOG");
+        vendor_callbacks_.epilog_cb(BT_VND_OP_RESULT_SUCCESS);
+        return -1;
+
+      default:
+        LOG_INFO(LOG_TAG, "Op not recognized.");
+        return -1;
     }
+    return 0;
+  }
 
-    // Close the HCI's file descriptor.
-    case BT_VND_OP_USERIAL_CLOSE:
-      LOG_INFO(LOG_TAG, "Doing op: BT_VND_OP_USERIAL_CLOSE");
-      LOG_INFO(LOG_TAG, "Closing HCI's fd (fd: %d)", manager->GetHciFd());
-      manager->CloseHciFd();
-      return 1;
-
-    case BT_VND_OP_FW_CFG:
-      LOG_INFO(LOG_TAG, "Unsupported op: BT_VND_OP_FW_CFG");
-      manager->GetVendorCallbacks().fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
-      return -1;
-
-    case BT_VND_OP_SCO_CFG:
-      LOG_INFO(LOG_TAG, "Unsupported op: BT_VND_OP_SCO_CFG");
-      manager->GetVendorCallbacks().scocfg_cb(BT_VND_OP_RESULT_SUCCESS);
-      return -1;
-
-    case BT_VND_OP_GET_LPM_IDLE_TIMEOUT:
-      LOG_INFO(LOG_TAG, "Doing op: BT_VND_OP_SCO_CFG");
-      *((uint32_t*)param) = 1000;
-      return 0;
-
-    case BT_VND_OP_LPM_SET_MODE:
-      LOG_INFO(LOG_TAG, "Unsupported op: BT_VND_OP_LPM_SET_MODE");
-      manager->GetVendorCallbacks().lpm_cb(BT_VND_OP_RESULT_SUCCESS);
-      return -1;
-
-    case BT_VND_OP_LPM_WAKE_SET_STATE:
-      LOG_INFO(LOG_TAG, "Unsupported op: BT_VND_OP_LPM_WAKE_SET_STATE");
-      return -1;
-
-    case BT_VND_OP_SET_AUDIO_STATE:
-      LOG_INFO(LOG_TAG, "Unsupported op: BT_VND_OP_SET_AUDIO_STATE");
-      return -1;
-
-    case BT_VND_OP_EPILOG:
-      LOG_INFO(LOG_TAG, "Unsupported op: BT_VND_OP_EPILOG");
-      manager->GetVendorCallbacks().epilog_cb(BT_VND_OP_RESULT_SUCCESS);
-      return -1;
-
-    default:
-      LOG_INFO(LOG_TAG, "Op not recognized.");
-      return -1;
+  // Closes the vendor interface and cleans up the global vendor manager object.
+  static void CleanUp(void) {
+    LOG_INFO(LOG_TAG, "Cleaning up vendor library.");
+    CHECK(vendor_manager_);
+    vendor_manager_->CleanUp();
+    vendor_manager_.reset();
   }
-  return 0;
-}
 
-// Closes the vendor interface and cleans up the global vendor manager object.
-static void TestVendorCleanUp(void) {
-  LOG_INFO(LOG_TAG, "Cleaning up vendor library.");
-  VendorManager::CleanUp();
-}
+ private:
+  static std::unique_ptr<VendorManager> vendor_manager_;
+  static bt_vendor_callbacks_t vendor_callbacks_;
+};
+
+// Definition of static class members
+std::unique_ptr<VendorManager> BtVendor::vendor_manager_;
+bt_vendor_callbacks_t BtVendor::vendor_callbacks_;
 
 }  // namespace test_vendor_lib
 
 // Entry point of DLib.
-#ifdef BLUETOOTH_USE_TEST_AS_VENDOR
 EXPORT_SYMBOL
-#endif
 const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = {
     sizeof(bt_vendor_interface_t),
-    test_vendor_lib::TestVendorInitialize,
-    test_vendor_lib::TestVendorOp,
-    test_vendor_lib::TestVendorCleanUp};
+    test_vendor_lib::BtVendor::Initialize,
+    test_vendor_lib::BtVendor::Op,
+    test_vendor_lib::BtVendor::CleanUp};
index 906a177..e66783c 100644 (file)
@@ -30,68 +30,78 @@ extern "C" {
 
 namespace test_vendor_lib {
 
-TestChannelTransport::TestChannelTransport(bool enabled, int port)
-    : enabled_(enabled), port_(port) {}
-
-bool TestChannelTransport::SetUp() {
-  CHECK(enabled_);
-
-  struct sockaddr_in listen_address, test_channel_address;
+int TestChannelTransport::SetUp(int port) {
+  struct sockaddr_in listen_address;
   socklen_t sockaddr_in_size = sizeof(struct sockaddr_in);
-  int listen_fd = -1;
-  int accept_fd = -1;
   memset(&listen_address, 0, sockaddr_in_size);
-  memset(&test_channel_address, 0, sockaddr_in_size);
 
-  if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+  OSI_NO_INTR(listen_fd_ = socket(AF_INET, SOCK_STREAM, 0));
+  if (listen_fd_ < 0) {
     LOG_INFO(LOG_TAG, "Error creating socket for test channel.");
-    return false;
+    return -1;
   }
 
-  LOG_INFO(LOG_TAG, "port: %d", port_);
+  LOG_INFO(LOG_TAG, "port: %d", port);
   listen_address.sin_family = AF_INET;
-  listen_address.sin_port = htons(port_);
+  listen_address.sin_port = htons(port);
   listen_address.sin_addr.s_addr = htonl(INADDR_ANY);
 
-  if (bind(listen_fd,
+  if (bind(listen_fd_,
            reinterpret_cast<sockaddr*>(&listen_address),
            sockaddr_in_size) < 0) {
     LOG_INFO(LOG_TAG, "Error binding test channel listener socket to address.");
-    close(listen_fd);
-    return false;
+    close(listen_fd_);
+    return -1;
   }
 
-  if (listen(listen_fd, 1) < 0) {
+  if (listen(listen_fd_, 1) < 0) {
     LOG_INFO(LOG_TAG, "Error listening for test channel.");
-    close(listen_fd);
-    return false;
+    close(listen_fd_);
+    return -1;
   }
+  return listen_fd_;
+}
 
-  if ((accept_fd = accept(listen_fd,
-                          reinterpret_cast<sockaddr*>(&test_channel_address),
-                          &sockaddr_in_size)) < 0) {
-    LOG_INFO(LOG_TAG, "Error accepting test channel connection.");
-    close(listen_fd);
-    return false;
+void TestChannelTransport::CleanUp() {
+  if (listen_fd_ == -1) {
+    return;
   }
-
-  fd_.reset(new base::ScopedFD(accept_fd));
-  return GetFd() >= 0;
+  if (close(listen_fd_)) {
+    LOG_ERROR(LOG_TAG, "Error closing listen_fd_.");
+  }
+  listen_fd_ = -1;
 }
 
-int TestChannelTransport::GetFd() {
-  return fd_->get();
-}
+int TestChannelTransport::Accept(int listen_fd_) {
+  int accept_fd = -1;
+  struct sockaddr_in test_channel_address;
+  socklen_t sockaddr_in_size = sizeof(struct sockaddr_in);
+  memset(&test_channel_address, 0, sockaddr_in_size);
 
-bool TestChannelTransport::IsEnabled() {
-  return enabled_;
-}
+  OSI_NO_INTR(accept_fd =
+                  accept(listen_fd_,
+                         reinterpret_cast<sockaddr*>(&test_channel_address),
+                         &sockaddr_in_size));
+  if (accept_fd < 0) {
+    LOG_INFO(LOG_TAG,
+             "Error accepting test channel connection errno=%d (%s).",
+             errno,
+             strerror(errno));
+
+    if (errno != EAGAIN && errno != EWOULDBLOCK) {
+      LOG_ERROR(LOG_TAG, "Closing listen_fd_ (won't try again).");
+      close(listen_fd_);
+      return -1;
+    }
+  }
 
-// base::MessageLoopForIO::Watcher overrides:
-void TestChannelTransport::OnFileCanReadWithoutBlocking(int fd) {
-  CHECK(fd == GetFd());
+  LOG_INFO(LOG_TAG, "accept_fd = %d.", accept_fd);
 
-  LOG_INFO(LOG_TAG, "Event ready in TestChannelTransport on fd: %d", fd);
+  return accept_fd;
+}
+
+void TestChannelTransport::OnCommandReady(int fd,
+                                          std::function<void(void)> unwatch) {
   uint8_t command_name_size = 0;
   read(fd, &command_name_size, 1);
   vector<uint8_t> command_name_raw;
@@ -101,8 +111,10 @@ void TestChannelTransport::OnFileCanReadWithoutBlocking(int fd) {
   LOG_INFO(
       LOG_TAG, "Received command from test channel: %s", command_name.data());
 
-  if (command_name == "CLOSE_TEST_CHANNEL") {
-    fd_.reset(nullptr);
+  if (command_name == "CLOSE_TEST_CHANNEL" || command_name == "") {
+    LOG_INFO(LOG_TAG, "Test channel closed");
+    unwatch();
+    close(fd);
     return;
   }
 
@@ -131,8 +143,4 @@ void TestChannelTransport::RegisterCommandHandler(
   command_handler_ = callback;
 }
 
-void TestChannelTransport::Disable() {
-  enabled_ = false;
-}
-
 }  // namespace test_vendor_lib {
index 215baf7..07cc86a 100644 (file)
 
 #include "base/logging.h"
 
-extern "C" {
 #include "osi/include/log.h"
-}  // extern "C"
 
 namespace test_vendor_lib {
 
 VendorManager* g_manager = nullptr;
 
-// static
 void VendorManager::CleanUp() {
-  delete g_manager;
-  g_manager = nullptr;
+  test_channel_transport_.CleanUp();
 }
 
-// static
-VendorManager* VendorManager::Get() {
-  // Initialize should have been called already.
-  CHECK(g_manager);
-  return g_manager;
-}
-
-// static
-void VendorManager::Initialize() {
-  CHECK(!g_manager);
-  g_manager = new VendorManager();
-}
-
-VendorManager::VendorManager()
-    : test_channel_transport_(true, 6111), running_(false) {}
-
-bool VendorManager::Run() {
-  CHECK(!running_);
-
+bool VendorManager::Initialize() {
   if (!transport_.SetUp()) {
     LOG_ERROR(LOG_TAG, "Error setting up transport object.");
     return false;
   }
 
-  if (test_channel_transport_.IsEnabled()) {
-    LOG_INFO(LOG_TAG, "Test channel is enabled.");
+  controller_.RegisterHandlersWithHciTransport(transport_);
 
-    if (test_channel_transport_.SetUp()) {
-      controller_.RegisterHandlersWithTestChannelTransport(
-          test_channel_transport_);
-    } else {
-      LOG_ERROR(LOG_TAG,
-                "Error setting up test channel object, continuing without it.");
-      test_channel_transport_.Disable();
-    }
-  } else {
-    LOG_INFO(LOG_TAG, "Test channel is disabled.");
-  }
+  controller_.RegisterHandlersWithTestChannelTransport(test_channel_transport_);
 
-  controller_.RegisterHandlersWithHciTransport(transport_);
-  // TODO(dennischeng): Register PostDelayedEventResponse instead.
-  controller_.RegisterDelayedEventChannel([this](
-      std::unique_ptr<EventPacket> event, std::chrono::milliseconds delay) {
-    transport_.PostDelayedEventResponse(*event, delay);
+  controller_.RegisterEventChannel([this](std::unique_ptr<EventPacket> event) {
+    transport_.PostEventResponse(*event);
   });
 
   transport_.RegisterEventScheduler(
@@ -92,38 +56,43 @@ bool VendorManager::Run() {
         async_manager_.ExecAsyncPeriodically(delay, period, task);
       });
 
-  running_ = true;
-  StartWatchingOnThread();
-
-  return true;
-}
-
-void VendorManager::StartWatchingOnThread() {
-  CHECK(running_);
-
   if (async_manager_.WatchFdForNonBlockingReads(
           transport_.GetVendorFd(), [this](int fd) {
             transport_.OnFileCanReadWithoutBlocking(fd);
           }) != 0) {
     LOG_ERROR(LOG_TAG, "Error watching vendor fd.");
-    return;
+    return true;
   }
 
-  if (test_channel_transport_.IsEnabled())
-    if (async_manager_.WatchFdForNonBlockingReads(
-            test_channel_transport_.GetFd(), [this](int fd) {
-              test_channel_transport_.OnFileCanReadWithoutBlocking(fd);
-            }) != 0) {
-      LOG_ERROR(LOG_TAG, "Error watching test channel fd.");
-    }
-}
+  SetUpTestChannel(6111);
 
-void VendorManager::SetVendorCallbacks(const bt_vendor_callbacks_t& callbacks) {
-  vendor_callbacks_ = callbacks;
+  return true;
 }
 
-const bt_vendor_callbacks_t& VendorManager::GetVendorCallbacks() const {
-  return vendor_callbacks_;
+VendorManager::VendorManager() : test_channel_transport_() {}
+
+void VendorManager::SetUpTestChannel(int port) {
+  int socket_fd = test_channel_transport_.SetUp(port);
+
+  if (socket_fd == -1) {
+    LOG_ERROR(LOG_TAG, "Test channel SetUp(%d) failed.", port);
+    return;
+  }
+
+  LOG_INFO(LOG_TAG, "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(LOG_TAG, "Error watching test channel fd.");
+      return;
+    }
+    LOG_INFO(LOG_TAG, "Test channel connection accepted.");
+    async_manager_.WatchFdForNonBlockingReads(conn_fd, [this](int conn_fd) {
+      test_channel_transport_.OnCommandReady(conn_fd, [this, conn_fd]() {
+        async_manager_.StopWatchingFileDescriptor(conn_fd);
+      });
+    });
+  });
 }
 
 void VendorManager::CloseHciFd() {