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.
417 lines
14 KiB
417 lines
14 KiB
// |
|
// 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/adapter.h" |
|
|
|
#include <atomic> |
|
#include <mutex> |
|
#include <string> |
|
#include <unordered_set> |
|
|
|
#include <base/logging.h> |
|
#include <base/observer_list.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 { |
|
|
|
// 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 |
|
} |
|
|
|
// 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); |
|
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(bool start_restricted) 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( |
|
start_restricted); |
|
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 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; |
|
} |
|
|
|
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); |
|
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); |
|
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; |
|
} |
|
default: |
|
VLOG(1) << "Unhandled adapter property: " |
|
<< BtPropertyText(property->type); |
|
break; |
|
} |
|
|
|
// TODO(armansito): notify others of the updated properties |
|
} |
|
} |
|
|
|
void SSPRequestCallback(RawAddress*, bt_bdname_t*, uint32_t, bt_ssp_variant_t, |
|
uint32_t pass_key) override { |
|
LOG(INFO) << "Passkey is: " << pass_key; |
|
} |
|
|
|
void AclStateChangedCallback(bt_status_t status, |
|
const RawAddress& remote_bdaddr, |
|
bt_acl_state_t state) 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_EACH_OBSERVER( |
|
Adapter::Observer, observers_, |
|
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_EACH_OBSERVER(Adapter::Observer, observers_, |
|
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_; |
|
base::ObserverList<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 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
|
|
|