| // |
| // 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 "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); |
| 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) 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_; |
| 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 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 |