// // 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/hal/bluetooth_interface.h" #include #include #include #include #include "abstract_observer_list.h" #include "service/logging_helpers.h" #include "btcore/include/hal_util.h" using std::lock_guard; using std::unique_lock; using std::shared_lock; using std::mutex; #if defined(OS_GENERIC) && defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION < 3500) using shared_mutex_impl = std::shared_mutex; #else using shared_mutex_impl = std::shared_timed_mutex; #endif namespace bluetooth { namespace hal { namespace { // The global BluetoothInterface instance. BluetoothInterface* g_bluetooth_interface = nullptr; // Mutex used by callbacks to access |g_interface|. If we initialize or clean it // use unique_lock. If only accessing |g_interface| use shared lock. // TODO(jpawlowski): this should be just shared_mutex, as we currently don't use // timed methods. Change to shared_mutex when we upgrade to C++14 shared_mutex_impl g_instance_lock; // Helper for obtaining the observer list. This is forward declared here and // defined below since it depends on BluetoothInterfaceImpl. btbase::AbstractObserverList* GetObservers(); #define FOR_EACH_BLUETOOTH_OBSERVER(func) \ for (auto& observer : *GetObservers()) { \ observer.func; \ } #define VERIFY_INTERFACE_OR_RETURN() \ do { \ if (!g_bluetooth_interface) { \ LOG(WARNING) << "Callback received while |g_interface| is NULL"; \ return; \ } \ } while (0) void AdapterStateChangedCallback(bt_state_t state) { shared_lock lock(g_instance_lock); VERIFY_INTERFACE_OR_RETURN(); VLOG(1) << "Adapter state changed: " << BtStateText(state); FOR_EACH_BLUETOOTH_OBSERVER(AdapterStateChangedCallback(state)); } void AdapterPropertiesCallback(bt_status_t status, int num_properties, bt_property_t* properties) { shared_lock lock(g_instance_lock); VERIFY_INTERFACE_OR_RETURN(); VLOG(1) << "Adapter properties changed - status: " << BtStatusText(status) << ", num_properties: " << num_properties; FOR_EACH_BLUETOOTH_OBSERVER( AdapterPropertiesCallback(status, num_properties, properties)); } void RemoteDevicePropertiesCallback(bt_status_t status, RawAddress* remote_bd_addr, int num_properties, bt_property_t* properties) { shared_lock lock(g_instance_lock); VERIFY_INTERFACE_OR_RETURN(); VLOG(1) << " Remote device properties changed - status: " << BtStatusText(status) << " - BD_ADDR: " << BtAddrString(remote_bd_addr) << ", num_properties: " << num_properties; FOR_EACH_BLUETOOTH_OBSERVER(RemoteDevicePropertiesCallback( status, remote_bd_addr, num_properties, properties)); } void DeviceFoundCallback(int num_properties, bt_property_t* properties) { shared_lock lock(g_instance_lock); VERIFY_INTERFACE_OR_RETURN(); VLOG(1) << " Device found."; FOR_EACH_BLUETOOTH_OBSERVER(DeviceFoundCallback(num_properties, properties)); } void DiscoveryStateChangedCallback(bt_discovery_state_t state) { shared_lock lock(g_instance_lock); VERIFY_INTERFACE_OR_RETURN(); VLOG(1) << "Discovery state changed - state: " << BtDiscoveryStateText(state); FOR_EACH_BLUETOOTH_OBSERVER(DiscoveryStateChangedCallback(state)); } void PinRequestCallback(RawAddress* remote_bd_addr, bt_bdname_t* bd_name, uint32_t cod, bool min_16_digit) { shared_lock lock(g_instance_lock); VERIFY_INTERFACE_OR_RETURN(); VLOG(2) << __func__ << " - remote_bd_addr: " << remote_bd_addr << " - bd_name: " << bd_name << " - cod: " << cod << " - min_16_digit: " << min_16_digit; FOR_EACH_BLUETOOTH_OBSERVER( PinRequestCallback(remote_bd_addr, bd_name, cod, min_16_digit)); } void SSPRequestCallback(RawAddress* remote_bd_addr, bt_bdname_t* bd_name, uint32_t cod, bt_ssp_variant_t pairing_variant, uint32_t pass_key) { shared_lock lock(g_instance_lock); VERIFY_INTERFACE_OR_RETURN(); VLOG(2) << __func__ << " - remote_bd_addr: " << remote_bd_addr << " - bd_name: " << bd_name << " - cod: " << cod << " - pairing_variant: " << pairing_variant; FOR_EACH_BLUETOOTH_OBSERVER(SSPRequestCallback(remote_bd_addr, bd_name, cod, pairing_variant, pass_key)); } void BondStateChangedCallback(bt_status_t status, RawAddress* remote_bd_addr, bt_bond_state_t state) { shared_lock lock(g_instance_lock); VERIFY_INTERFACE_OR_RETURN(); VLOG(2) << __func__ << " - remote_bd_addr: " << BtAddrString(remote_bd_addr) << " - status: " << status << " - state: " << state; FOR_EACH_BLUETOOTH_OBSERVER( BondStateChangedCallback(status, remote_bd_addr, state)); } void AclStateChangedCallback(bt_status_t status, RawAddress* remote_bd_addr, bt_acl_state_t state, bt_hci_error_code_t hci_reason) { shared_lock lock(g_instance_lock); VERIFY_INTERFACE_OR_RETURN(); CHECK(remote_bd_addr); VLOG(1) << "Remote device ACL state changed - status: " << BtStatusText(status) << " - BD_ADDR: " << BtAddrString(remote_bd_addr) << " - state: " << ((state == BT_ACL_STATE_CONNECTED) ? "CONNECTED" : "DISCONNECTED") << " - HCI_REASON: " << std::to_string(hci_reason); FOR_EACH_BLUETOOTH_OBSERVER( AclStateChangedCallback(status, *remote_bd_addr, state, hci_reason)); } void ThreadEventCallback(bt_cb_thread_evt evt) { VLOG(1) << "ThreadEventCallback" << BtEventText(evt); // TODO(armansito): This callback is completely useless to us but btif borks // out if this is not set. Consider making this optional. } bool SetWakeAlarmCallout(uint64_t /* delay_millis */, bool /* should_wake */, alarm_cb /* cb */, void* /* data */) { // TODO(armansito): According to sharvil@, this interface doesn't even need to // exist and can be done entirely from within osi by interfacing directly with // the kernel. Remove these stubs once that's fixed. (See http://b/23390297) return false; } int AcquireWakeLockCallout(const char* /* lock_name */) { // TODO(armansito): According to sharvil@, this interface doesn't even need to // exist and can be done entirely from within osi by interfacing directly with // the kernel. Remove these stubs once that's fixed. (See http://b/23390297) // Lie here and return success so that enabling and disabling the controller // works before this is properly implemented. return BT_STATUS_SUCCESS; } int ReleaseWakeLockCallout(const char* /* lock_name */) { // TODO(armansito): According to sharvil@, this interface doesn't even need to // exist and can be done entirely from within osi by interfacing directly with // the kernel. Remove these stubs once that's fixed. (See http://b/23390297) // Lie here and return success so that enabling and disabling the controller // works before this is properly implemented. return BT_STATUS_SUCCESS; } void LinkQualityReportCallback(uint64_t timestamp, int report_id, int rssi, int snr, int retransmission_count, int packets_not_receive_count, int negative_acknowledgement_count) { shared_lock lock(g_instance_lock); VERIFY_INTERFACE_OR_RETURN(); LOG(WARNING) << __func__ << " - timestamp: " << timestamp << " - report_id: " << report_id << " - rssi: " << rssi << " - snr: " << snr << " - retransmission_count: " << retransmission_count << " - packets_not_receive_count: " << packets_not_receive_count << " - negative_acknowledgement_count: " << negative_acknowledgement_count; FOR_EACH_BLUETOOTH_OBSERVER(LinkQualityReportCallback( timestamp, report_id, rssi, snr, retransmission_count, packets_not_receive_count, negative_acknowledgement_count)); } // The HAL Bluetooth DM callbacks. bt_callbacks_t bt_callbacks = { sizeof(bt_callbacks_t), AdapterStateChangedCallback, AdapterPropertiesCallback, RemoteDevicePropertiesCallback, DeviceFoundCallback, DiscoveryStateChangedCallback, PinRequestCallback, SSPRequestCallback, BondStateChangedCallback, AclStateChangedCallback, ThreadEventCallback, nullptr, /* dut_mode_recv_cb */ nullptr, /* le_test_mode_cb */ nullptr, /* energy_info_cb */ LinkQualityReportCallback, nullptr /* generate_local_oob_data_cb */ }; bt_os_callouts_t bt_os_callouts = {sizeof(bt_os_callouts_t), SetWakeAlarmCallout, AcquireWakeLockCallout, ReleaseWakeLockCallout}; } // namespace // BluetoothInterface implementation for production. class BluetoothInterfaceImpl : public BluetoothInterface { public: BluetoothInterfaceImpl() : hal_iface_(nullptr) {} ~BluetoothInterfaceImpl() override { if (hal_iface_) hal_iface_->cleanup(); } // BluetoothInterface overrides. void AddObserver(Observer* observer) override { shared_lock lock(g_instance_lock); observers_.AddObserver(observer); } void RemoveObserver(Observer* observer) override { shared_lock lock(g_instance_lock); observers_.RemoveObserver(observer); } const bt_interface_t* GetHALInterface() const override { return hal_iface_; } bt_callbacks_t* GetHALCallbacks() const override { return &bt_callbacks; } // Initialize the interface. This loads the shared Bluetooth library and sets // up the callbacks. bool Initialize() { // Load the Bluetooth shared library module. const bt_interface_t* interface; int status = hal_util_load_bt_library(&interface); if (status) { LOG(ERROR) << "Failed to open the Bluetooth module"; return false; } hal_iface_ = interface; // Initialize the Bluetooth interface. Set up the adapter (Bluetooth DM) API // callbacks. status = hal_iface_->init(&bt_callbacks, false, false, 0, nullptr, false); if (status != BT_STATUS_SUCCESS) { LOG(ERROR) << "Failed to initialize Bluetooth stack"; return false; } status = hal_iface_->set_os_callouts(&bt_os_callouts); if (status != BT_STATUS_SUCCESS) { LOG(ERROR) << "Failed to set up Bluetooth OS callouts"; return false; } return true; } btbase::AbstractObserverList* observers() { return &observers_; } private: // List of observers that are interested in notifications from us. We're not // using a base::ObserverListThreadSafe, which it posts observer events // automatically on the origin threads, as we want to avoid that overhead and // simply forward the events to the upper layer. btbase::AbstractObserverList observers_; // The HAL handle obtained from the shared library. We hold a weak reference // to this since the actual data resides in the shared Bluetooth library. const bt_interface_t* hal_iface_; DISALLOW_COPY_AND_ASSIGN(BluetoothInterfaceImpl); }; namespace { // Helper for obtaining the observer list from the global instance. This // function is NOT thread safe. btbase::AbstractObserverList* GetObservers() { CHECK(g_bluetooth_interface); return static_cast(g_bluetooth_interface) ->observers(); } } // namespace // Default observer implementations. These are provided so that the methods // themselves are optional. void BluetoothInterface::Observer::AdapterStateChangedCallback( bt_state_t /* state*/) { // Do nothing. } void BluetoothInterface::Observer::AdapterPropertiesCallback( bt_status_t /* status */, int /* num_properties */, bt_property_t* /* properties */) { // Do nothing. } void BluetoothInterface::Observer::RemoteDevicePropertiesCallback( bt_status_t /* status */, RawAddress* /* remote_bd_addr */, int /* num_properties */, bt_property_t* /* properties */) { // Do nothing. } void BluetoothInterface::Observer::DeviceFoundCallback( int /* num_properties */, bt_property_t* /* properties */) { // Do nothing. } void BluetoothInterface::Observer::DiscoveryStateChangedCallback( bt_discovery_state_t /* state */) { // Do nothing. } void BluetoothInterface::Observer::PinRequestCallback( RawAddress* remote_bd_addr, bt_bdname_t* bd_name, uint32_t cod, bool min_16_digit) { // Do nothing. } void BluetoothInterface::Observer::SSPRequestCallback( RawAddress* remote_bd_addr, bt_bdname_t* bd_name, uint32_t cod, bt_ssp_variant_t pairing_variant, uint32_t pass_key) { // Do nothing. } void BluetoothInterface::Observer::BondStateChangedCallback( bt_status_t status, RawAddress* remote_bd_addr, bt_bond_state_t state) { // Do nothing. } void BluetoothInterface::Observer::AclStateChangedCallback( bt_status_t /* status */, const RawAddress& /* remote_bdaddr */, bt_acl_state_t /* state */, bt_hci_error_code_t /* hci_reason */) { // Do nothing. } void BluetoothInterface::Observer::LinkQualityReportCallback( uint64_t /* timestamp */, int /* report_id */, int /* rssi */, int /* snr */, int /* retransmission_count */, int /* packets_not_receive_count */, int /* negative_acknowledgement_count */) { // Do nothing. } // static bool BluetoothInterface::Initialize() { unique_lock lock(g_instance_lock); CHECK(!g_bluetooth_interface); std::unique_ptr impl(new BluetoothInterfaceImpl()); if (!impl->Initialize()) { LOG(ERROR) << "Failed to initialize BluetoothInterface"; return false; } g_bluetooth_interface = impl.release(); return true; } // static void BluetoothInterface::CleanUp() { unique_lock lock(g_instance_lock); CHECK(g_bluetooth_interface); delete g_bluetooth_interface; g_bluetooth_interface = nullptr; } // static bool BluetoothInterface::IsInitialized() { shared_lock lock(g_instance_lock); return g_bluetooth_interface != nullptr; } // static BluetoothInterface* BluetoothInterface::Get() { shared_lock lock(g_instance_lock); CHECK(g_bluetooth_interface); return g_bluetooth_interface; } // static void BluetoothInterface::InitializeForTesting( BluetoothInterface* test_instance) { unique_lock lock(g_instance_lock); CHECK(test_instance); CHECK(!g_bluetooth_interface); g_bluetooth_interface = test_instance; } } // namespace hal } // namespace bluetooth