//
// 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.
//
#include "service/hal/bluetooth_gatt_interface.h"
#include <mutex>
#include <shared_mutex>
#include <base/logging.h>
#include <base/observer_list.h>
#include "service/hal/bluetooth_interface.h"
#include "service/logging_helpers.h"
using std::lock_guard;
using std::unique_lock;
using std::shared_lock;
using std::mutex;
#if defined(OS_GENERIC) && defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION < 3500)
using shared_mutex_impl = std::shared_mutex;
#else
using shared_mutex_impl = std::shared_timed_mutex;
#endif
namespace bluetooth {
namespace hal {
namespace {
// The global BluetoothGattInterface instance.
BluetoothGattInterface* g_interface = nullptr;
// Mutex used by callbacks to access |g_interface|. If we initialize or clean it
// use unique_lock. If only accessing |g_interface| use shared lock.
// TODO(jpawlowski): this should be just shared_mutex, as we currently don't use
// timed methods. Change to shared_mutex when we upgrade to C++14
shared_mutex_impl g_instance_lock;
// Helper for obtaining the observer lists. This is forward declared here
// and defined below since it depends on BluetoothInterfaceImpl.
base::ObserverList<BluetoothGattInterface::ScannerObserver>*
GetScannerObservers();
base::ObserverList<BluetoothGattInterface::ClientObserver>*
GetClientObservers();
base::ObserverList<BluetoothGattInterface::ServerObserver>*
GetServerObservers();
#define FOR_EACH_SCANNER_OBSERVER(func) \
FOR_EACH_OBSERVER(BluetoothGattInterface::ScannerObserver, \
*GetScannerObservers(), func)
#define FOR_EACH_CLIENT_OBSERVER(func) \
FOR_EACH_OBSERVER(BluetoothGattInterface::ClientObserver, \
*GetClientObservers(), func)
#define FOR_EACH_SERVER_OBSERVER(func) \
FOR_EACH_OBSERVER(BluetoothGattInterface::ServerObserver, \
*GetServerObservers(), func)
#define VERIFY_INTERFACE_OR_RETURN() \
do { \
if (!g_interface) { \
LOG(WARNING) << "Callback received while |g_interface| is NULL"; \
return; \
} \
} while (0)
void RegisterClientCallback(int status, int client_if, bt_uuid_t* app_uuid) {
shared_lock<shared_mutex_impl> lock(g_instance_lock);
VLOG(2) << __func__ << " - status: " << status << " client_if: " << client_if;
VERIFY_INTERFACE_OR_RETURN();
CHECK(app_uuid);
FOR_EACH_CLIENT_OBSERVER(
RegisterClientCallback(g_interface, status, client_if, *app_uuid));
}
void ScanResultCallback(
uint16_t ble_evt_type, uint8_t addr_type, bt_bdaddr_t* bda,
uint8_t ble_primary_phy, uint8_t ble_secondary_phy,
uint8_t ble_advertising_sid, int8_t ble_tx_power, int8_t rssi,
uint16_t ble_periodic_adv_int,
std::vector<uint8_t> adv_data) { // NOLINT(pass-by-value)
shared_lock<shared_mutex_impl> lock(g_instance_lock);
VERIFY_INTERFACE_OR_RETURN();
CHECK(bda);
VLOG(2) << __func__ << " - BD_ADDR: " << BtAddrString(bda)
<< " RSSI: " << rssi;
FOR_EACH_SCANNER_OBSERVER(
ScanResultCallback(g_interface, *bda, rssi, adv_data));
}
void ConnectCallback(int conn_id, int status, int client_if, bt_bdaddr_t* bda) {
shared_lock<shared_mutex_impl> lock(g_instance_lock);
VERIFY_INTERFACE_OR_RETURN();
CHECK(bda);
VLOG(2) << __func__ << " - status: " << status << " client_if: " << client_if
<< " - BD_ADDR: " << BtAddrString(bda) << " - conn_id: " << conn_id;
FOR_EACH_CLIENT_OBSERVER(
ConnectCallback(g_interface, conn_id, status, client_if, *bda));
}
void DisconnectCallback(int conn_id, int status, int client_if,
bt_bdaddr_t* bda) {
shared_lock<shared_mutex_impl> lock(g_instance_lock);
VERIFY_INTERFACE_OR_RETURN();
CHECK(bda);
VLOG(2) << __func__ << " - conn_id: " << conn_id << " - status: " << status
<< " client_if: " << client_if << " - BD_ADDR: " << BtAddrString(bda);
FOR_EACH_CLIENT_OBSERVER(
DisconnectCallback(g_interface, conn_id, status, client_if, *bda));
}
void SearchCompleteCallback(int conn_id, int status) {
shared_lock<shared_mutex_impl> lock(g_instance_lock);
VERIFY_INTERFACE_OR_RETURN();
VLOG(2) << __func__ << " - conn_id: " << conn_id << " - status: " << status;
FOR_EACH_CLIENT_OBSERVER(
SearchCompleteCallback(g_interface, conn_id, status));
}
void RegisterForNotificationCallback(int conn_id, int registered, int status,
uint16_t handle) {
shared_lock<shared_mutex_impl> lock(g_instance_lock);
VERIFY_INTERFACE_OR_RETURN();
LOG(INFO) << __func__ << " - conn_id: " << conn_id << " - status: " << status
<< " - registered: " << registered << " - handle: " << handle;
FOR_EACH_CLIENT_OBSERVER(RegisterForNotificationCallback(
g_interface, conn_id, status, registered, handle));
}
void NotifyCallback(int conn_id, btgatt_notify_params_t* p_data) {
shared_lock<shared_mutex_impl> lock(g_instance_lock);
VERIFY_INTERFACE_OR_RETURN();
VLOG(2) << __func__ << " - conn_id: " << conn_id
<< " - address: " << BtAddrString(&p_data->bda)
<< " - handle: " << p_data->handle << " - len: " << p_data->len
<< " - is_notify: " << p_data->is_notify;
FOR_EACH_CLIENT_OBSERVER(NotifyCallback(g_interface, conn_id, p_data));
}
void WriteCharacteristicCallback(int conn_id, int status, uint16_t handle) {
shared_lock<shared_mutex_impl> lock(g_instance_lock);
VERIFY_INTERFACE_OR_RETURN();
VLOG(2) << __func__ << " - conn_id: " << conn_id << " - status: " << status;
FOR_EACH_CLIENT_OBSERVER(
WriteCharacteristicCallback(g_interface, conn_id, status, handle));
}
void WriteDescriptorCallback(int conn_id, int status, uint16_t handle) {
shared_lock<shared_mutex_impl> lock(g_instance_lock);
VERIFY_INTERFACE_OR_RETURN();
VLOG(2) << __func__ << " - conn_id: " << conn_id << " - status: " << status;
FOR_EACH_CLIENT_OBSERVER(
WriteDescriptorCallback(g_interface, conn_id, status, handle));
}
void MtuChangedCallback(int conn_id, int status, int mtu) {
shared_lock<shared_mutex_impl> lock(g_instance_lock);
VERIFY_INTERFACE_OR_RETURN();
VLOG(2) << __func__ << " - conn_id: " << conn_id << " status: " << status
<< " mtu: " << mtu;
FOR_EACH_CLIENT_OBSERVER(
MtuChangedCallback(g_interface, conn_id, status, mtu));
}
void GetGattDbCallback(int conn_id, btgatt_db_element_t* db, int size) {
shared_lock<shared_mutex_impl> lock(g_instance_lock);
VLOG(2) << __func__ << " - conn_id: " << conn_id << " size: " << size;
VERIFY_INTERFACE_OR_RETURN();
FOR_EACH_CLIENT_OBSERVER(GetGattDbCallback(g_interface, conn_id, db, size));
}
void ServicesRemovedCallback(int conn_id, uint16_t start_handle,
uint16_t end_handle) {
shared_lock<shared_mutex_impl> lock(g_instance_lock);
VLOG(2) << __func__ << " - conn_id: " << conn_id
<< " start_handle: " << start_handle << " end_handle: " << end_handle;
VERIFY_INTERFACE_OR_RETURN();
FOR_EACH_CLIENT_OBSERVER(
ServicesRemovedCallback(g_interface, conn_id, start_handle, end_handle));
}
void ServicesAddedCallback(int conn_id, btgatt_db_element_t* added,
int added_count) {
shared_lock<shared_mutex_impl> lock(g_instance_lock);
VLOG(2) << __func__ << " - conn_id: " << conn_id
<< " added_count: " << added_count;
VERIFY_INTERFACE_OR_RETURN();
FOR_EACH_CLIENT_OBSERVER(
ServicesAddedCallback(g_interface, conn_id, added, added_count));
}
void RegisterServerCallback(int status, int server_if, bt_uuid_t* app_uuid) {
shared_lock<shared_mutex_impl> lock(g_instance_lock);
VLOG(2) << __func__ << " - status: " << status << " server_if: " << server_if;
VERIFY_INTERFACE_OR_RETURN();
CHECK(app_uuid);
FOR_EACH_SERVER_OBSERVER(
RegisterServerCallback(g_interface, status, server_if, *app_uuid));
}
void ConnectionCallback(int conn_id, int server_if, int connected,
bt_bdaddr_t* bda) {
shared_lock<shared_mutex_impl> lock(g_instance_lock);
VLOG(2) << __func__ << " - conn_id: " << conn_id
<< " server_if: " << server_if << " connected: " << connected;
VERIFY_INTERFACE_OR_RETURN();
CHECK(bda);
FOR_EACH_SERVER_OBSERVER(
ConnectionCallback(g_interface, conn_id, server_if, connected, *bda));
}
void ServiceAddedCallback(
int status, int server_if,
std::vector<btgatt_db_element_t> service) { // NOLINT(pass-by-value)
shared_lock<shared_mutex_impl> lock(g_instance_lock);
VLOG(2) << __func__ << " - status: " << status << " server_if: " << server_if
<< " count: " << service.size();
VERIFY_INTERFACE_OR_RETURN();
CHECK(service.size());
FOR_EACH_SERVER_OBSERVER(
ServiceAddedCallback(g_interface, status, server_if, service));
}
void ServiceStoppedCallback(int status, int server_if, int srvc_handle) {
shared_lock<shared_mutex_impl> lock(g_instance_lock);
VLOG(2) << __func__ << " - status: " << status << " server_if: " << server_if
<< " handle: " << srvc_handle;
VERIFY_INTERFACE_OR_RETURN();
FOR_EACH_SERVER_OBSERVER(
ServiceStoppedCallback(g_interface, status, server_if, srvc_handle));
}
void ServiceDeletedCallback(int status, int server_if, int srvc_handle) {
shared_lock<shared_mutex_impl> lock(g_instance_lock);
VLOG(2) << __func__ << " - status: " << status << " server_if: " << server_if
<< " handle: " << srvc_handle;
VERIFY_INTERFACE_OR_RETURN();
FOR_EACH_SERVER_OBSERVER(
ServiceDeletedCallback(g_interface, status, server_if, srvc_handle));
}
void RequestReadCharacteristicCallback(int conn_id, int trans_id,
bt_bdaddr_t* bda, int attr_handle,
int offset, bool is_long) {
shared_lock<shared_mutex_impl> lock(g_instance_lock);
VLOG(2) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
<< " attr_handle: " << attr_handle << " offset: " << offset
<< " is_long: " << is_long;
VERIFY_INTERFACE_OR_RETURN();
CHECK(bda);
FOR_EACH_SERVER_OBSERVER(RequestReadCharacteristicCallback(
g_interface, conn_id, trans_id, *bda, attr_handle, offset, is_long));
}
void RequestReadDescriptorCallback(int conn_id, int trans_id, bt_bdaddr_t* bda,
int attr_handle, int offset, bool is_long) {
shared_lock<shared_mutex_impl> lock(g_instance_lock);
VLOG(2) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
<< " attr_handle: " << attr_handle << " offset: " << offset
<< " is_long: " << is_long;
VERIFY_INTERFACE_OR_RETURN();
CHECK(bda);
FOR_EACH_SERVER_OBSERVER(RequestReadDescriptorCallback(
g_interface, conn_id, trans_id, *bda, attr_handle, offset, is_long));
}
void RequestWriteCharacteristicCallback(int conn_id, int trans_id,
bt_bdaddr_t* bda, int attr_handle,
int offset, bool need_rsp, bool is_prep,
std::vector<uint8_t> value) {
shared_lock<shared_mutex_impl> lock(g_instance_lock);
VLOG(2) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
<< " attr_handle: " << attr_handle << " offset: " << offset
<< " length: " << value.size() << " need_rsp: " << need_rsp
<< " is_prep: " << is_prep;
VERIFY_INTERFACE_OR_RETURN();
CHECK(bda);
FOR_EACH_SERVER_OBSERVER(RequestWriteCharacteristicCallback(
g_interface, conn_id, trans_id, *bda, attr_handle, offset, need_rsp,
is_prep, value));
}
void RequestWriteDescriptorCallback(
int conn_id, int trans_id, bt_bdaddr_t* bda, int attr_handle, int offset,
bool need_rsp, bool is_prep,
std::vector<uint8_t> value) { // NOLINT(pass-by-value)
shared_lock<shared_mutex_impl> lock(g_instance_lock);
VLOG(2) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
<< " attr_handle: " << attr_handle << " offset: " << offset
<< " length: " << value.size() << " need_rsp: " << need_rsp
<< " is_prep: " << is_prep;
VERIFY_INTERFACE_OR_RETURN();
CHECK(bda);
FOR_EACH_SERVER_OBSERVER(RequestWriteDescriptorCallback(
g_interface, conn_id, trans_id, *bda, attr_handle, offset, need_rsp,
is_prep, value));
}
void RequestExecWriteCallback(int conn_id, int trans_id, bt_bdaddr_t* bda,
int exec_write) {
shared_lock<shared_mutex_impl> lock(g_instance_lock);
VLOG(2) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
<< " exec_write: " << exec_write;
VERIFY_INTERFACE_OR_RETURN();
CHECK(bda);
FOR_EACH_SERVER_OBSERVER(RequestExecWriteCallback(
g_interface, conn_id, trans_id, *bda, exec_write));
}
void ResponseConfirmationCallback(int status, int handle) {
shared_lock<shared_mutex_impl> lock(g_instance_lock);
VLOG(2) << __func__ << " - status: " << status << " handle: " << handle;
VERIFY_INTERFACE_OR_RETURN();
FOR_EACH_SERVER_OBSERVER(
ResponseConfirmationCallback(g_interface, status, handle));
}
void IndicationSentCallback(int conn_id, int status) {
shared_lock<shared_mutex_impl> lock(g_instance_lock);
VLOG(2) << __func__ << " - conn_id: " << conn_id << " status: " << status;
VERIFY_INTERFACE_OR_RETURN();
FOR_EACH_SERVER_OBSERVER(
IndicationSentCallback(g_interface, conn_id, status));
}
void MtuChangedCallback(int conn_id, int mtu) {
shared_lock<shared_mutex_impl> lock(g_instance_lock);
VLOG(2) << __func__ << " - conn_id: " << conn_id << " mtu: " << mtu;
VERIFY_INTERFACE_OR_RETURN();
FOR_EACH_SERVER_OBSERVER(MtuChangedCallback(g_interface, conn_id, mtu));
}
// The HAL Bluetooth GATT client interface callbacks. These signal a mixture of
// GATT client-role and GAP events.
const btgatt_scanner_callbacks_t gatt_scanner_callbacks = {
ScanResultCallback,
nullptr, // batchscan_reports_cb
nullptr, // batchscan_threshold_cb
nullptr, // track_adv_event_cb
};
const btgatt_client_callbacks_t gatt_client_callbacks = {
RegisterClientCallback,
ConnectCallback,
DisconnectCallback,
SearchCompleteCallback,
RegisterForNotificationCallback,
NotifyCallback,
nullptr, // read_characteristic_cb
WriteCharacteristicCallback,
nullptr, // read_descriptor_cb
WriteDescriptorCallback,
nullptr, // execute_write_cb
nullptr, // read_remote_rssi_cb
MtuChangedCallback,
nullptr, // congestion_cb
GetGattDbCallback,
ServicesRemovedCallback,
ServicesAddedCallback,
nullptr,
nullptr,
};
const btgatt_server_callbacks_t gatt_server_callbacks = {
RegisterServerCallback,
ConnectionCallback,
ServiceAddedCallback,
ServiceStoppedCallback,
ServiceDeletedCallback,
RequestReadCharacteristicCallback,
RequestReadDescriptorCallback,
RequestWriteCharacteristicCallback,
RequestWriteDescriptorCallback,
RequestExecWriteCallback,
ResponseConfirmationCallback,
IndicationSentCallback,
nullptr, // congestion_cb
MtuChangedCallback,
nullptr,
nullptr,
};
const btgatt_callbacks_t gatt_callbacks = {
sizeof(btgatt_callbacks_t), &gatt_client_callbacks, &gatt_server_callbacks,
&gatt_scanner_callbacks,
};
} // namespace
// BluetoothGattInterface implementation for production.
class BluetoothGattInterfaceImpl : public BluetoothGattInterface {
public:
BluetoothGattInterfaceImpl() : hal_iface_(nullptr) {}
~BluetoothGattInterfaceImpl() override {
if (hal_iface_) hal_iface_->cleanup();
}
void AddScannerObserver(ScannerObserver* observer) override {
scanner_observers_.AddObserver(observer);
}
void RemoveScannerObserver(ScannerObserver* observer) override {
scanner_observers_.RemoveObserver(observer);
}
void AddClientObserver(ClientObserver* observer) override {
client_observers_.AddObserver(observer);
}
void RemoveClientObserver(ClientObserver* observer) override {
client_observers_.RemoveObserver(observer);
}
void AddServerObserver(ServerObserver* observer) override {
server_observers_.AddObserver(observer);
}
void RemoveServerObserver(ServerObserver* observer) override {
server_observers_.RemoveObserver(observer);
}
BleAdvertiserInterface* GetAdvertiserHALInterface() const override {
return hal_iface_->advertiser;
}
BleScannerInterface* GetScannerHALInterface() const override {
return hal_iface_->scanner;
}
const btgatt_client_interface_t* GetClientHALInterface() const override {
return hal_iface_->client;
}
const btgatt_server_interface_t* GetServerHALInterface() const override {
return hal_iface_->server;
}
// Initialize the interface.
bool Initialize() {
const bt_interface_t* bt_iface =
BluetoothInterface::Get()->GetHALInterface();
CHECK(bt_iface);
const btgatt_interface_t* gatt_iface =
reinterpret_cast<const btgatt_interface_t*>(
bt_iface->get_profile_interface(BT_PROFILE_GATT_ID));
if (!gatt_iface) {
LOG(ERROR) << "Failed to obtain HAL GATT interface handle";
return false;
}
bt_status_t status = gatt_iface->init(&gatt_callbacks);
if (status != BT_STATUS_SUCCESS) {
LOG(ERROR) << "Failed to initialize HAL GATT interface";
return false;
}
hal_iface_ = gatt_iface;
return true;
}
base::ObserverList<ScannerObserver>* scanner_observers() {
return &scanner_observers_;
}
base::ObserverList<ClientObserver>* client_observers() {
return &client_observers_;
}
base::ObserverList<ServerObserver>* server_observers() {
return &server_observers_;
}
private:
// List of observers that are interested in notifications from us.
// We're not using a base::ObserverListThreadSafe, which it posts observer
// events automatically on the origin threads, as we want to avoid that
// overhead and simply forward the events to the upper layer.
base::ObserverList<ScannerObserver> scanner_observers_;
base::ObserverList<ClientObserver> client_observers_;
base::ObserverList<ServerObserver> server_observers_;
// The HAL handle obtained from the shared library. We hold a weak reference
// to this since the actual data resides in the shared Bluetooth library.
const btgatt_interface_t* hal_iface_;
DISALLOW_COPY_AND_ASSIGN(BluetoothGattInterfaceImpl);
};
namespace {
base::ObserverList<BluetoothGattInterface::ScannerObserver>*
GetScannerObservers() {
CHECK(g_interface);
return static_cast<BluetoothGattInterfaceImpl*>(g_interface)
->scanner_observers();
}
base::ObserverList<BluetoothGattInterface::ClientObserver>*
GetClientObservers() {
CHECK(g_interface);
return static_cast<BluetoothGattInterfaceImpl*>(g_interface)
->client_observers();
}
base::ObserverList<BluetoothGattInterface::ServerObserver>*
GetServerObservers() {
CHECK(g_interface);
return static_cast<BluetoothGattInterfaceImpl*>(g_interface)
->server_observers();
}
} // namespace
// Default observer implementations. These are provided so that the methods
// themselves are optional.
void BluetoothGattInterface::ScannerObserver::ScanResultCallback(
BluetoothGattInterface* /* gatt_iface */, const bt_bdaddr_t& /* bda */,
int /* rssi */,
std::vector<uint8_t> /* adv_data */) { // NOLINT(pass-by-value)
// Do Nothing.
}
void BluetoothGattInterface::ClientObserver::RegisterClientCallback(
BluetoothGattInterface* /* gatt_iface */, int /* status */,
int /* client_if */, const bt_uuid_t& /* app_uuid */) {
// Do nothing.
}
void BluetoothGattInterface::ClientObserver::ConnectCallback(
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
int /* status */, int /* client_if */, const bt_bdaddr_t& /* bda */) {
// Do nothing
}
void BluetoothGattInterface::ClientObserver::DisconnectCallback(
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
int /* status */, int /* client_if */, const bt_bdaddr_t& /* bda */) {
// Do nothing
}
void BluetoothGattInterface::ClientObserver::SearchCompleteCallback(
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
int /* status */) {
// Do nothing
}
void BluetoothGattInterface::ClientObserver::RegisterForNotificationCallback(
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
int /* status */, int /* registered */, uint16_t /* handle */) {
// Do nothing
}
void BluetoothGattInterface::ClientObserver::NotifyCallback(
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
btgatt_notify_params_t* /* p_data */) {
// Do nothing
}
void BluetoothGattInterface::ClientObserver::WriteCharacteristicCallback(
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
int /* status */, uint16_t /* handle */) {
// Do nothing
}
void BluetoothGattInterface::ClientObserver::WriteDescriptorCallback(
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
int /* status */, uint16_t /* handle */) {
// Do nothing
}
void BluetoothGattInterface::ClientObserver::MtuChangedCallback(
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
int /* statis*/, int /* mtu */) {
// Do nothing.
}
void BluetoothGattInterface::ClientObserver::GetGattDbCallback(
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
btgatt_db_element_t* /* gatt_db */, int /* size */) {
// Do nothing.
}
void BluetoothGattInterface::ClientObserver::ServicesRemovedCallback(
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
uint16_t /* start_handle */, uint16_t /* end_handle */) {
// Do nothing.
}
void BluetoothGattInterface::ClientObserver::ServicesAddedCallback(
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
btgatt_db_element_t* /* added */, int /* added_count */) {
// Do nothing.
}
void BluetoothGattInterface::ServerObserver::RegisterServerCallback(
BluetoothGattInterface* /* gatt_iface */, int /* status */,
int /* server_if */, const bt_uuid_t& /* app_uuid */) {
// Do nothing.
}
void BluetoothGattInterface::ServerObserver::ConnectionCallback(
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
int /* server_if */, int /* connected */, const bt_bdaddr_t& /* bda */) {
// Do nothing.
}
void BluetoothGattInterface::ServerObserver::ServiceAddedCallback(
BluetoothGattInterface* /* gatt_iface */, int /* status */,
int /* server_if */,
std::vector<btgatt_db_element_t> /* service */) { // NOLINT(pass-by-value)
// Do nothing.
}
void BluetoothGattInterface::ServerObserver::ServiceStoppedCallback(
BluetoothGattInterface* /* gatt_iface */, int /* status */,
int /* server_if */, int /* srvc_handle */) {
// Do nothing.
}
void BluetoothGattInterface::ServerObserver::ServiceDeletedCallback(
BluetoothGattInterface* /* gatt_iface */, int /* status */,
int /* server_if */, int /* srvc_handle */) {
// Do nothing.
}
void BluetoothGattInterface::ServerObserver::RequestReadCharacteristicCallback(
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
int /* trans_id */, const bt_bdaddr_t& /* bda */, int /* attr_handle */,
int /* offset */, bool /* is_long */) {
// Do nothing.
}
void BluetoothGattInterface::ServerObserver::RequestReadDescriptorCallback(
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
int /* trans_id */, const bt_bdaddr_t& /* bda */, int /* attr_handle */,
int /* offset */, bool /* is_long */) {
// Do nothing.
}
void BluetoothGattInterface::ServerObserver::RequestWriteCharacteristicCallback(
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
int /* trans_id */, const bt_bdaddr_t& /* bda */, int /* attr_handle */,
int /* offset */, bool /* need_rsp */, bool /* is_prep */,
std::vector<uint8_t> /* value */) { // NOLINT(pass-by-value)
// Do nothing.
}
void BluetoothGattInterface::ServerObserver::RequestWriteDescriptorCallback(
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
int /* trans_id */, const bt_bdaddr_t& /* bda */, int /* attr_handle */,
int /* offset */, bool /* need_rsp */, bool /* is_prep */,
std::vector<uint8_t> /* value */) { // NOLINT(pass-by-value)
// Do nothing.
}
void BluetoothGattInterface::ServerObserver::RequestExecWriteCallback(
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
int /* trans_id */, const bt_bdaddr_t& /* bda */, int /* exec_write */) {
// Do nothing.
}
void BluetoothGattInterface::ServerObserver::ResponseConfirmationCallback(
BluetoothGattInterface* /* gatt_iface */, int /* status */,
int /* handle */) {
// Do nothing
}
void BluetoothGattInterface::ServerObserver::IndicationSentCallback(
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
int /* status */) {
// Do nothing.
}
void BluetoothGattInterface::ServerObserver::MtuChangedCallback(
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
int /* mtu */) {
// Do nothing.
}
// static
bool BluetoothGattInterface::Initialize() {
unique_lock<shared_mutex_impl> lock(g_instance_lock);
CHECK(!g_interface);
std::unique_ptr<BluetoothGattInterfaceImpl> impl(
new BluetoothGattInterfaceImpl());
if (!impl->Initialize()) {
LOG(ERROR) << "Failed to initialize BluetoothGattInterface";
return false;
}
g_interface = impl.release();
return true;
}
// static
void BluetoothGattInterface::CleanUp() {
unique_lock<shared_mutex_impl> lock(g_instance_lock);
CHECK(g_interface);
delete g_interface;
g_interface = nullptr;
}
// static
bool BluetoothGattInterface::IsInitialized() {
shared_lock<shared_mutex_impl> lock(g_instance_lock);
return g_interface != nullptr;
}
// static
BluetoothGattInterface* BluetoothGattInterface::Get() {
shared_lock<shared_mutex_impl> lock(g_instance_lock);
CHECK(g_interface);
return g_interface;
}
// static
void BluetoothGattInterface::InitializeForTesting(
BluetoothGattInterface* test_instance) {
unique_lock<shared_mutex_impl> lock(g_instance_lock);
CHECK(test_instance);
CHECK(!g_interface);
g_interface = test_instance;
}
bt_status_t BluetoothGattInterface::StartScan(int client_id) {
lock_guard<mutex> lock(scan_clients_lock_);
// Scan already initiated for this client.
if (scan_client_set_.find(client_id) != scan_client_set_.end()) {
// Assume starting scan multiple times is not error, but warn user.
LOG(WARNING) << "Scan already initiated for client";
return BT_STATUS_SUCCESS;
}
// If this is the first scan client, then make a call into the stack. We
// only do this when the reference count changes to or from 0.
if (scan_client_set_.empty()) {
GetScannerHALInterface()->Scan(true);
}
scan_client_set_.insert(client_id);
return BT_STATUS_SUCCESS;
}
bt_status_t BluetoothGattInterface::StopScan(int client_id) {
lock_guard<mutex> lock(scan_clients_lock_);
// Scan not initiated for this client.
auto iter = scan_client_set_.find(client_id);
if (iter == scan_client_set_.end()) {
// Assume stopping scan multiple times is not error, but warn user.
LOG(WARNING) << "Scan already stopped or not initiated for client";
return BT_STATUS_SUCCESS;
}
if (scan_client_set_.size() == 1) {
GetScannerHALInterface()->Scan(false);
}
scan_client_set_.erase(iter);
return BT_STATUS_SUCCESS;
}
} // namespace hal
} // namespace bluetooth