You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
810 lines
26 KiB
810 lines
26 KiB
//
|
|
// Copyright 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/adapter.h"
|
|
|
|
#include <atomic>
|
|
#include <mutex>
|
|
#include <string>
|
|
#include <unordered_set>
|
|
|
|
#include <base/logging.h>
|
|
#include <base/observer_list.h>
|
|
|
|
#include "abstract_observer_list.h"
|
|
#include "service/a2dp_sink.h"
|
|
#include "service/a2dp_source.h"
|
|
#include "service/avrcp_control.h"
|
|
#include "service/avrcp_target.h"
|
|
#include "service/common/bluetooth/util/atomic_string.h"
|
|
#include "service/gatt_client.h"
|
|
#include "service/gatt_server.h"
|
|
#include "service/hal/bluetooth_interface.h"
|
|
#include "service/logging_helpers.h"
|
|
#include "service/low_energy_advertiser.h"
|
|
#include "service/low_energy_client.h"
|
|
#include "service/low_energy_scanner.h"
|
|
|
|
using std::lock_guard;
|
|
using std::mutex;
|
|
|
|
namespace bluetooth {
|
|
|
|
namespace {
|
|
|
|
RemoteDeviceProps ParseRemoteDeviceProps(int num_properties,
|
|
bt_property_t* properties) {
|
|
std::string name;
|
|
std::string address;
|
|
std::vector<Uuid> service_uuids;
|
|
int32_t device_class = 0;
|
|
int32_t device_type = 0;
|
|
int32_t rssi = 0;
|
|
|
|
for (int i = 0; i < num_properties; ++i) {
|
|
bt_property_t* property = properties + i;
|
|
switch (property->type) {
|
|
case BT_PROPERTY_BDNAME: {
|
|
if (property->len < 0) {
|
|
NOTREACHED() << "Invalid length for BT_PROPERTY_BDNAME";
|
|
break;
|
|
}
|
|
bt_bdname_t* hal_name = reinterpret_cast<bt_bdname_t*>(property->val);
|
|
name = reinterpret_cast<char*>(hal_name->name);
|
|
break;
|
|
}
|
|
case BT_PROPERTY_BDADDR: {
|
|
if (property->len != sizeof(RawAddress)) {
|
|
NOTREACHED() << "Invalid length for BT_PROPERTY_BDADDR";
|
|
break;
|
|
}
|
|
address = BtAddrString(reinterpret_cast<RawAddress*>(property->val));
|
|
break;
|
|
}
|
|
case BT_PROPERTY_UUIDS: {
|
|
if (property->len < 0) {
|
|
NOTREACHED() << "Negative length on BT_PROPERTY_UUIDS:";
|
|
break;
|
|
}
|
|
if (property->len % sizeof(Uuid) != 0) {
|
|
NOTREACHED() << "Trailing bytes on BT_PROPERTY_UUIDS:";
|
|
}
|
|
auto uuids = static_cast<const Uuid*>(property->val);
|
|
|
|
for (size_t i = 0; i < property->len / sizeof(Uuid); ++i) {
|
|
service_uuids.push_back(uuids[i]);
|
|
}
|
|
break;
|
|
}
|
|
case BT_PROPERTY_CLASS_OF_DEVICE: {
|
|
if (property->len != sizeof(int32_t)) {
|
|
NOTREACHED() << "Invalid length for BT_PROPERTY_CLASS_OF_DEVICE";
|
|
break;
|
|
}
|
|
device_class = *reinterpret_cast<const int32_t*>(property->val);
|
|
break;
|
|
}
|
|
case BT_PROPERTY_TYPE_OF_DEVICE: {
|
|
if (property->len != sizeof(int32_t)) {
|
|
NOTREACHED() << "Invalid length for BT_PROPERTY_TYPE_OF_DEVICE";
|
|
break;
|
|
}
|
|
device_type = *reinterpret_cast<const int32_t*>(property->val);
|
|
break;
|
|
}
|
|
case BT_PROPERTY_REMOTE_RSSI: {
|
|
if (property->len != sizeof(int8_t)) {
|
|
NOTREACHED() << "Invalid length for BT_PROPERTY_REMOTE_RSSI";
|
|
break;
|
|
}
|
|
rssi = *reinterpret_cast<const int8_t*>(property->val);
|
|
break;
|
|
}
|
|
default:
|
|
VLOG(1) << "Unhandled adapter property: "
|
|
<< BtPropertyText(property->type);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return RemoteDeviceProps(name, address, service_uuids, device_class,
|
|
device_type, rssi);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
// static
|
|
const char Adapter::kDefaultAddress[] = "00:00:00:00:00:00";
|
|
// static
|
|
const char Adapter::kDefaultName[] = "not-initialized";
|
|
|
|
// TODO(armansito): The following constants come straight from
|
|
// packages/apps/Bluetooth/src/c/a/b/btservice/AdapterService.java. It would be
|
|
// nice to know if there were a way to obtain these values from the stack
|
|
// instead of hardcoding them here.
|
|
|
|
// The minimum number of advertising instances required for multi-advertisement
|
|
// support.
|
|
const int kMinAdvInstancesForMultiAdv = 5;
|
|
|
|
// Used when determining if offloaded scan filtering is supported.
|
|
const int kMinOffloadedFilters = 10;
|
|
|
|
// Used when determining if offloaded scan batching is supported.
|
|
const int kMinOffloadedScanStorageBytes = 1024;
|
|
|
|
void Adapter::Observer::OnAdapterStateChanged(Adapter* adapter,
|
|
AdapterState prev_state,
|
|
AdapterState new_state) {
|
|
// Default implementation does nothing
|
|
}
|
|
|
|
void Adapter::Observer::OnDeviceConnectionStateChanged(
|
|
Adapter* adapter, const std::string& device_address, bool connected) {
|
|
// Default implementation does nothing
|
|
}
|
|
|
|
void Adapter::Observer::OnScanEnableChanged(Adapter* adapter,
|
|
bool scan_enabled) {
|
|
// Default implementation does nothing
|
|
}
|
|
|
|
void Adapter::Observer::OnSspRequest(Adapter* adapter,
|
|
const std::string& device_address,
|
|
const std::string& device_name, int cod,
|
|
int pairing_variant, int pass_key) {
|
|
// Default implementation does nothing
|
|
}
|
|
|
|
void Adapter::Observer::OnBondStateChanged(Adapter* adapter, int status,
|
|
const std::string& device_address,
|
|
int state) {
|
|
// Default implementation does nothing
|
|
}
|
|
|
|
void Adapter::Observer::OnGetBondedDevices(
|
|
Adapter* adapter, int status,
|
|
const std::vector<std::string>& bonded_devices) {
|
|
// Default implementation does nothing
|
|
}
|
|
|
|
void Adapter::Observer::OnGetRemoteDeviceProperties(
|
|
Adapter* adapter, int status, const std::string& device_address,
|
|
const RemoteDeviceProps& properties) {
|
|
// Default implementation does nothing
|
|
}
|
|
|
|
void Adapter::Observer::OnDeviceFound(Adapter* adapter,
|
|
const RemoteDeviceProps& properties) {
|
|
// Default implementation does nothing
|
|
}
|
|
|
|
// The real Adapter implementation used in production.
|
|
class AdapterImpl : public Adapter, public hal::BluetoothInterface::Observer {
|
|
public:
|
|
AdapterImpl()
|
|
: state_(ADAPTER_STATE_OFF),
|
|
address_(kDefaultAddress),
|
|
name_(kDefaultName) {
|
|
memset(&local_le_features_, 0, sizeof(local_le_features_));
|
|
hal::BluetoothInterface::Get()->AddObserver(this);
|
|
a2dp_sink_factory_.reset(new A2dpSinkFactory);
|
|
a2dp_source_factory_.reset(new A2dpSourceFactory);
|
|
avrcp_control_factory_.reset(new AvrcpControlFactory);
|
|
avrcp_target_factory_.reset(new AvrcpTargetFactory);
|
|
ble_client_factory_.reset(new LowEnergyClientFactory(*this));
|
|
ble_advertiser_factory_.reset(new LowEnergyAdvertiserFactory());
|
|
ble_scanner_factory_.reset(new LowEnergyScannerFactory(*this));
|
|
gatt_client_factory_.reset(new GattClientFactory());
|
|
gatt_server_factory_.reset(new GattServerFactory());
|
|
hal::BluetoothInterface::Get()->GetHALInterface()->get_adapter_properties();
|
|
}
|
|
|
|
~AdapterImpl() override {
|
|
hal::BluetoothInterface::Get()->RemoveObserver(this);
|
|
}
|
|
|
|
void AddObserver(Adapter::Observer* observer) override {
|
|
lock_guard<mutex> lock(observers_lock_);
|
|
observers_.AddObserver(observer);
|
|
}
|
|
|
|
void RemoveObserver(Adapter::Observer* observer) override {
|
|
lock_guard<mutex> lock(observers_lock_);
|
|
observers_.RemoveObserver(observer);
|
|
}
|
|
|
|
AdapterState GetState() const override { return state_.load(); }
|
|
|
|
bool IsEnabled() const override { return state_.load() == ADAPTER_STATE_ON; }
|
|
|
|
bool Enable() override {
|
|
AdapterState current_state = GetState();
|
|
if (current_state != ADAPTER_STATE_OFF) {
|
|
LOG(INFO) << "Adapter not disabled - state: "
|
|
<< AdapterStateToString(current_state);
|
|
return false;
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Disable() override {
|
|
if (!IsEnabled()) {
|
|
LOG(INFO) << "Adapter is not enabled";
|
|
return false;
|
|
}
|
|
|
|
AdapterState current_state = GetState();
|
|
|
|
// 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;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
std::string GetName() const override { return name_.Get(); }
|
|
|
|
bool SetName(const std::string& name) override {
|
|
bt_bdname_t hal_name;
|
|
size_t max_name_len = sizeof(hal_name.name);
|
|
|
|
// Include the \0 byte in size measurement.
|
|
if (name.length() >= max_name_len) {
|
|
LOG(ERROR) << "Given name \"" << name << "\" is larger than maximum"
|
|
<< " allowed size: " << max_name_len;
|
|
return false;
|
|
}
|
|
|
|
strncpy(reinterpret_cast<char*>(hal_name.name), name.c_str(),
|
|
name.length() + 1);
|
|
|
|
VLOG(1) << "Setting adapter name: " << name;
|
|
|
|
if (!SetAdapterProperty(BT_PROPERTY_BDNAME, &hal_name, sizeof(hal_name))) {
|
|
LOG(ERROR) << "Failed to set adapter name: " << name;
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
std::string GetAddress() const override { return address_.Get(); }
|
|
|
|
bool SetScanMode(int scan_mode) override {
|
|
switch (scan_mode) {
|
|
case BT_SCAN_MODE_NONE:
|
|
case BT_SCAN_MODE_CONNECTABLE:
|
|
case BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE:
|
|
break;
|
|
default:
|
|
LOG(ERROR) << "Unknown scan mode: " << scan_mode;
|
|
return false;
|
|
}
|
|
|
|
auto bd_scanmode = static_cast<bt_scan_mode_t>(scan_mode);
|
|
|
|
if (!SetAdapterProperty(BT_PROPERTY_ADAPTER_SCAN_MODE, &bd_scanmode,
|
|
sizeof(bd_scanmode))) {
|
|
LOG(ERROR) << "Failed to set scan mode to : " << scan_mode;
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool SetScanEnable(bool scan_enable) override {
|
|
if (scan_enable) {
|
|
int status =
|
|
hal::BluetoothInterface::Get()->GetHALInterface()->start_discovery();
|
|
if (status != BT_STATUS_SUCCESS) {
|
|
LOG(ERROR) << "Failed to enable scanning";
|
|
return false;
|
|
}
|
|
} else {
|
|
int status =
|
|
hal::BluetoothInterface::Get()->GetHALInterface()->cancel_discovery();
|
|
if (status != BT_STATUS_SUCCESS) {
|
|
LOG(ERROR) << "Failed to disable scanning";
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool SspReply(const std::string& device_address, int variant, bool accept,
|
|
int32_t pass_key) override {
|
|
RawAddress addr;
|
|
if (!RawAddress::FromString(device_address, addr)) {
|
|
LOG(ERROR) << "Invalid device address given: " << device_address;
|
|
return false;
|
|
}
|
|
|
|
int status = hal::BluetoothInterface::Get()->GetHALInterface()->ssp_reply(
|
|
&addr, static_cast<bt_ssp_variant_t>(variant), accept, pass_key);
|
|
if (status != BT_STATUS_SUCCESS) {
|
|
LOG(ERROR) << "Failed to send SSP response - status: "
|
|
<< BtStatusText((const bt_status_t)status);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CreateBond(const std::string& device_address, int transport) override {
|
|
RawAddress addr;
|
|
if (!RawAddress::FromString(device_address, addr)) {
|
|
LOG(ERROR) << "Invalid device address given: " << device_address;
|
|
return false;
|
|
}
|
|
|
|
int status = hal::BluetoothInterface::Get()->GetHALInterface()->create_bond(
|
|
&addr, transport);
|
|
if (status != BT_STATUS_SUCCESS) {
|
|
LOG(ERROR) << "Failed to create bond - status: "
|
|
<< BtStatusText((const bt_status_t)status);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool IsMultiAdvertisementSupported() override {
|
|
lock_guard<mutex> lock(local_le_features_lock_);
|
|
return local_le_features_.max_adv_instance >= kMinAdvInstancesForMultiAdv;
|
|
}
|
|
|
|
bool IsDeviceConnected(const std::string& device_address) override {
|
|
lock_guard<mutex> lock(connected_devices_lock_);
|
|
return connected_devices_.find(device_address) != connected_devices_.end();
|
|
}
|
|
|
|
int GetTotalNumberOfTrackableAdvertisements() override {
|
|
lock_guard<mutex> lock(local_le_features_lock_);
|
|
return local_le_features_.total_trackable_advertisers;
|
|
}
|
|
|
|
bool IsOffloadedFilteringSupported() override {
|
|
lock_guard<mutex> lock(local_le_features_lock_);
|
|
return local_le_features_.max_adv_filter_supported >= kMinOffloadedFilters;
|
|
}
|
|
|
|
bool IsOffloadedScanBatchingSupported() override {
|
|
lock_guard<mutex> lock(local_le_features_lock_);
|
|
return local_le_features_.scan_result_storage_size >=
|
|
kMinOffloadedScanStorageBytes;
|
|
}
|
|
|
|
bool GetBondedDevices() override {
|
|
int status =
|
|
hal::BluetoothInterface::Get()->GetHALInterface()->get_adapter_property(
|
|
BT_PROPERTY_ADAPTER_BONDED_DEVICES);
|
|
if (status != BT_STATUS_SUCCESS) {
|
|
LOG(ERROR) << "Failed to get bonded devices. Status: "
|
|
<< BtStatusText(static_cast<bt_status_t>(status));
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool RemoveBond(const std::string& device_address) override {
|
|
RawAddress addr;
|
|
if (!RawAddress::FromString(device_address, addr)) {
|
|
LOG(ERROR) << "Invalid device address given: " << device_address;
|
|
return false;
|
|
}
|
|
|
|
int status =
|
|
hal::BluetoothInterface::Get()->GetHALInterface()->remove_bond(&addr);
|
|
if (status != BT_STATUS_SUCCESS) {
|
|
LOG(ERROR) << "Failed to send remove bond - status: "
|
|
<< BtStatusText(static_cast<bt_status_t>(status));
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool GetRemoteDeviceProperties(const std::string& device_address) override {
|
|
RawAddress addr;
|
|
if (!RawAddress::FromString(device_address, addr)) {
|
|
LOG(ERROR) << "Invalid device address given: " << device_address;
|
|
return false;
|
|
}
|
|
|
|
int status = hal::BluetoothInterface::Get()
|
|
->GetHALInterface()
|
|
->get_remote_device_properties(&addr);
|
|
if (status != BT_STATUS_SUCCESS) {
|
|
LOG(ERROR) << "Failed to send GetRemoteDeviceProperties - status: "
|
|
<< BtStatusText((const bt_status_t)status);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
A2dpSinkFactory* GetA2dpSinkFactory() const override {
|
|
return a2dp_sink_factory_.get();
|
|
}
|
|
|
|
A2dpSourceFactory* GetA2dpSourceFactory() const override {
|
|
return a2dp_source_factory_.get();
|
|
}
|
|
|
|
AvrcpControlFactory* GetAvrcpControlFactory() const override {
|
|
return avrcp_control_factory_.get();
|
|
}
|
|
|
|
AvrcpTargetFactory* GetAvrcpTargetFactory() const override {
|
|
return avrcp_target_factory_.get();
|
|
}
|
|
|
|
LowEnergyClientFactory* GetLowEnergyClientFactory() const override {
|
|
return ble_client_factory_.get();
|
|
}
|
|
|
|
LowEnergyAdvertiserFactory* GetLeAdvertiserFactory() const override {
|
|
return ble_advertiser_factory_.get();
|
|
}
|
|
|
|
LowEnergyScannerFactory* GetLeScannerFactory() const override {
|
|
return ble_scanner_factory_.get();
|
|
}
|
|
|
|
GattClientFactory* GetGattClientFactory() const override {
|
|
return gatt_client_factory_.get();
|
|
}
|
|
|
|
GattServerFactory* GetGattServerFactory() const override {
|
|
return gatt_server_factory_.get();
|
|
}
|
|
|
|
// hal::BluetoothInterface::Observer overrides.
|
|
void AdapterStateChangedCallback(bt_state_t state) override {
|
|
LOG(INFO) << "Adapter state changed: " << BtStateText(state);
|
|
|
|
AdapterState prev_state = GetState();
|
|
|
|
switch (state) {
|
|
case BT_STATE_OFF:
|
|
state_ = ADAPTER_STATE_OFF;
|
|
break;
|
|
|
|
case BT_STATE_ON:
|
|
state_ = ADAPTER_STATE_ON;
|
|
break;
|
|
|
|
default:
|
|
NOTREACHED();
|
|
}
|
|
|
|
NotifyAdapterStateChanged(prev_state, GetState());
|
|
}
|
|
|
|
void AdapterPropertiesCallback(bt_status_t status, int num_properties,
|
|
bt_property_t* properties) override {
|
|
LOG(INFO) << "Adapter properties changed";
|
|
|
|
if (status != BT_STATUS_SUCCESS) {
|
|
LOG(ERROR) << "status: " << BtStatusText(status);
|
|
|
|
for (int i = 0; i < num_properties; ++i) {
|
|
bt_property_t* property = properties + i;
|
|
if (property->type == BT_PROPERTY_ADAPTER_BONDED_DEVICES) {
|
|
lock_guard<mutex> lock(observers_lock_);
|
|
for (auto& observer : observers_) {
|
|
observer.OnGetBondedDevices(this, status, {});
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < num_properties; i++) {
|
|
bt_property_t* property = properties + i;
|
|
switch (property->type) {
|
|
case BT_PROPERTY_BDADDR: {
|
|
std::string address =
|
|
BtAddrString(reinterpret_cast<RawAddress*>(property->val));
|
|
LOG(INFO) << "Adapter address changed: " << address;
|
|
address_.Set(address);
|
|
break;
|
|
}
|
|
case BT_PROPERTY_BDNAME: {
|
|
bt_bdname_t* hal_name = reinterpret_cast<bt_bdname_t*>(property->val);
|
|
if (hal_name) {
|
|
std::string name = reinterpret_cast<char*>(hal_name->name);
|
|
LOG(INFO) << "Adapter name changed: " << name;
|
|
name_.Set(name);
|
|
}
|
|
break;
|
|
}
|
|
case BT_PROPERTY_LOCAL_LE_FEATURES: {
|
|
lock_guard<mutex> lock(local_le_features_lock_);
|
|
if (property->len != sizeof(bt_local_le_features_t)) {
|
|
LOG(WARNING) << "Malformed value received for property: "
|
|
<< "BT_PROPERTY_LOCAL_LE_FEATURES";
|
|
break;
|
|
}
|
|
bt_local_le_features_t* features =
|
|
reinterpret_cast<bt_local_le_features_t*>(property->val);
|
|
memcpy(&local_le_features_, features, sizeof(*features));
|
|
LOG(INFO) << "Supported LE features updated";
|
|
break;
|
|
}
|
|
case BT_PROPERTY_ADAPTER_BONDED_DEVICES: {
|
|
if (property->len < 0) {
|
|
NOTREACHED() << "Negative property length";
|
|
break;
|
|
}
|
|
auto addrs = reinterpret_cast<const RawAddress*>(property->val);
|
|
if (property->len % sizeof(addrs[0]) != 0) {
|
|
LOG(ERROR) << "Invalid property length: " << property->len;
|
|
// TODO(bcf): Seems to be a bug where we hit this somewhat
|
|
// frequently.
|
|
break;
|
|
}
|
|
std::vector<std::string> str_addrs;
|
|
|
|
for (size_t i = 0; i < property->len / sizeof(addrs[0]); ++i)
|
|
str_addrs.push_back(BtAddrString(addrs + i));
|
|
|
|
lock_guard<mutex> lock(observers_lock_);
|
|
for (auto& observer : observers_) {
|
|
observer.OnGetBondedDevices(this, status, str_addrs);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
VLOG(1) << "Unhandled adapter property: "
|
|
<< BtPropertyText(property->type);
|
|
break;
|
|
}
|
|
|
|
// TODO(armansito): notify others of the updated properties
|
|
}
|
|
}
|
|
|
|
void RemoteDevicePropertiesCallback(bt_status_t status,
|
|
RawAddress* remote_bdaddr,
|
|
int num_properties,
|
|
bt_property_t* properties) override {
|
|
std::string device_address = BtAddrString(remote_bdaddr);
|
|
if (status != BT_STATUS_SUCCESS) {
|
|
lock_guard<mutex> lock(observers_lock_);
|
|
for (auto& observer : observers_) {
|
|
observer.OnGetRemoteDeviceProperties(this, status, device_address,
|
|
RemoteDeviceProps());
|
|
}
|
|
return;
|
|
}
|
|
|
|
RemoteDeviceProps props =
|
|
ParseRemoteDeviceProps(num_properties, properties);
|
|
|
|
std::string address = BtAddrString(remote_bdaddr);
|
|
props.set_address(address);
|
|
|
|
lock_guard<mutex> lock(observers_lock_);
|
|
for (auto& observer : observers_) {
|
|
observer.OnGetRemoteDeviceProperties(this, status, device_address, props);
|
|
}
|
|
}
|
|
|
|
void DeviceFoundCallback(int num_properties,
|
|
bt_property_t* properties) override {
|
|
RemoteDeviceProps props =
|
|
ParseRemoteDeviceProps(num_properties, properties);
|
|
|
|
lock_guard<mutex> lock(observers_lock_);
|
|
for (auto& observer : observers_) {
|
|
observer.OnDeviceFound(this, props);
|
|
}
|
|
}
|
|
|
|
void DiscoveryStateChangedCallback(bt_discovery_state_t state) override {
|
|
bool enabled = false;
|
|
switch (state) {
|
|
case BT_DISCOVERY_STOPPED:
|
|
enabled = false;
|
|
break;
|
|
case BT_DISCOVERY_STARTED:
|
|
enabled = true;
|
|
break;
|
|
default:
|
|
NOTREACHED();
|
|
}
|
|
|
|
for (auto& observer : observers_) {
|
|
observer.OnScanEnableChanged(this, enabled);
|
|
}
|
|
}
|
|
|
|
void SSPRequestCallback(RawAddress* remote_bdaddr, bt_bdname_t* bd_name,
|
|
uint32_t cod, bt_ssp_variant_t pairing_variant,
|
|
uint32_t pass_key) override {
|
|
std::string device_address = BtAddrString(remote_bdaddr);
|
|
std::string name = reinterpret_cast<char*>(bd_name->name);
|
|
|
|
lock_guard<mutex> lock(observers_lock_);
|
|
for (auto& observer : observers_) {
|
|
observer.OnSspRequest(this, device_address, name, cod, pairing_variant,
|
|
pass_key);
|
|
}
|
|
}
|
|
|
|
void BondStateChangedCallback(bt_status_t status, RawAddress* remote_bdaddr,
|
|
bt_bond_state_t state) override {
|
|
std::string device_address = BtAddrString(remote_bdaddr);
|
|
|
|
lock_guard<mutex> lock(observers_lock_);
|
|
for (auto& observer : observers_) {
|
|
observer.OnBondStateChanged(this, status, device_address, state);
|
|
}
|
|
}
|
|
|
|
void AclStateChangedCallback(bt_status_t status,
|
|
const RawAddress& remote_bdaddr,
|
|
bt_acl_state_t state,
|
|
bt_hci_error_code_t hci_reason) override {
|
|
std::string device_address = BtAddrString(&remote_bdaddr);
|
|
bool connected = (state == BT_ACL_STATE_CONNECTED);
|
|
LOG(INFO) << "ACL state changed: " << device_address
|
|
<< " - connected: " << (connected ? "true" : "false");
|
|
|
|
// If this is reported with an error status, I suppose the best thing we can
|
|
// do is to log it and ignore the event.
|
|
if (status != BT_STATUS_SUCCESS) {
|
|
LOG(ERROR) << "status: " << BtStatusText(status);
|
|
return;
|
|
}
|
|
|
|
// Introduce a scope to manage |connected_devices_lock_| with RAII.
|
|
{
|
|
lock_guard<mutex> lock(connected_devices_lock_);
|
|
if (connected)
|
|
connected_devices_.insert(device_address);
|
|
else
|
|
connected_devices_.erase(device_address);
|
|
}
|
|
|
|
lock_guard<mutex> lock(observers_lock_);
|
|
for (auto& observer : observers_) {
|
|
observer.OnDeviceConnectionStateChanged(this, device_address, connected);
|
|
}
|
|
}
|
|
|
|
// Sends a request to set the given HAL adapter property type and value.
|
|
bool SetAdapterProperty(bt_property_type_t type, void* value, int length) {
|
|
CHECK(length > 0);
|
|
CHECK(value);
|
|
|
|
bt_property_t property;
|
|
property.len = length;
|
|
property.val = value;
|
|
property.type = type;
|
|
|
|
int status =
|
|
hal::BluetoothInterface::Get()->GetHALInterface()->set_adapter_property(
|
|
&property);
|
|
if (status != BT_STATUS_SUCCESS) {
|
|
VLOG(1) << "Failed to set property";
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Helper for invoking the AdapterStateChanged observer method.
|
|
void NotifyAdapterStateChanged(AdapterState prev_state,
|
|
AdapterState new_state) {
|
|
if (prev_state == new_state) return;
|
|
|
|
lock_guard<mutex> lock(observers_lock_);
|
|
for (auto& observer : observers_) {
|
|
observer.OnAdapterStateChanged(this, prev_state, new_state);
|
|
}
|
|
}
|
|
|
|
private:
|
|
// The current adapter state.
|
|
std::atomic<AdapterState> state_;
|
|
|
|
// The Bluetooth device address of the local adapter in string from
|
|
// (i.e.. XX:XX:XX:XX:XX:XX)
|
|
util::AtomicString address_;
|
|
|
|
// The current local adapter name.
|
|
util::AtomicString name_;
|
|
|
|
// The current set of supported LE features as obtained from the stack. The
|
|
// values here are all initially set to 0 and updated when the corresponding
|
|
// adapter property has been received from the stack.
|
|
std::mutex local_le_features_lock_;
|
|
bt_local_le_features_t local_le_features_;
|
|
|
|
// List of observers that are interested in notifications from us.
|
|
std::mutex observers_lock_;
|
|
btbase::AbstractObserverList<Adapter::Observer> observers_;
|
|
|
|
// List of devices addresses that are currently connected.
|
|
std::mutex connected_devices_lock_;
|
|
std::unordered_set<std::string> connected_devices_;
|
|
|
|
// Factory used to create per-app A2dpSink instances.
|
|
std::unique_ptr<A2dpSinkFactory> a2dp_sink_factory_;
|
|
|
|
// Factory used to create per-app A2dpSource instances.
|
|
std::unique_ptr<A2dpSourceFactory> a2dp_source_factory_;
|
|
|
|
// Factory used to create per-app AvrcpControl instances.
|
|
std::unique_ptr<AvrcpControlFactory> avrcp_control_factory_;
|
|
|
|
// Factory used to create per-app AvrcpTarget instances.
|
|
std::unique_ptr<AvrcpTargetFactory> avrcp_target_factory_;
|
|
|
|
// Factory used to create per-app LowEnergyClient instances.
|
|
std::unique_ptr<LowEnergyClientFactory> ble_client_factory_;
|
|
|
|
// Factory used to create per-app LeAdvertiser instances.
|
|
std::unique_ptr<LowEnergyAdvertiserFactory> ble_advertiser_factory_;
|
|
|
|
// Factory used to create per-app LeScanner instances.
|
|
std::unique_ptr<LowEnergyScannerFactory> ble_scanner_factory_;
|
|
|
|
// Factory used to create per-app GattClient instances.
|
|
std::unique_ptr<GattClientFactory> gatt_client_factory_;
|
|
|
|
// Factory used to create per-app GattServer instances.
|
|
std::unique_ptr<GattServerFactory> gatt_server_factory_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(AdapterImpl);
|
|
};
|
|
|
|
// static
|
|
std::unique_ptr<Adapter> Adapter::Create() {
|
|
return std::unique_ptr<Adapter>(new AdapterImpl());
|
|
}
|
|
|
|
} // namespace bluetooth
|