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

Commit 3cc1ef97 authored by Arman Uguray's avatar Arman Uguray
Browse files

service: Introduce bluetooth::Adapter::Observer

This CL introduces a new Observer interface for the Adapter class.
This meant to serve as the top-level API for receiving Adapter state
notifications, property updates, etc, in a format that doesn't use
the native HAL types.

Bug: 23328384
Change-Id: Ibf29063a169ad5e986d433d0901b3b973af0aa56
parent fbf37366
Loading
Loading
Loading
Loading
+33 −5
Original line number Diff line number Diff line
@@ -27,6 +27,12 @@ const char Adapter::kDefaultAddress[] = "00:00:00:00:00:00";
// static
const char Adapter::kDefaultName[] = "not-initialized";

void Adapter::Observer::OnAdapterStateChanged(Adapter* adapter,
                                              AdapterState prev_state,
                                              AdapterState new_state) {
  // Default implementation does nothing
}

Adapter::Adapter()
    : state_(ADAPTER_STATE_OFF),
      address_(kDefaultAddress),
@@ -39,6 +45,16 @@ Adapter::~Adapter() {
  hal::BluetoothInterface::Get()->RemoveObserver(this);
}

void Adapter::AddObserver(Observer* observer) {
  std::lock_guard<std::mutex> lock(observers_lock_);
  observers_.AddObserver(observer);
}

void Adapter::RemoveObserver(Observer* observer) {
  std::lock_guard<std::mutex> lock(observers_lock_);
  observers_.RemoveObserver(observer);
}

AdapterState Adapter::GetState() const {
  return state_.load();
}
@@ -58,17 +74,17 @@ bool Adapter::Enable() {
  // Set the state before calling enable() as there might be a race between here
  // and the AdapterStateChangedCallback.
  state_ = ADAPTER_STATE_TURNING_ON;
  NotifyAdapterStateChanged(current_state, state_);

  int status = hal::BluetoothInterface::Get()->GetHALInterface()->enable();
  if (status != BT_STATUS_SUCCESS) {
    LOG(ERROR) << "Failed to enable Bluetooth - status: "
               << BtStatusText((const bt_status_t)status);
    state_ = ADAPTER_STATE_OFF;
    NotifyAdapterStateChanged(ADAPTER_STATE_TURNING_ON, state_);
    return false;
  }

  // TODO(armansito): Notify others of the state change.

  return true;
}

@@ -83,17 +99,17 @@ bool Adapter::Disable() {
  // Set the state before calling enable() as there might be a race between here
  // and the AdapterStateChangedCallback.
  state_ = ADAPTER_STATE_TURNING_OFF;
  NotifyAdapterStateChanged(current_state, state_);

  int status = hal::BluetoothInterface::Get()->GetHALInterface()->disable();
  if (status != BT_STATUS_SUCCESS) {
    LOG(ERROR) << "Failed to disable Bluetooth - status: "
               << BtStatusText((const bt_status_t)status);
    state_ = current_state;
    NotifyAdapterStateChanged(ADAPTER_STATE_TURNING_OFF, state_);
    return false;
  }

  // TODO(armansito): Notify others of the state change.

  return true;
}

@@ -132,6 +148,8 @@ std::string Adapter::GetAddress() const {
void Adapter::AdapterStateChangedCallback(bt_state_t state) {
  LOG(INFO) << "Adapter state changed: " << BtStateText(state);

  AdapterState prev_state = GetState();

  switch (state) {
  case BT_STATE_OFF:
    state_ = ADAPTER_STATE_OFF;
@@ -145,7 +163,7 @@ void Adapter::AdapterStateChangedCallback(bt_state_t state) {
    NOTREACHED();
  }

  // TODO(armansito): Notify others of the state change.
  NotifyAdapterStateChanged(prev_state, GetState());
}

void Adapter::AdapterPropertiesCallback(bt_status_t status,
@@ -205,4 +223,14 @@ bool Adapter::SetAdapterProperty(bt_property_type_t type,
  return true;
}

void Adapter::NotifyAdapterStateChanged(AdapterState prev_state,
                                        AdapterState new_state) {
  if (prev_state == new_state)
    return;

  std::lock_guard<std::mutex> lock(observers_lock_);
  FOR_EACH_OBSERVER(Observer, observers_,
                    OnAdapterStateChanged(this, prev_state, new_state));
}

}  // namespace bluetooth
+26 −0
Original line number Diff line number Diff line
@@ -17,9 +17,11 @@
#pragma once

#include <atomic>
#include <mutex>
#include <string>

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

#include "service/adapter_state.h"
#include "service/hal/bluetooth_interface.h"
@@ -36,9 +38,25 @@ class Adapter : hal::BluetoothInterface::Observer {
  static const char kDefaultAddress[];
  static const char kDefaultName[];

  // Observer interface allows other classes to receive notifications from us.
  // All of the methods in this interface are declared as optional to allow
  // different layers to process only those events that they are interested in.
  class Observer {
   public:
    virtual ~Observer() = default;

    virtual void OnAdapterStateChanged(Adapter* adapter,
                                       AdapterState prev_state,
                                       AdapterState new_state);
  };

  Adapter();
  ~Adapter() override;

  // Add or remove an observer.
  void AddObserver(Observer* observer);
  void RemoveObserver(Observer* observer);

  // Returns the current Adapter state.
  AdapterState GetState() const;

@@ -76,6 +94,10 @@ class Adapter : hal::BluetoothInterface::Observer {
  // Sends a request to set the given HAL adapter property type and value.
  bool SetAdapterProperty(bt_property_type_t type, void* value, int length);

  // Helper for invoking observer method.
  void NotifyAdapterStateChanged(AdapterState prev_state,
                                 AdapterState new_state);

  // The current adapter state.
  std::atomic<AdapterState> state_;

@@ -86,6 +108,10 @@ class Adapter : hal::BluetoothInterface::Observer {
  // The current local adapter name.
  util::AtomicString name_;

  // List of observers that are interested in notifications from us.
  std::mutex observers_lock_;
  base::ObserverList<Observer> observers_;

  DISALLOW_COPY_AND_ASSIGN(Adapter);
};

+1 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ enum AdapterState {
  ADAPTER_STATE_TURNING_ON = 11,
  ADAPTER_STATE_ON = 12,
  ADAPTER_STATE_TURNING_OFF = 13,
  ADAPTER_STATE_INVALID = 0xFFFF
};

// Returns a string for the given Adapter state |state|.
+69 −0
Original line number Diff line number Diff line
@@ -50,6 +50,39 @@ class AdapterTest : public ::testing::Test {
  DISALLOW_COPY_AND_ASSIGN(AdapterTest);
};

class TestObserver final : public bluetooth::Adapter::Observer {
 public:
  TestObserver(bluetooth::Adapter* adapter)
      : adapter_(adapter),
        prev_state_(bluetooth::ADAPTER_STATE_INVALID),
        cur_state_(bluetooth::ADAPTER_STATE_INVALID) {
    CHECK(adapter_);
    adapter_->AddObserver(this);
  }

  ~TestObserver() override {
    adapter_->RemoveObserver(this);
  }

  bluetooth::AdapterState prev_state() const { return prev_state_; }
  bluetooth::AdapterState cur_state() const { return cur_state_; }

  // bluetooth::Adapter::Observer override:
  void OnAdapterStateChanged(bluetooth::Adapter* adapter,
                             bluetooth::AdapterState prev_state,
                             bluetooth::AdapterState new_state) {
    ASSERT_EQ(adapter_, adapter);
    prev_state_ = prev_state;
    cur_state_ = new_state;
  }

 private:
  bluetooth::Adapter* adapter_;
  bluetooth::AdapterState prev_state_, cur_state_;

  DISALLOW_COPY_AND_ASSIGN(TestObserver);
};

TEST_F(AdapterTest, IsEnabled) {
  EXPECT_FALSE(adapter_->IsEnabled());

@@ -61,6 +94,8 @@ TEST_F(AdapterTest, IsEnabled) {
}

TEST_F(AdapterTest, Enable) {
  TestObserver observer(adapter_.get());

  EXPECT_FALSE(adapter_->IsEnabled());
  EXPECT_EQ(bluetooth::ADAPTER_STATE_OFF, adapter_->GetState());

@@ -72,6 +107,10 @@ TEST_F(AdapterTest, Enable) {
  fake_hal_manager_->enable_succeed = true;
  EXPECT_TRUE(adapter_->Enable());

  // Should have received a state update.
  EXPECT_EQ(bluetooth::ADAPTER_STATE_OFF, observer.prev_state());
  EXPECT_EQ(bluetooth::ADAPTER_STATE_TURNING_ON, observer.cur_state());

  // Enable fails because not disabled
  EXPECT_EQ(bluetooth::ADAPTER_STATE_TURNING_ON, adapter_->GetState());
  EXPECT_FALSE(adapter_->Enable());
@@ -80,11 +119,17 @@ TEST_F(AdapterTest, Enable) {
  fake_hal_iface_->NotifyAdapterStateChanged(BT_STATE_ON);
  EXPECT_EQ(bluetooth::ADAPTER_STATE_ON, adapter_->GetState());

  // Should have received a state update.
  EXPECT_EQ(bluetooth::ADAPTER_STATE_TURNING_ON, observer.prev_state());
  EXPECT_EQ(bluetooth::ADAPTER_STATE_ON, observer.cur_state());

  // Enable fails because already enabled
  EXPECT_FALSE(adapter_->Enable());
}

TEST_F(AdapterTest, Disable) {
  TestObserver observer(adapter_.get());

  fake_hal_manager_->disable_succeed = true;
  EXPECT_FALSE(adapter_->IsEnabled());
  EXPECT_EQ(bluetooth::ADAPTER_STATE_OFF, adapter_->GetState());
@@ -95,8 +140,17 @@ TEST_F(AdapterTest, Disable) {

  // Disable success
  fake_hal_iface_->NotifyAdapterStateChanged(BT_STATE_ON);

  // Should have received a state update.
  EXPECT_EQ(bluetooth::ADAPTER_STATE_OFF, observer.prev_state());
  EXPECT_EQ(bluetooth::ADAPTER_STATE_ON, observer.cur_state());

  EXPECT_TRUE(adapter_->Disable());

  // Should have received a state update.
  EXPECT_EQ(bluetooth::ADAPTER_STATE_ON, observer.prev_state());
  EXPECT_EQ(bluetooth::ADAPTER_STATE_TURNING_OFF, observer.cur_state());

  // Disable fails because not enabled
  EXPECT_EQ(bluetooth::ADAPTER_STATE_TURNING_OFF, adapter_->GetState());
  EXPECT_FALSE(adapter_->Disable());
@@ -104,9 +158,24 @@ TEST_F(AdapterTest, Disable) {
  fake_hal_iface_->NotifyAdapterStateChanged(BT_STATE_ON);
  EXPECT_EQ(bluetooth::ADAPTER_STATE_ON, adapter_->GetState());

  // Should have received a state update.
  EXPECT_EQ(bluetooth::ADAPTER_STATE_TURNING_OFF, observer.prev_state());
  EXPECT_EQ(bluetooth::ADAPTER_STATE_ON, observer.cur_state());

  // Disable fails at HAL level
  fake_hal_manager_->disable_succeed = false;
  EXPECT_FALSE(adapter_->Disable());

  // Should have received a state update. In this case we will receive two
  // updates: one going from OFF to TURNING_OFF, and one going from TURNING_OFF
  // back to ON since we failed to initiate the disable operation.
  EXPECT_EQ(bluetooth::ADAPTER_STATE_TURNING_OFF, observer.prev_state());
  EXPECT_EQ(bluetooth::ADAPTER_STATE_ON, observer.cur_state());

  // Update state to OFF. Should receive a state update.
  fake_hal_iface_->NotifyAdapterStateChanged(BT_STATE_OFF);
  EXPECT_EQ(bluetooth::ADAPTER_STATE_ON, observer.prev_state());
  EXPECT_EQ(bluetooth::ADAPTER_STATE_OFF, observer.cur_state());
}

TEST_F(AdapterTest, GetName) {