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

Commit 360b22f8 authored by Arman Uguray's avatar Arman Uguray
Browse files

service: Replace CoreStack with Adapter

This CL removes the CoreStack class. Code that depended on a CoreStack instance
now depend on Adapter and hal::BluetoothInterface instead.

Bug: 23169364
Change-Id: Ide008cc7d3f9e74656f6bfa4df2dfee511e55b90
parent 859a12c7
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -19,9 +19,7 @@ LOCAL_PATH:= $(call my-dir)
# Common variables
# ========================================================
btserviceCommonSrc := \
	a2dp_source.cpp \
	adapter.cpp \
	core_stack.cpp \
	daemon.cpp \
	gatt_server.cpp \
	hal/bluetooth_interface.cpp \

system/service/a2dp_source.cpp

deleted100644 → 0
+0 −83
Original line number Diff line number Diff line
//
//  Copyright (C) 2015 Google, Inc.
//
//  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.
//

#define LOG_TAG "bt_a2dp_source"

#include "a2dp_source.h"

#include "core_stack.h"
#include "logging_helpers.h"
#include "osi/include/log.h"
#include "osi/include/osi.h"

namespace {

void ConnectionStateCallback(btav_connection_state_t state,
                             UNUSED_ATTR bt_bdaddr_t *bd_addr) {
  LOG_INFO(LOG_TAG, "%s: %s", __func__, BtAvConnectionStateText(state));
}

void AudioStateCallback(btav_audio_state_t state,
                        UNUSED_ATTR bt_bdaddr_t *bd_addr) {
  LOG_INFO(LOG_TAG, "%s: %s", __func__, BtAvAudioStateText(state));
}

void AudioConfigCallback(UNUSED_ATTR bt_bdaddr_t *bd_addr,
                         UNUSED_ATTR uint32_t sample_rate,
                         UNUSED_ATTR uint8_t channel_count) {
  // I think these are used for audio sink only?
  // TODO(icoolidge): revisit.
}

btav_callbacks_t av_callbacks = {
    sizeof(btav_callbacks_t), ConnectionStateCallback, AudioStateCallback,
    AudioConfigCallback,
};

}  // namespace

namespace bluetooth {

A2dpSource::A2dpSource(CoreStack *bt) : av_(nullptr), bt_(bt) {
  // TODO(icoolidge): DCHECK(bt);
}

int A2dpSource::Start() {
  // Get the interface to the a2dp source profile.
  const void *interface = bt_->GetInterface(BT_PROFILE_ADVANCED_AUDIO_ID);
  if (!interface) {
    LOG_ERROR(LOG_TAG, "Error getting audio source interface");
    return -1;
  }

  av_ = reinterpret_cast<const btav_interface_t *>(interface);

  bt_status_t btstat = av_->init(&av_callbacks);
  if (btstat != BT_STATUS_SUCCESS && btstat != BT_STATUS_DONE) {
    LOG_ERROR(LOG_TAG, "Failed to initialize audio source interface: %s %d",
              BtStatusText(btstat), btstat);
    return -1;
  }
  return 0;
}

int A2dpSource::Stop() {
  // TODO(icoolidge): DCHECK(av_);
  av_->cleanup();
  return 0;
}

}  // namespace bluetooth

system/service/a2dp_source.h

deleted100644 → 0
+0 −44
Original line number Diff line number Diff line
//
//  Copyright (C) 2015 Google, Inc.
//
//  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.
//
#pragma once

#include "hardware/bluetooth.h"
#include "hardware/bt_av.h"

namespace bluetooth {

class CoreStack;

// This class is just experimental to test out BlueDroid A2DP
// interface, capability, and functionality.
class A2dpSource {
 public:
  explicit A2dpSource(CoreStack* bt);

  // Enables the A2DP source profile in the stack.
  // Creates audio Unix sockets. (see audio_a2dp_hw.h)
  int Start();

  // Disables the A2DP source profile in the stack.
  int Stop();

 private:
  const btav_interface_t* av_;
  // Weak reference.
  CoreStack* bt_;
};

}  // namespace bluetooth

system/service/core_stack.cpp

deleted100644 → 0
+0 −321
Original line number Diff line number Diff line
//
//  Copyright (C) 2015 Google, Inc.
//
//  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.
//

#define LOG_TAG "bluetooth_daemon"

#include "core_stack.h"

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include <condition_variable>
#include <mutex>
#include <string>

#include <hardware/bluetooth.h>
#include <hardware/hardware.h>

#include "logging_helpers.h"

extern "C" {
#include "btcore/include/hal_util.h"
#include "osi/include/log.h"
#include "osi/include/osi.h"
}  // extern "C"

namespace {

std::mutex mutex;
std::condition_variable synchronize;
bool instantiated = false;

void AdapterStateChangedCallback(bt_state_t state) {
  LOG_INFO(LOG_TAG, "Bluetooth state:%s", BtStateText(state));
  std::lock_guard<std::mutex> lock(mutex);
  synchronize.notify_one();
}

void CallbackThreadCallback(bt_cb_thread_evt evt) {
  LOG_INFO(LOG_TAG, "%s: %s", __func__, BtEventText(evt));
}

// TODO(icoolidge): Audit how these os callouts should be
// implemented (or nulled) for systems w/out wakelocks.
bool SetWakeAlarmCallback(uint64_t delay_millis,
                          UNUSED_ATTR bool should_wake,
                          alarm_cb cb,
                          void *data) {
  static timer_t timer;
  static bool timer_created;

  if (!timer_created) {
    struct sigevent sigevent;
    memset(&sigevent, 0, sizeof(sigevent));
    sigevent.sigev_notify = SIGEV_THREAD;
    sigevent.sigev_notify_function = (void (*)(union sigval))cb;
    sigevent.sigev_value.sival_ptr = data;
    timer_create(CLOCK_MONOTONIC, &sigevent, &timer);
    timer_created = true;
  }

  struct itimerspec new_value;
  new_value.it_value.tv_sec = delay_millis / 1000;
  new_value.it_value.tv_nsec = (delay_millis % 1000) * 1000 * 1000;
  new_value.it_interval.tv_sec = 0;
  new_value.it_interval.tv_nsec = 0;
  timer_settime(timer, 0, &new_value, nullptr);

  return true;
}

// Dummy implementation due to no wakelocks.
int AcquireWakeLock(UNUSED_ATTR const char *lock_name) {
  return BT_STATUS_SUCCESS;
}

// Dummy implementation due to no wakelocks.
int ReleaseWakeLock(UNUSED_ATTR const char *lock_name) {
  return BT_STATUS_SUCCESS;
}

void GenericDevicePropertiesCallback(bt_status_t status,
                                     bt_bdaddr_t *remote_address,
                                     int num_properties,
                                     bt_property_t *properties) {
  if (status != BT_STATUS_SUCCESS) {
    LOG_ERROR(LOG_TAG, "%s: %s", __func__, BtStatusText(status));
    return;
  }

  if (!remote_address) {
    LOG_INFO(LOG_TAG, "%s", "Local adapter properties:");
  }

  for (int i = 0; i < num_properties; ++i) {
    bt_property_t *prop = &properties[i];
    switch (prop->type) {
      case BT_PROPERTY_BDADDR: {
        std::string text =
            BtAddrString(reinterpret_cast<bt_bdaddr_t *>(prop->val));
        LOG_INFO(LOG_TAG, "%s: %s", BtPropertyText(prop->type), text.c_str());
        break;
      }
      case BT_PROPERTY_ADAPTER_SCAN_MODE: {
        bt_scan_mode_t *mode = reinterpret_cast<bt_scan_mode_t *>(prop->val);
        LOG_INFO(LOG_TAG, "%s: %s", BtPropertyText(prop->type), BtScanModeText(*mode));
        std::lock_guard<std::mutex> lock(mutex);
        synchronize.notify_one();
        break;
      }
      case BT_PROPERTY_BDNAME: {
        bt_bdname_t *name = reinterpret_cast<bt_bdname_t *>(prop->val);
        LOG_INFO(LOG_TAG, "%s: %s", BtPropertyText(prop->type),
                 reinterpret_cast<char *>(name->name));
        std::lock_guard<std::mutex> lock(mutex);
        synchronize.notify_one();
        break;
      }
      default:
        LOG_INFO(LOG_TAG, "%s: %s", __func__, BtPropertyText(prop->type));
        break;
    }
  }
}

void AclStateChangedCallback(bt_status_t status, bt_bdaddr_t *remote_bd_addr,
                             bt_acl_state_t state) {
  if (status != BT_STATUS_SUCCESS) {
    LOG_ERROR(LOG_TAG, "%s: %s", __func__, BtStatusText(status));
    return;
  }

  std::string text = BtAddrString(remote_bd_addr);
  LOG_INFO(LOG_TAG, "%s: %s: %s", __func__, text.c_str(), BtAclText(state));
}

void LocalAdapterPropertiesCallback(bt_status_t status, int num_properties,
                                    bt_property_t *properties) {
  GenericDevicePropertiesCallback(status, nullptr, num_properties, properties);
}

bt_callbacks_t bt_callbacks = {
  sizeof(bt_callbacks_t),
  AdapterStateChangedCallback,
  LocalAdapterPropertiesCallback,
  GenericDevicePropertiesCallback,
  nullptr, /* device_found_cb */
  nullptr, /* discovery_state_changed_cb */
  nullptr, /* pin_request_cb  */
  nullptr, /* ssp_request_cb  */
  nullptr, /* bond_state_changed_cb */
  AclStateChangedCallback,
  CallbackThreadCallback,
  nullptr, /* dut_mode_recv_cb */
  nullptr, /* le_test_mode_cb */
  nullptr  /* energy_info_cb */
};

bt_os_callouts_t callouts = {
  sizeof(bt_os_callouts_t),
  SetWakeAlarmCallback,
  AcquireWakeLock,
  ReleaseWakeLock
};

}  // namespace

namespace bluetooth {

// 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 CoreStackImpl::Initialize() {
  std::unique_lock<std::mutex> lock(mutex);

  // Load the bluetooth module.
  const hw_module_t *module;
  int status = hal_util_load_bt_library(&module);
  if (status) {
    LOG_ERROR(LOG_TAG, "Error getting bluetooth module");
    return false;
  }

  // Open the bluetooth device.
  hw_device_t *device;
  status = module->methods->open(module, BT_HARDWARE_MODULE_ID, &device);
  if (status) {
    LOG_ERROR(LOG_TAG, "Error opening bluetooth module");
    return false;
  }

  // TODO(icoolidge): Audit initialization and teardown.
  adapter_ = reinterpret_cast<bluetooth_device_t *>(device);
  hal_ = adapter_->get_bluetooth_interface();

  // Bind module callbacks to local handlers.
  status = hal_->init(&bt_callbacks);
  if (status != BT_STATUS_SUCCESS) {
    LOG_ERROR(LOG_TAG, "Error binding callbacks");
    return false;
  }

  status = hal_->set_os_callouts(&callouts);
  if (status != BT_STATUS_SUCCESS) {
    LOG_ERROR(LOG_TAG, "Error binding OS callbacks");
    return false;
  }

  status = hal_->enable();
  if (status) {
    LOG_ERROR(LOG_TAG, "Enable failed: %d", status);
    return false;
  }

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

bool CoreStackImpl::SetAdapterName(const std::string &name) {
  bt_bdname_t n;
  snprintf(reinterpret_cast<char *>(n.name), sizeof(n.name), "%s",
           name.c_str());
  bt_property_t prop;
  prop.len = sizeof(n);
  prop.val = &n;
  prop.type = BT_PROPERTY_BDNAME;

  std::unique_lock<std::mutex> lock(mutex);

  int status = hal_->set_adapter_property(&prop);
  if (status) {
    LOG_ERROR(LOG_TAG, "%s: prop change failed: %d", __func__, status);
    return false;
  }

  synchronize.wait(lock);
  return true;
}

bool CoreStackImpl::SetClassicDiscoverable() {
  bt_scan_mode_t mode = BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
  bt_property_t disc;
  disc.len = sizeof(mode);
  disc.val = &mode;
  disc.type = BT_PROPERTY_ADAPTER_SCAN_MODE;

  std::unique_lock<std::mutex> lock(mutex);

  int status = hal_->set_adapter_property(&disc);
  if (status) {
    LOG_ERROR(LOG_TAG, "Prop change failed: %d", status);
    return false;
  }

  synchronize.wait(lock);
  return true;
}

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);
  if (!interface) {
    LOG_ERROR(LOG_TAG, "Error getting %s interface", profile);
    return nullptr;
  }
  return interface;
}

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

system/service/core_stack.h

deleted100644 → 0
+0 −57
Original line number Diff line number Diff line
//
//  Copyright (C) 2015 Google, Inc.
//
//  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.
//

#pragma once

#include <memory>
#include <string>

#include <base/macros.h>

namespace bluetooth {

// This represents the core Bluetooth stack,
// with high level operations that affect many profiles.
// It is also used to access profile interfaces.
class CoreStack {
 public:
  virtual ~CoreStack() = default;

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

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

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

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

  // Factory method that creates a real CoreStack instance. This should be used
  // in production code.
  static std::unique_ptr<CoreStack> Create();

 protected:
  CoreStack() = default;

 private:
  DISALLOW_COPY_AND_ASSIGN(CoreStack);
};

}  // namespace bluetooth
Loading