#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_client.h"
+
+using std::lock_guard;
+using std::mutex;
namespace bluetooth {
// 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.
-//
-// TODO(armansito): This number comes 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 this number from the stack instead
-// of hardcoding it here.
-const char kMinAdvInstancesForMultiAdv = 5;
+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,
// Default implementation does nothing
}
-Adapter::Adapter()
+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());
- gatt_client_factory_.reset(new GattClientFactory());
- gatt_server_factory_.reset(new GattServerFactory());
- hal::BluetoothInterface::Get()->GetHALInterface()->get_adapter_properties();
-}
-
-Adapter::~Adapter() {
- hal::BluetoothInterface::Get()->RemoveObserver(this);
-}
-
-void Adapter::AddObserver(Observer* observer) {
- std::lock_guard<std::mutex> lock(observers_lock_);
- observers_.AddObserver(observer);
-}
+ memset(&local_le_features_, 0, sizeof(local_le_features_));
+ hal::BluetoothInterface::Get()->AddObserver(this);
+ ble_client_factory_.reset(new LowEnergyClientFactory(*this));
+ gatt_client_factory_.reset(new GattClientFactory());
+ gatt_server_factory_.reset(new GattServerFactory());
+ hal::BluetoothInterface::Get()->GetHALInterface()->get_adapter_properties();
+ }
-void Adapter::RemoveObserver(Observer* observer) {
- std::lock_guard<std::mutex> lock(observers_lock_);
- observers_.RemoveObserver(observer);
-}
+ ~AdapterImpl() override {
+ hal::BluetoothInterface::Get()->RemoveObserver(this);
+ }
-AdapterState Adapter::GetState() const {
- return state_.load();
-}
+ void AddObserver(Adapter::Observer* observer) override {
+ lock_guard<mutex> lock(observers_lock_);
+ observers_.AddObserver(observer);
+ }
-bool Adapter::IsEnabled() const {
- return state_.load() == ADAPTER_STATE_ON;
-}
+ void RemoveObserver(Adapter::Observer* observer) override {
+ lock_guard<mutex> lock(observers_lock_);
+ observers_.RemoveObserver(observer);
+ }
-bool Adapter::Enable() {
- AdapterState current_state = GetState();
- if (current_state != ADAPTER_STATE_OFF) {
- LOG(INFO) << "Adapter not disabled - state: "
- << AdapterStateToString(current_state);
- return false;
+ AdapterState GetState() const override {
+ return state_.load();
}
- // 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;
+ bool IsEnabled() const override {
+ return state_.load() == ADAPTER_STATE_ON;
}
- return true;
-}
+ 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;
+ }
-bool Adapter::Disable() {
- if (!IsEnabled()) {
- LOG(INFO) << "Adapter is not enabled";
- 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;
}
- AdapterState current_state = GetState();
+ bool Disable() override {
+ if (!IsEnabled()) {
+ LOG(INFO) << "Adapter is not enabled";
+ return false;
+ }
- // 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_);
+ AdapterState current_state = GetState();
- 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;
+ // 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;
}
- return true;
-}
+ std::string GetName() const override {
+ return name_.Get();
+ }
-std::string Adapter::GetName() const {
- return name_.Get();
-}
+ bool SetName(const std::string& name) override {
+ bt_bdname_t hal_name;
+ size_t max_name_len = sizeof(hal_name.name);
-bool Adapter::SetName(const std::string& name) {
- 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;
+ }
- // 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);
- strncpy(reinterpret_cast<char*>(hal_name.name), name.c_str(),
- name.length() + 1);
+ VLOG(1) << "Setting adapter name: " << name;
- 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;
+ }
- if (!SetAdapterProperty(BT_PROPERTY_BDNAME, &hal_name, sizeof(hal_name))) {
- LOG(ERROR) << "Failed to set adapter name: " << name;
- return false;
+ return true;
}
- return true;
-}
+ std::string GetAddress() const override {
+ return address_.Get();
+ }
-std::string Adapter::GetAddress() const {
- return address_.Get();
-}
+ bool IsMultiAdvertisementSupported() override {
+ lock_guard<mutex> lock(local_le_features_lock_);
+ return local_le_features_.max_adv_instance >= kMinAdvInstancesForMultiAdv;
+ }
-bool Adapter::IsMultiAdvertisementSupported() const {
- 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();
+ }
-LowEnergyClientFactory* Adapter::GetLowEnergyClientFactory() const {
- return ble_client_factory_.get();
-}
+ int GetTotalNumberOfTrackableAdvertisements() override {
+ lock_guard<mutex> lock(local_le_features_lock_);
+ return local_le_features_.total_trackable_advertisers;
+ }
-GattClientFactory* Adapter::GetGattClientFactory() const {
- return gatt_client_factory_.get();
-}
+ bool IsOffloadedFilteringSupported() override {
+ lock_guard<mutex> lock(local_le_features_lock_);
+ return local_le_features_.max_adv_filter_supported >= kMinOffloadedFilters;
+ }
-GattServerFactory* Adapter::GetGattServerFactory() const {
- return gatt_server_factory_.get();
-}
+ bool IsOffloadedScanBatchingSupported() override {
+ lock_guard<mutex> lock(local_le_features_lock_);
+ return local_le_features_.scan_result_storage_size >=
+ kMinOffloadedScanStorageBytes;
+ }
-void Adapter::AdapterStateChangedCallback(bt_state_t state) {
- LOG(INFO) << "Adapter state changed: " << BtStateText(state);
+ LowEnergyClientFactory* GetLowEnergyClientFactory() const override {
+ return ble_client_factory_.get();
+ }
- AdapterState prev_state = GetState();
+ GattClientFactory* GetGattClientFactory() const override {
+ return gatt_client_factory_.get();
+ }
- switch (state) {
- case BT_STATE_OFF:
- state_ = ADAPTER_STATE_OFF;
- break;
+ GattServerFactory* GetGattServerFactory() const override {
+ return gatt_server_factory_.get();
+ }
- case BT_STATE_ON:
- state_ = ADAPTER_STATE_ON;
- break;
+ // hal::BluetoothInterface::Observer overrides.
+ void AdapterStateChangedCallback(bt_state_t state) override {
+ LOG(INFO) << "Adapter state changed: " << BtStateText(state);
- default:
- NOTREACHED();
- }
+ AdapterState prev_state = GetState();
- NotifyAdapterStateChanged(prev_state, GetState());
-}
+ switch (state) {
+ case BT_STATE_OFF:
+ state_ = ADAPTER_STATE_OFF;
+ break;
+
+ case BT_STATE_ON:
+ state_ = ADAPTER_STATE_ON;
+ break;
-void Adapter::AdapterPropertiesCallback(bt_status_t status,
- int num_properties,
- bt_property_t* properties) {
- LOG(INFO) << "Adapter properties changed";
+ default:
+ NOTREACHED();
+ }
- if (status != BT_STATUS_SUCCESS) {
- LOG(ERROR) << "status: " << BtStatusText(status);
- return;
+ NotifyAdapterStateChanged(prev_state, GetState());
}
- 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<bt_bdaddr_t*>(
- 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: {
- if (property->len != sizeof(bt_local_le_features_t)) {
- LOG(WARNING) << "Malformed value received for property: "
- << "BT_PROPERTY_LOCAL_LE_FEATURES";
+ 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<bt_bdaddr_t*>(
+ property->val));
+ LOG(INFO) << "Adapter address changed: " << address;
+ address_.Set(address);
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_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;
}
- default:
- VLOG(1) << "Unhandled adapter property: "
- << BtPropertyText(property->type);
- break;
+
+ // TODO(armansito): notify others of the updated properties
+ }
+ }
+
+ void AclStateChangedCallback(bt_status_t status,
+ const bt_bdaddr_t& 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);
}
- // TODO(armansito): notify others of the updated properties
+ lock_guard<mutex> lock(observers_lock_);
+ FOR_EACH_OBSERVER(
+ Adapter::Observer, observers_,
+ OnDeviceConnectionStateChanged(this, device_address, connected));
}
-}
-bool Adapter::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;
+ // 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;
}
- 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_;
-void Adapter::NotifyAdapterStateChanged(AdapterState prev_state,
- AdapterState new_state) {
- if (prev_state == new_state)
- return;
+ // List of devices addresses that are currently connected.
+ std::mutex connected_devices_lock_;
+ std::unordered_set<std::string> connected_devices_;
- std::lock_guard<std::mutex> lock(observers_lock_);
- FOR_EACH_OBSERVER(Observer, observers_,
- OnAdapterStateChanged(this, prev_state, new_state));
+ // Factory used to create per-app LowEnergyClient instances.
+ std::unique_ptr<LowEnergyClientFactory> ble_client_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