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

Commit 718a6317 authored by Arman Uguray's avatar Arman Uguray
Browse files

service: Add Mock support for Daemon and CoreStack

This patch turns the Daemon and CoreStack classes into abstract
interfaces. Mock and real implementations are implemented in special
subclasses and obtained via a factory method. Other test implementations
(e.g. stub) can be provided in the future.

Bug: 22532180
Change-Id: Ic3000518e5cef1c867dd803cd0bba6aab49dc596
parent 49713e1b
Loading
Loading
Loading
Loading
+34 −7
Original line number Diff line number Diff line
@@ -181,13 +181,35 @@ bt_os_callouts_t callouts = {

namespace bluetooth {

CoreStack::CoreStack() : adapter_(nullptr), hal_(nullptr) {
// The real CoreStack implementation to be used in production code.
class CoreStackImpl : public CoreStack {
 public:
  CoreStackImpl();
  ~CoreStackImpl() override;

  // CoreStack overrides.
  bool Initialize() override;
  bool SetAdapterName(const std::string& name) override;
  bool SetClassicDiscoverable() override;
  const void* GetInterface(const char* profile) override;

 private:
  // Our libhardware handle.
  bluetooth_device_t *adapter_;

  // Common Bluetooth interface handle.
  const bt_interface_t *hal_;

  DISALLOW_COPY_AND_ASSIGN(CoreStackImpl);
};

CoreStackImpl::CoreStackImpl() : adapter_(nullptr), hal_(nullptr) {
  std::lock_guard<std::mutex> lock(mutex);
  // TODO(icoolidge): DCHECK(!instantiated);
  instantiated = true;
}

bool CoreStack::Initialize() {
bool CoreStackImpl::Initialize() {
  std::unique_lock<std::mutex> lock(mutex);

  // Load the bluetooth module.
@@ -230,11 +252,11 @@ bool CoreStack::Initialize() {
  }

  synchronize.wait(lock);
  LOG_INFO(LOG_TAG, "%s", "CoreStack::Initialize success");
  LOG_INFO(LOG_TAG, "%s", "CoreStackImpl::Initialize success");
  return true;
}

bool CoreStack::SetAdapterName(const std::string &name) {
bool CoreStackImpl::SetAdapterName(const std::string &name) {
  bt_bdname_t n;
  snprintf(reinterpret_cast<char *>(n.name), sizeof(n.name), "%s",
           name.c_str());
@@ -255,7 +277,7 @@ bool CoreStack::SetAdapterName(const std::string &name) {
  return true;
}

bool CoreStack::SetClassicDiscoverable() {
bool CoreStackImpl::SetClassicDiscoverable() {
  bt_scan_mode_t mode = BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
  bt_property_t disc;
  disc.len = sizeof(mode);
@@ -274,7 +296,7 @@ bool CoreStack::SetClassicDiscoverable() {
  return true;
}

const void *CoreStack::GetInterface(const char *profile) {
const void* CoreStackImpl::GetInterface(const char *profile) {
  std::unique_lock<std::mutex> lock(mutex);
  // Get the interface to the GATT profile.
  const void *interface = hal_->get_profile_interface(profile);
@@ -285,10 +307,15 @@ const void *CoreStack::GetInterface(const char *profile) {
  return interface;
}

CoreStack::~CoreStack() {
CoreStackImpl::~CoreStackImpl() {
  // TODO(icoolidge): Disable bluetooth hardware, clean up library state.
  std::lock_guard<std::mutex> lock(mutex);
  instantiated = false;
}

// static
std::unique_ptr<CoreStack> CoreStack::Create() {
  return std::unique_ptr<CoreStack>(new CoreStackImpl());
}

}  // namespace bluetooth
+15 −15
Original line number Diff line number Diff line
@@ -13,11 +13,13 @@
//  See the License for the specific language governing permissions and
//  limitations under the License.
//

#pragma once

#include <memory>
#include <string>

#include "hardware/bluetooth.h"
#include <base/macros.h>

namespace bluetooth {

@@ -26,32 +28,30 @@ namespace bluetooth {
// It is also used to access profile interfaces.
class CoreStack {
 public:
  CoreStack();
  ~CoreStack();
  virtual ~CoreStack() = default;

  // Initialize the bluetooth stack and device.
  bool Initialize();
  virtual bool Initialize() = 0;

  // Set the device name.
  // This can be referenced in BLE GAP advertisements.
  bool SetAdapterName(const std::string& name);
  virtual bool SetAdapterName(const std::string& name) = 0;

  // Allow activated classic profiles to be discovered.
  bool SetClassicDiscoverable();
  virtual bool SetClassicDiscoverable() = 0;

  // Get an interface for a profile (BLE GATT, A2DP, etc).
  const void *GetInterface(const char* profile);
  virtual const void* GetInterface(const char* profile) = 0;

 private:
  // Prevent copy and assignment.
  CoreStack& operator=(const CoreStack& rhs) = delete;
  CoreStack(const CoreStack& rhs) = delete;
  // Factory method that creates a real CoreStack instance. This should be used
  // in production code.
  static std::unique_ptr<CoreStack> Create();

  // Our libhardware handle.
  bluetooth_device_t *adapter_;
 protected:
  CoreStack() = default;

  // Common bluetooth interface handle.
  const bt_interface_t *hal_;
 private:
  DISALLOW_COPY_AND_ASSIGN(CoreStack);
};

}  // namespace bluetooth
+66 −47
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

#include "service/daemon.h"

#include <memory>

#include <base/logging.h>

#include "service/core_stack.h"
@@ -29,53 +31,25 @@ namespace {
// The global Daemon instance.
Daemon* g_daemon = nullptr;

}  // namespace

// static
bool Daemon::Initialize() {
  CHECK(!g_daemon);

  g_daemon = new Daemon();
  if (g_daemon->Init())
    return true;

  LOG(ERROR) << "Failed to initialize the Daemon object";

  delete g_daemon;
  g_daemon = nullptr;
class DaemonImpl : public Daemon {
 public:
  DaemonImpl() = default;
  ~DaemonImpl() override = default;

  return false;
}

// static
void Daemon::ShutDown() {
  CHECK(g_daemon);
  CHECK(g_daemon->initialized_);

  delete g_daemon;
  g_daemon = NULL;
}

// static
Daemon* Daemon::Get() {
  CHECK(g_daemon);
  return g_daemon;
}

Daemon::Daemon() : initialized_(false) {
  void StartMainLoop() override {
    message_loop_->Run();
  }

Daemon::~Daemon() {
  Settings* GetSettings() const override {
    return settings_.get();
  }

void Daemon::StartMainLoop() {
  CHECK(initialized_);
  message_loop_->Run();
  base::MessageLoop* GetMessageLoop() const override {
    return message_loop_.get();
  }

bool Daemon::Init() {
  CHECK(!initialized_);

 private:
  bool Init() override {
    message_loop_.reset(new base::MessageLoop());

    settings_.reset(new Settings());
@@ -84,7 +58,7 @@ bool Daemon::Init() {
      return false;
    }

  core_stack_.reset(new CoreStack());
    core_stack_ = CoreStack::Create();
    if (!core_stack_->Initialize()) {
      LOG(ERROR) << "Failed to set up CoreStack";
      return false;
@@ -100,9 +74,54 @@ bool Daemon::Init() {
      return false;
    }

  initialized_ = true;
    return true;
  }

  std::unique_ptr<base::MessageLoop> message_loop_;
  std::unique_ptr<Settings> settings_;
  std::unique_ptr<CoreStack> core_stack_;
  std::unique_ptr<ipc::IPCManager> ipc_manager_;

  DISALLOW_COPY_AND_ASSIGN(DaemonImpl);
};

}  // namespace

// static
bool Daemon::Initialize() {
  CHECK(!g_daemon);

  g_daemon = new DaemonImpl();
  if (g_daemon->Init())
    return true;

  LOG(ERROR) << "Failed to initialize the Daemon object";

  delete g_daemon;
  g_daemon = nullptr;

  return false;
}

// static
void Daemon::ShutDown() {
  CHECK(g_daemon);
  delete g_daemon;
  g_daemon = nullptr;
}

// static
void Daemon::InitializeForTesting(Daemon* test_daemon) {
  CHECK(test_daemon);
  CHECK(!g_daemon);

  g_daemon = test_daemon;
}

// static
Daemon* Daemon::Get() {
  CHECK(g_daemon);
  return g_daemon;
}

}  // namespace bluetooth
+13 −16
Original line number Diff line number Diff line
@@ -16,8 +16,6 @@

#pragma once

#include <memory>

#include <base/macros.h>
#include <base/message_loop/message_loop.h>

@@ -43,33 +41,32 @@ class Daemon {
  // Cleans up all the resources associated with the global Daemon object.
  static void ShutDown();

  // Assigns the global Daemon instance for testing. Should only be called from
  // test code.
  static void InitializeForTesting(Daemon* test_daemon);

  // Returns the singleton Daemon instance. All classes can interact with the
  // Daemon, obtain its resources etc using this getter.
  static Daemon* Get();

  // The global Settings object. All classes have direct access to this through
  // the Daemon object.
  Settings* settings() const { return settings_.get(); }
  virtual Settings* GetSettings() const  = 0;

  // The main event loop. This should be used for any events and delayed tasks
  // that should be executed on the daemon's main thread.
  base::MessageLoop* message_loop() const { return message_loop_.get(); }
  virtual base::MessageLoop* GetMessageLoop() const = 0;

  // Starts the daemon's main loop.
  void StartMainLoop();
  virtual void StartMainLoop() = 0;

 private:
  Daemon();
  ~Daemon();
 protected:
  Daemon() = default;
  virtual ~Daemon() = default;

  // Private instance helper for Initialize().
  bool Init();

  bool initialized_;
  std::unique_ptr<base::MessageLoop> message_loop_;
  std::unique_ptr<Settings> settings_;
  std::unique_ptr<CoreStack> core_stack_;
  std::unique_ptr<ipc::IPCManager> ipc_manager_;
 private:
  // Internal instance helper called by Initialize().
  virtual bool Init() = 0;

  DISALLOW_COPY_AND_ASSIGN(Daemon);
};
+2 −2
Original line number Diff line number Diff line
@@ -41,9 +41,9 @@ bool IPCHandlerUnix::Run() {
  CHECK(!running_);

  const std::string& android_suffix =
      bluetooth::Daemon::Get()->settings()->android_ipc_socket_suffix();
      bluetooth::Daemon::Get()->GetSettings()->android_ipc_socket_suffix();
  const base::FilePath& path =
      bluetooth::Daemon::Get()->settings()->create_ipc_socket_path();
      bluetooth::Daemon::Get()->GetSettings()->create_ipc_socket_path();

  // Both flags cannot be set at the same time.
  CHECK(android_suffix.empty() || path.empty());
Loading