Loading system/service/ipc/binder/bluetooth_low_energy_binder_server.cpp +6 −0 Original line number Diff line number Diff line Loading @@ -168,6 +168,12 @@ bool BluetoothLowEnergyBinderServer::StopMultiAdvertising(int client_id) { return true; } void BluetoothLowEnergyBinderServer::OnConnectionState( bluetooth::LowEnergyClient* client, int status, const char* address, bool connected) { VLOG(2) << __func__ << " address: " << address << " connected: " << connected; } void BluetoothLowEnergyBinderServer::OnScanResult( bluetooth::LowEnergyClient* client, const bluetooth::ScanResult& result) { Loading system/service/ipc/binder/bluetooth_low_energy_binder_server.h +2 −0 Original line number Diff line number Diff line Loading @@ -60,6 +60,8 @@ class BluetoothLowEnergyBinderServer bool StopMultiAdvertising(int client_id) override; // bluetooth::LowEnergyClient::Delegate overrides: void OnConnectionState(bluetooth::LowEnergyClient* client, int status, const char* address, bool connected) override; void OnScanResult(bluetooth::LowEnergyClient* client, const bluetooth::ScanResult& result) override; Loading system/service/low_energy_client.cpp +86 −2 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <base/logging.h> #include "service/adapter.h" #include "service/common/bluetooth/util/address_helper.h" #include "service/logging_helpers.h" #include "stack/include/bt_types.h" #include "stack/include/hcidefs.h" Loading Loading @@ -334,6 +335,49 @@ LowEnergyClient::~LowEnergyClient() { StopScan(); } bool LowEnergyClient::Connect(std::string address, bool is_direct) { VLOG(2) << __func__ << "Address: " << address << " is_direct: " << is_direct; bt_bdaddr_t bda; util::BdAddrFromString(address, &bda); bt_status_t status = hal::BluetoothGattInterface::Get()-> GetClientHALInterface()->connect(client_id_, &bda, is_direct, BT_TRANSPORT_LE); if (status != BT_STATUS_SUCCESS) { LOG(ERROR) << "HAL call to connect failed"; return false; } return true; } bool LowEnergyClient::Disconnect(std::string address) { VLOG(2) << __func__ << "Address: " << address; bt_bdaddr_t bda; util::BdAddrFromString(address, &bda); std::map<const bt_bdaddr_t, int>::iterator conn_id; { lock_guard<mutex> lock(connection_fields_lock_); conn_id = connection_ids_.find(bda); if (conn_id == connection_ids_.end()) { LOG(WARNING) << "Can't disconnect, no existing connection to " << address; return false; } } bt_status_t status = hal::BluetoothGattInterface::Get()-> GetClientHALInterface()->disconnect(client_id_, &bda, conn_id->second); if (status != BT_STATUS_SUCCESS) { LOG(ERROR) << "HAL call to disconnect failed"; return false; } return true; } void LowEnergyClient::SetDelegate(Delegate* delegate) { lock_guard<mutex> lock(delegate_mutex_); delegate_ = delegate; Loading Loading @@ -513,6 +557,46 @@ void LowEnergyClient::ScanResultCallback( delegate_->OnScanResult(this, result); } void LowEnergyClient::ConnectCallback( hal::BluetoothGattInterface* gatt_iface, int conn_id, int status, int client_id, const bt_bdaddr_t& bda) { if (client_id != client_id_) return; VLOG(1) << __func__ << "client_id: " << client_id << " status: " << status; { lock_guard<mutex> lock(connection_fields_lock_); auto success = connection_ids_.emplace(bda, conn_id); if (!success.second) { LOG(ERROR) << __func__ << " Insertion into connection_ids_ failed!"; } } if (delegate_) delegate_->OnConnectionState(this, status, BtAddrString(&bda).c_str(), true); } void LowEnergyClient::DisconnectCallback( hal::BluetoothGattInterface* gatt_iface, int conn_id, int status, int client_id, const bt_bdaddr_t& bda) { if (client_id != client_id_) return; VLOG(1) << __func__ << " client_id: " << client_id << " status: " << status; { lock_guard<mutex> lock(connection_fields_lock_); if (!connection_ids_.erase(bda)) { LOG(ERROR) << __func__ << " Erasing from connection_ids_ failed!"; } } if (delegate_) delegate_->OnConnectionState(this, status, BtAddrString(&bda).c_str(), false); } void LowEnergyClient::MultiAdvEnableCallback( hal::BluetoothGattInterface* gatt_iface, int client_id, int status) { Loading system/service/low_energy_client.h +33 −1 Original line number Diff line number Diff line Loading @@ -35,6 +35,12 @@ namespace bluetooth { struct ConnComparator { bool operator()(const bt_bdaddr_t& a, const bt_bdaddr_t& b) const { return memcmp(&a, &b, sizeof(bt_bdaddr_t)) < 0; } }; class Adapter; // A LowEnergyClient represents an application's handle to perform various Loading @@ -55,6 +61,10 @@ class LowEnergyClient : private hal::BluetoothGattInterface::ClientObserver, virtual void OnScanResult(LowEnergyClient* client, const ScanResult& scan_result) = 0; // Called asynchronously to notify the delegate of connection state change virtual void OnConnectionState(LowEnergyClient* client, int status, const char* address, bool connected) = 0; private: DISALLOW_COPY_AND_ASSIGN(Delegate); }; Loading @@ -70,6 +80,15 @@ class LowEnergyClient : private hal::BluetoothGattInterface::ClientObserver, // Callback type used to return the result of asynchronous operations below. using StatusCallback = std::function<void(BLEStatus)>; // Initiates a BLE connection do device with address |address|. If // |is_direct| is set, use direct connect procedure. Return true on success //, false otherwise. bool Connect(std::string address, bool is_direct); // Disconnect from previously connected BLE device with address |address|. // Return true on success, false otherwise. bool Disconnect(std::string address); // Initiates a BLE device scan for this client using the given |settings| and // |filters|. See the documentation for ScanSettings and ScanFilter for how // these parameters can be configured. Return true on success, false Loading Loading @@ -123,6 +142,13 @@ class LowEnergyClient : private hal::BluetoothGattInterface::ClientObserver, void ScanResultCallback( hal::BluetoothGattInterface* gatt_iface, const bt_bdaddr_t& bda, int rssi, uint8_t* adv_data) override; void ConnectCallback( hal::BluetoothGattInterface* gatt_iface, int conn_id, int status, int client_id, const bt_bdaddr_t& bda) override; void DisconnectCallback( hal::BluetoothGattInterface* gatt_iface, int conn_id, int status, int client_id, const bt_bdaddr_t& bda) override; void MultiAdvEnableCallback( hal::BluetoothGattInterface* gatt_iface, int client_id, int status) override; Loading Loading @@ -190,6 +216,12 @@ class LowEnergyClient : private hal::BluetoothGattInterface::ClientObserver, std::mutex delegate_mutex_; Delegate* delegate_; // Protects device connection related members below. std::mutex connection_fields_lock_; // Maps bluetooth address to connection id std::map<const bt_bdaddr_t, int, ConnComparator> connection_ids_; DISALLOW_COPY_AND_ASSIGN(LowEnergyClient); }; Loading system/service/test/low_energy_client_unittest.cpp +72 −4 Original line number Diff line number Diff line Loading @@ -27,6 +27,9 @@ using ::testing::_; using ::testing::Return; using ::testing::Pointee; using ::testing::DoAll; using ::testing::Invoke; namespace bluetooth { namespace { Loading Loading @@ -74,7 +77,7 @@ class MockGattHandler class TestDelegate : public LowEnergyClient::Delegate { public: TestDelegate() : scan_result_count_(0) { TestDelegate() : scan_result_count_(0), connection_state_count_(0) { } ~TestDelegate() override = default; Loading @@ -82,6 +85,14 @@ class TestDelegate : public LowEnergyClient::Delegate { int scan_result_count() const { return scan_result_count_; } const ScanResult& last_scan_result() const { return last_scan_result_; } int connection_state_count() const { return connection_state_count_; } void OnConnectionState(LowEnergyClient* client, int status, const char* address, bool connected) { ASSERT_TRUE(client); connection_state_count_++; } void OnScanResult(LowEnergyClient* client, const ScanResult& scan_result) { ASSERT_TRUE(client); scan_result_count_++; Loading @@ -92,6 +103,8 @@ class TestDelegate : public LowEnergyClient::Delegate { int scan_result_count_; ScanResult last_scan_result_; int connection_state_count_; DISALLOW_COPY_AND_ASSIGN(TestDelegate); }; Loading Loading @@ -937,5 +950,60 @@ TEST_F(LowEnergyClientPostRegisterTest, ScanRecord) { le_client_->SetDelegate(nullptr); } MATCHER_P(BitEq, x, std::string(negation ? "isn't" : "is") + " bitwise equal to " + ::testing::PrintToString(x)) { static_assert(sizeof(x) == sizeof(arg), "Size mismatch"); return std::memcmp(&arg, &x, sizeof(x)) == 0; } TEST_F(LowEnergyClientPostRegisterTest, Connect) { const bt_bdaddr_t kTestAddress = { { 0x01, 0x02, 0x03, 0x0A, 0x0B, 0x0C } }; const char kTestAddressStr[] = "01:02:03:0A:0B:0C"; const bool kTestDirect = false; const int connId = 12; TestDelegate delegate; le_client_->SetDelegate(&delegate); // TODO(jpawlowski): NotifyConnectCallback should be called after returning // success, fix it when it becomes important. // These should succeed and result in a HAL call EXPECT_CALL(*mock_handler_, Connect(le_client_->GetInstanceId(), Pointee(BitEq(kTestAddress)), kTestDirect, BT_TRANSPORT_LE)) .Times(1) .WillOnce(DoAll( Invoke([&](int client_id, const bt_bdaddr_t *bd_addr, bool is_direct, int transport){ fake_hal_gatt_iface_->NotifyConnectCallback(connId, BT_STATUS_SUCCESS, client_id, *bd_addr); }), Return(BT_STATUS_SUCCESS))); EXPECT_TRUE(le_client_->Connect(kTestAddressStr, kTestDirect)); EXPECT_EQ(1, delegate.connection_state_count()); // TODO(jpawlowski): same as above // These should succeed and result in a HAL call EXPECT_CALL(*mock_handler_, Disconnect(le_client_->GetInstanceId(), Pointee(BitEq(kTestAddress)), connId)) .Times(1) .WillOnce(DoAll( Invoke([&](int client_id, const bt_bdaddr_t *bd_addr, int connId){ fake_hal_gatt_iface_->NotifyDisconnectCallback(connId, BT_STATUS_SUCCESS, client_id, *bd_addr); }), Return(BT_STATUS_SUCCESS))); EXPECT_TRUE(le_client_->Disconnect(kTestAddressStr)); EXPECT_EQ(2, delegate.connection_state_count()); le_client_->SetDelegate(nullptr); ::testing::Mock::VerifyAndClearExpectations(mock_handler_.get()); } } // namespace } // namespace bluetooth Loading
system/service/ipc/binder/bluetooth_low_energy_binder_server.cpp +6 −0 Original line number Diff line number Diff line Loading @@ -168,6 +168,12 @@ bool BluetoothLowEnergyBinderServer::StopMultiAdvertising(int client_id) { return true; } void BluetoothLowEnergyBinderServer::OnConnectionState( bluetooth::LowEnergyClient* client, int status, const char* address, bool connected) { VLOG(2) << __func__ << " address: " << address << " connected: " << connected; } void BluetoothLowEnergyBinderServer::OnScanResult( bluetooth::LowEnergyClient* client, const bluetooth::ScanResult& result) { Loading
system/service/ipc/binder/bluetooth_low_energy_binder_server.h +2 −0 Original line number Diff line number Diff line Loading @@ -60,6 +60,8 @@ class BluetoothLowEnergyBinderServer bool StopMultiAdvertising(int client_id) override; // bluetooth::LowEnergyClient::Delegate overrides: void OnConnectionState(bluetooth::LowEnergyClient* client, int status, const char* address, bool connected) override; void OnScanResult(bluetooth::LowEnergyClient* client, const bluetooth::ScanResult& result) override; Loading
system/service/low_energy_client.cpp +86 −2 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <base/logging.h> #include "service/adapter.h" #include "service/common/bluetooth/util/address_helper.h" #include "service/logging_helpers.h" #include "stack/include/bt_types.h" #include "stack/include/hcidefs.h" Loading Loading @@ -334,6 +335,49 @@ LowEnergyClient::~LowEnergyClient() { StopScan(); } bool LowEnergyClient::Connect(std::string address, bool is_direct) { VLOG(2) << __func__ << "Address: " << address << " is_direct: " << is_direct; bt_bdaddr_t bda; util::BdAddrFromString(address, &bda); bt_status_t status = hal::BluetoothGattInterface::Get()-> GetClientHALInterface()->connect(client_id_, &bda, is_direct, BT_TRANSPORT_LE); if (status != BT_STATUS_SUCCESS) { LOG(ERROR) << "HAL call to connect failed"; return false; } return true; } bool LowEnergyClient::Disconnect(std::string address) { VLOG(2) << __func__ << "Address: " << address; bt_bdaddr_t bda; util::BdAddrFromString(address, &bda); std::map<const bt_bdaddr_t, int>::iterator conn_id; { lock_guard<mutex> lock(connection_fields_lock_); conn_id = connection_ids_.find(bda); if (conn_id == connection_ids_.end()) { LOG(WARNING) << "Can't disconnect, no existing connection to " << address; return false; } } bt_status_t status = hal::BluetoothGattInterface::Get()-> GetClientHALInterface()->disconnect(client_id_, &bda, conn_id->second); if (status != BT_STATUS_SUCCESS) { LOG(ERROR) << "HAL call to disconnect failed"; return false; } return true; } void LowEnergyClient::SetDelegate(Delegate* delegate) { lock_guard<mutex> lock(delegate_mutex_); delegate_ = delegate; Loading Loading @@ -513,6 +557,46 @@ void LowEnergyClient::ScanResultCallback( delegate_->OnScanResult(this, result); } void LowEnergyClient::ConnectCallback( hal::BluetoothGattInterface* gatt_iface, int conn_id, int status, int client_id, const bt_bdaddr_t& bda) { if (client_id != client_id_) return; VLOG(1) << __func__ << "client_id: " << client_id << " status: " << status; { lock_guard<mutex> lock(connection_fields_lock_); auto success = connection_ids_.emplace(bda, conn_id); if (!success.second) { LOG(ERROR) << __func__ << " Insertion into connection_ids_ failed!"; } } if (delegate_) delegate_->OnConnectionState(this, status, BtAddrString(&bda).c_str(), true); } void LowEnergyClient::DisconnectCallback( hal::BluetoothGattInterface* gatt_iface, int conn_id, int status, int client_id, const bt_bdaddr_t& bda) { if (client_id != client_id_) return; VLOG(1) << __func__ << " client_id: " << client_id << " status: " << status; { lock_guard<mutex> lock(connection_fields_lock_); if (!connection_ids_.erase(bda)) { LOG(ERROR) << __func__ << " Erasing from connection_ids_ failed!"; } } if (delegate_) delegate_->OnConnectionState(this, status, BtAddrString(&bda).c_str(), false); } void LowEnergyClient::MultiAdvEnableCallback( hal::BluetoothGattInterface* gatt_iface, int client_id, int status) { Loading
system/service/low_energy_client.h +33 −1 Original line number Diff line number Diff line Loading @@ -35,6 +35,12 @@ namespace bluetooth { struct ConnComparator { bool operator()(const bt_bdaddr_t& a, const bt_bdaddr_t& b) const { return memcmp(&a, &b, sizeof(bt_bdaddr_t)) < 0; } }; class Adapter; // A LowEnergyClient represents an application's handle to perform various Loading @@ -55,6 +61,10 @@ class LowEnergyClient : private hal::BluetoothGattInterface::ClientObserver, virtual void OnScanResult(LowEnergyClient* client, const ScanResult& scan_result) = 0; // Called asynchronously to notify the delegate of connection state change virtual void OnConnectionState(LowEnergyClient* client, int status, const char* address, bool connected) = 0; private: DISALLOW_COPY_AND_ASSIGN(Delegate); }; Loading @@ -70,6 +80,15 @@ class LowEnergyClient : private hal::BluetoothGattInterface::ClientObserver, // Callback type used to return the result of asynchronous operations below. using StatusCallback = std::function<void(BLEStatus)>; // Initiates a BLE connection do device with address |address|. If // |is_direct| is set, use direct connect procedure. Return true on success //, false otherwise. bool Connect(std::string address, bool is_direct); // Disconnect from previously connected BLE device with address |address|. // Return true on success, false otherwise. bool Disconnect(std::string address); // Initiates a BLE device scan for this client using the given |settings| and // |filters|. See the documentation for ScanSettings and ScanFilter for how // these parameters can be configured. Return true on success, false Loading Loading @@ -123,6 +142,13 @@ class LowEnergyClient : private hal::BluetoothGattInterface::ClientObserver, void ScanResultCallback( hal::BluetoothGattInterface* gatt_iface, const bt_bdaddr_t& bda, int rssi, uint8_t* adv_data) override; void ConnectCallback( hal::BluetoothGattInterface* gatt_iface, int conn_id, int status, int client_id, const bt_bdaddr_t& bda) override; void DisconnectCallback( hal::BluetoothGattInterface* gatt_iface, int conn_id, int status, int client_id, const bt_bdaddr_t& bda) override; void MultiAdvEnableCallback( hal::BluetoothGattInterface* gatt_iface, int client_id, int status) override; Loading Loading @@ -190,6 +216,12 @@ class LowEnergyClient : private hal::BluetoothGattInterface::ClientObserver, std::mutex delegate_mutex_; Delegate* delegate_; // Protects device connection related members below. std::mutex connection_fields_lock_; // Maps bluetooth address to connection id std::map<const bt_bdaddr_t, int, ConnComparator> connection_ids_; DISALLOW_COPY_AND_ASSIGN(LowEnergyClient); }; Loading
system/service/test/low_energy_client_unittest.cpp +72 −4 Original line number Diff line number Diff line Loading @@ -27,6 +27,9 @@ using ::testing::_; using ::testing::Return; using ::testing::Pointee; using ::testing::DoAll; using ::testing::Invoke; namespace bluetooth { namespace { Loading Loading @@ -74,7 +77,7 @@ class MockGattHandler class TestDelegate : public LowEnergyClient::Delegate { public: TestDelegate() : scan_result_count_(0) { TestDelegate() : scan_result_count_(0), connection_state_count_(0) { } ~TestDelegate() override = default; Loading @@ -82,6 +85,14 @@ class TestDelegate : public LowEnergyClient::Delegate { int scan_result_count() const { return scan_result_count_; } const ScanResult& last_scan_result() const { return last_scan_result_; } int connection_state_count() const { return connection_state_count_; } void OnConnectionState(LowEnergyClient* client, int status, const char* address, bool connected) { ASSERT_TRUE(client); connection_state_count_++; } void OnScanResult(LowEnergyClient* client, const ScanResult& scan_result) { ASSERT_TRUE(client); scan_result_count_++; Loading @@ -92,6 +103,8 @@ class TestDelegate : public LowEnergyClient::Delegate { int scan_result_count_; ScanResult last_scan_result_; int connection_state_count_; DISALLOW_COPY_AND_ASSIGN(TestDelegate); }; Loading Loading @@ -937,5 +950,60 @@ TEST_F(LowEnergyClientPostRegisterTest, ScanRecord) { le_client_->SetDelegate(nullptr); } MATCHER_P(BitEq, x, std::string(negation ? "isn't" : "is") + " bitwise equal to " + ::testing::PrintToString(x)) { static_assert(sizeof(x) == sizeof(arg), "Size mismatch"); return std::memcmp(&arg, &x, sizeof(x)) == 0; } TEST_F(LowEnergyClientPostRegisterTest, Connect) { const bt_bdaddr_t kTestAddress = { { 0x01, 0x02, 0x03, 0x0A, 0x0B, 0x0C } }; const char kTestAddressStr[] = "01:02:03:0A:0B:0C"; const bool kTestDirect = false; const int connId = 12; TestDelegate delegate; le_client_->SetDelegate(&delegate); // TODO(jpawlowski): NotifyConnectCallback should be called after returning // success, fix it when it becomes important. // These should succeed and result in a HAL call EXPECT_CALL(*mock_handler_, Connect(le_client_->GetInstanceId(), Pointee(BitEq(kTestAddress)), kTestDirect, BT_TRANSPORT_LE)) .Times(1) .WillOnce(DoAll( Invoke([&](int client_id, const bt_bdaddr_t *bd_addr, bool is_direct, int transport){ fake_hal_gatt_iface_->NotifyConnectCallback(connId, BT_STATUS_SUCCESS, client_id, *bd_addr); }), Return(BT_STATUS_SUCCESS))); EXPECT_TRUE(le_client_->Connect(kTestAddressStr, kTestDirect)); EXPECT_EQ(1, delegate.connection_state_count()); // TODO(jpawlowski): same as above // These should succeed and result in a HAL call EXPECT_CALL(*mock_handler_, Disconnect(le_client_->GetInstanceId(), Pointee(BitEq(kTestAddress)), connId)) .Times(1) .WillOnce(DoAll( Invoke([&](int client_id, const bt_bdaddr_t *bd_addr, int connId){ fake_hal_gatt_iface_->NotifyDisconnectCallback(connId, BT_STATUS_SUCCESS, client_id, *bd_addr); }), Return(BT_STATUS_SUCCESS))); EXPECT_TRUE(le_client_->Disconnect(kTestAddressStr)); EXPECT_EQ(2, delegate.connection_state_count()); le_client_->SetDelegate(nullptr); ::testing::Mock::VerifyAndClearExpectations(mock_handler_.get()); } } // namespace } // namespace bluetooth