// // 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 #include #include #include #include #include #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 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(property->val); name = reinterpret_cast(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(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(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(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(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(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& 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 lock(observers_lock_); observers_.AddObserver(observer); } void RemoveObserver(Adapter::Observer* observer) override { lock_guard 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(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(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(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 lock(local_le_features_lock_); return local_le_features_.max_adv_instance >= kMinAdvInstancesForMultiAdv; } bool IsDeviceConnected(const std::string& device_address) override { lock_guard lock(connected_devices_lock_); return connected_devices_.find(device_address) != connected_devices_.end(); } int GetTotalNumberOfTrackableAdvertisements() override { lock_guard lock(local_le_features_lock_); return local_le_features_.total_trackable_advertisers; } bool IsOffloadedFilteringSupported() override { lock_guard lock(local_le_features_lock_); return local_le_features_.max_adv_filter_supported >= kMinOffloadedFilters; } bool IsOffloadedScanBatchingSupported() override { lock_guard 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(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(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 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(property->val)); LOG(INFO) << "Adapter address changed: " << address; address_.Set(address); break; } case BT_PROPERTY_BDNAME: { bt_bdname_t* hal_name = reinterpret_cast(property->val); if (hal_name) { std::string name = reinterpret_cast(hal_name->name); LOG(INFO) << "Adapter name changed: " << name; name_.Set(name); } break; } case BT_PROPERTY_LOCAL_LE_FEATURES: { lock_guard 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(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(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 str_addrs; for (size_t i = 0; i < property->len / sizeof(addrs[0]); ++i) str_addrs.push_back(BtAddrString(addrs + i)); lock_guard 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 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 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 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(bd_name->name); lock_guard 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 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 lock(connected_devices_lock_); if (connected) connected_devices_.insert(device_address); else connected_devices_.erase(device_address); } lock_guard 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 lock(observers_lock_); for (auto& observer : observers_) { observer.OnAdapterStateChanged(this, prev_state, new_state); } } private: // The current adapter state. std::atomic 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 observers_; // List of devices addresses that are currently connected. std::mutex connected_devices_lock_; std::unordered_set connected_devices_; // Factory used to create per-app A2dpSink instances. std::unique_ptr a2dp_sink_factory_; // Factory used to create per-app A2dpSource instances. std::unique_ptr a2dp_source_factory_; // Factory used to create per-app AvrcpControl instances. std::unique_ptr avrcp_control_factory_; // Factory used to create per-app AvrcpTarget instances. std::unique_ptr avrcp_target_factory_; // Factory used to create per-app LowEnergyClient instances. std::unique_ptr ble_client_factory_; // Factory used to create per-app LeAdvertiser instances. std::unique_ptr ble_advertiser_factory_; // Factory used to create per-app LeScanner instances. std::unique_ptr ble_scanner_factory_; // Factory used to create per-app GattClient instances. std::unique_ptr gatt_client_factory_; // Factory used to create per-app GattServer instances. std::unique_ptr gatt_server_factory_; DISALLOW_COPY_AND_ASSIGN(AdapterImpl); }; // static std::unique_ptr Adapter::Create() { return std::unique_ptr(new AdapterImpl()); } } // namespace bluetooth