diff options
author | 2022-09-12 19:48:50 +0800 | |
---|---|---|
committer | 2022-10-19 15:39:29 +0800 | |
commit | 5c8aec51015e00b8b6fe8d430b3a5111439f3e13 (patch) | |
tree | ca87489b9f348d3c102bbd9e19b3643fa2e1a41d | |
parent | aa88fe3f88386662b8d676d7b90ebed75c28e2e5 (diff) |
floss: plumbing (dis)connection direction to btif
Whether (dis)connection is initiated by the host or by the peer is
an information worthy of being logged by metrics. Therefore,
surfacing it.
Bug: 240782154
Tag: #floss
Test: Verify connection direction is properly passed
BYPASS_LONG_LINES_REASON: Bluetooth likes 120 lines
Change-Id: I41f5b1333eded0c23459a58a5535258ebace7e3c
46 files changed, 281 insertions, 117 deletions
diff --git a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp index b6cebbceed..47f5121078 100644 --- a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp +++ b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp @@ -368,7 +368,8 @@ static void le_address_associate_callback(RawAddress* main_bd_addr, static void acl_state_changed_callback(bt_status_t status, RawAddress* bd_addr, bt_acl_state_t state, int transport_link_type, - bt_hci_error_code_t hci_reason) { + bt_hci_error_code_t hci_reason, + bt_conn_direction_t direction) { if (!bd_addr) { ALOGE("Address is null in %s", __func__); return; diff --git a/system/btif/include/btif_common.h b/system/btif/include/btif_common.h index cabf709a34..4d69014a9f 100644 --- a/system/btif/include/btif_common.h +++ b/system/btif/include/btif_common.h @@ -224,7 +224,8 @@ void invoke_le_address_associate_cb(RawAddress main_bd_addr, RawAddress secondary_bd_addr); void invoke_acl_state_changed_cb(bt_status_t status, RawAddress bd_addr, bt_acl_state_t state, int transport_link_type, - bt_hci_error_code_t hci_reason); + bt_hci_error_code_t hci_reason, + bt_conn_direction_t direction); void invoke_thread_evt_cb(bt_cb_thread_evt event); void invoke_le_test_mode_cb(bt_status_t status, uint16_t count); void invoke_energy_info_cb(bt_activity_energy_info energy_info, diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc index ffe884f289..a2d3a2574d 100644 --- a/system/btif/src/bluetooth.cc +++ b/system/btif/src/bluetooth.cc @@ -990,16 +990,18 @@ void invoke_le_address_associate_cb(RawAddress main_bd_addr, } void invoke_acl_state_changed_cb(bt_status_t status, RawAddress bd_addr, bt_acl_state_t state, int transport_link_type, - bt_hci_error_code_t hci_reason) { + bt_hci_error_code_t hci_reason, + bt_conn_direction_t direction) { do_in_jni_thread( FROM_HERE, base::BindOnce( [](bt_status_t status, RawAddress bd_addr, bt_acl_state_t state, - int transport_link_type, bt_hci_error_code_t hci_reason) { + int transport_link_type, bt_hci_error_code_t hci_reason, + bt_conn_direction_t direction) { HAL_CBACK(bt_hal_cbacks, acl_state_changed_cb, status, &bd_addr, - state, transport_link_type, hci_reason); + state, transport_link_type, hci_reason, direction); }, - status, bd_addr, state, transport_link_type, hci_reason)); + status, bd_addr, state, transport_link_type, hci_reason, direction)); } void invoke_thread_evt_cb(bt_cb_thread_evt event) { diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc index e6029ba68d..4c26b5281a 100644 --- a/system/btif/src/btif_dm.cc +++ b/system/btif/src/btif_dm.cc @@ -1825,26 +1825,48 @@ static void btif_dm_upstreams_evt(uint16_t event, char* p_param) { invoke_acl_state_changed_cb( BT_STATUS_SUCCESS, bd_addr, BT_ACL_STATE_CONNECTED, - (int)p_data->link_up.transport_link_type, HCI_SUCCESS); + (int)p_data->link_up.transport_link_type, HCI_SUCCESS, + btm_is_acl_locally_initiated() + ? bt_conn_direction_t::BT_CONN_DIRECTION_OUTGOING + : bt_conn_direction_t::BT_CONN_DIRECTION_INCOMING); break; case BTA_DM_LINK_UP_FAILED_EVT: invoke_acl_state_changed_cb( BT_STATUS_FAIL, p_data->link_up_failed.bd_addr, BT_ACL_STATE_DISCONNECTED, p_data->link_up_failed.transport_link_type, - p_data->link_up_failed.status); + p_data->link_up_failed.status, + btm_is_acl_locally_initiated() + ? bt_conn_direction_t::BT_CONN_DIRECTION_OUTGOING + : bt_conn_direction_t::BT_CONN_DIRECTION_INCOMING); break; - case BTA_DM_LINK_DOWN_EVT: + case BTA_DM_LINK_DOWN_EVT: { bd_addr = p_data->link_down.bd_addr; btm_set_bond_type_dev(p_data->link_down.bd_addr, tBTM_SEC_DEV_REC::BOND_TYPE_UNKNOWN); btif_av_acl_disconnected(bd_addr); + bt_conn_direction_t direction; + switch (btm_get_acl_disc_reason_code()) { + case HCI_ERR_PEER_USER: + case HCI_ERR_REMOTE_LOW_RESOURCE: + case HCI_ERR_REMOTE_POWER_OFF: + direction = bt_conn_direction_t::BT_CONN_DIRECTION_INCOMING; + break; + case HCI_ERR_CONN_CAUSE_LOCAL_HOST: + case HCI_ERR_HOST_REJECT_SECURITY: + direction = bt_conn_direction_t::BT_CONN_DIRECTION_OUTGOING; + break; + default: + direction = bt_conn_direction_t::BT_CONN_DIRECTION_UNKNOWN; + } + invoke_acl_state_changed_cb( BT_STATUS_SUCCESS, bd_addr, BT_ACL_STATE_DISCONNECTED, (int)p_data->link_down.transport_link_type, - static_cast<bt_hci_error_code_t>(btm_get_acl_disc_reason_code())); + static_cast<bt_hci_error_code_t>(btm_get_acl_disc_reason_code()), + direction); LOG_DEBUG( "Sent BT_ACL_STATE_DISCONNECTED upward as ACL link down event " "device:%s reason:%s", @@ -1852,7 +1874,7 @@ static void btif_dm_upstreams_evt(uint16_t event, char* p_param) { hci_reason_code_text( static_cast<tHCI_REASON>(btm_get_acl_disc_reason_code())) .c_str()); - break; + } break; case BTA_DM_BLE_KEY_EVT: BTIF_TRACE_DEBUG("BTA_DM_BLE_KEY_EVT key_type=0x%02x ", diff --git a/system/btif/test/btif_core_test.cc b/system/btif/test/btif_core_test.cc index 82f86dc5fb..17dcebe135 100644 --- a/system/btif/test/btif_core_test.cc +++ b/system/btif/test/btif_core_test.cc @@ -69,7 +69,8 @@ void le_address_associate_callback(RawAddress* main_bd_addr, RawAddress* secondary_bd_addr) {} void acl_state_changed_callback(bt_status_t status, RawAddress* remote_bd_addr, bt_acl_state_t state, int transport_link_type, - bt_hci_error_code_t hci_reason) {} + bt_hci_error_code_t hci_reason, + bt_conn_direction_t direction) {} void link_quality_report_callback(uint64_t timestamp, int report_id, int rssi, int snr, int retransmission_count, int packets_not_receive_count, diff --git a/system/gd/hci/acl_manager/classic_impl.h b/system/gd/hci/acl_manager/classic_impl.h index 9433664202..f68f8e7f0d 100644 --- a/system/gd/hci/acl_manager/classic_impl.h +++ b/system/gd/hci/acl_manager/classic_impl.h @@ -310,7 +310,11 @@ struct classic_impl : public security::ISecurityManagerListener { LOG_ERROR("Failed to create connection, reporting failure and continuing"); ASSERT(client_callbacks_ != nullptr); client_handler_->Post(common::BindOnce( - &ConnectionCallbacks::OnConnectFail, common::Unretained(client_callbacks_), address, status.GetStatus())); + &ConnectionCallbacks::OnConnectFail, + common::Unretained(client_callbacks_), + address, + status.GetStatus(), + true /* locally initiated */)); acl_scheduler_->ReportOutgoingAclConnectionFailure(); } else { // everything is good, resume when a connection_complete event arrives @@ -333,7 +337,11 @@ struct classic_impl : public security::ISecurityManagerListener { } if (status != ErrorCode::SUCCESS) { client_handler_->Post(common::BindOnce( - &ConnectionCallbacks::OnConnectFail, common::Unretained(client_callbacks_), address, status)); + &ConnectionCallbacks::OnConnectFail, + common::Unretained(client_callbacks_), + address, + status, + initiator == Initiator::LOCALLY_INITIATED)); return; } uint16_t handle = connection_complete.GetConnectionHandle(); @@ -401,7 +409,11 @@ struct classic_impl : public security::ISecurityManagerListener { address, handler_->BindOnceOn(this, &classic_impl::actually_cancel_connect, address), client_handler_->BindOnceOn( - client_callbacks_, &ConnectionCallbacks::OnConnectFail, address, ErrorCode::UNKNOWN_CONNECTION)); + client_callbacks_, + &ConnectionCallbacks::OnConnectFail, + address, + ErrorCode::UNKNOWN_CONNECTION, + true /* locally initiated */)); } void actually_cancel_connect(Address address) { diff --git a/system/gd/hci/acl_manager/connection_callbacks.h b/system/gd/hci/acl_manager/connection_callbacks.h index 9a72654e26..6043bf49cc 100644 --- a/system/gd/hci/acl_manager/connection_callbacks.h +++ b/system/gd/hci/acl_manager/connection_callbacks.h @@ -33,7 +33,7 @@ class ConnectionCallbacks { // Invoked when controller sends Connection Complete event with Success error code virtual void OnConnectSuccess(std::unique_ptr<ClassicAclConnection>) = 0; // Invoked when controller sends Connection Complete event with non-Success error code - virtual void OnConnectFail(Address, ErrorCode reason) = 0; + virtual void OnConnectFail(Address, ErrorCode reason, bool locally_initiated) = 0; virtual void HACK_OnEscoConnectRequest(Address, ClassOfDevice) = 0; virtual void HACK_OnScoConnectRequest(Address, ClassOfDevice) = 0; diff --git a/system/gd/hci/acl_manager/le_connection_callbacks.h b/system/gd/hci/acl_manager/le_connection_callbacks.h index 07abc9a21c..594b2ca015 100644 --- a/system/gd/hci/acl_manager/le_connection_callbacks.h +++ b/system/gd/hci/acl_manager/le_connection_callbacks.h @@ -33,7 +33,7 @@ class LeConnectionCallbacks { // AddressWithType is always equal to the object used in AclManager#CreateLeConnection virtual void OnLeConnectSuccess(AddressWithType, std::unique_ptr<LeAclConnection>) = 0; // Invoked when create connection timeout or controller sends Connection Complete event with non-Success error code - virtual void OnLeConnectFail(AddressWithType, ErrorCode reason) = 0; + virtual void OnLeConnectFail(AddressWithType, ErrorCode reason, bool locally_initiated) = 0; }; } // namespace acl_manager diff --git a/system/gd/hci/acl_manager/le_impl.h b/system/gd/hci/acl_manager/le_impl.h index 6ad94efb46..a8dfdc2528 100644 --- a/system/gd/hci/acl_manager/le_impl.h +++ b/system/gd/hci/acl_manager/le_impl.h @@ -343,7 +343,11 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback { if (status != ErrorCode::SUCCESS) { le_client_handler_->Post(common::BindOnce( - &LeConnectionCallbacks::OnLeConnectFail, common::Unretained(le_client_callbacks_), remote_address, status)); + &LeConnectionCallbacks::OnLeConnectFail, + common::Unretained(le_client_callbacks_), + remote_address, + status, + true /* locally_initiated */)); return; } } else { @@ -356,6 +360,12 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback { if (status != ErrorCode::SUCCESS) { std::string error_code = ErrorCodeText(status); LOG_WARN("Received on_le_connection_complete with error code %s", error_code.c_str()); + le_client_handler_->Post(common::BindOnce( + &LeConnectionCallbacks::OnLeConnectFail, + common::Unretained(le_client_callbacks_), + remote_address, + status, + false /* locally_initiated */)); return; } @@ -390,6 +400,7 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback { connection->latency_ = conn_latency; connection->supervision_timeout_ = supervision_timeout; connection->in_filter_accept_list_ = in_filter_accept_list; + connection->locally_initiated_ = (role == hci::Role::CENTRAL); connections.add( handle, remote_address, queue_down_end, handler_, connection->GetEventCallbacks([this](uint16_t handle) { this->connections.invalidate(handle); @@ -456,7 +467,11 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback { if (status != ErrorCode::SUCCESS) { le_client_handler_->Post(common::BindOnce( - &LeConnectionCallbacks::OnLeConnectFail, common::Unretained(le_client_callbacks_), remote_address, status)); + &LeConnectionCallbacks::OnLeConnectFail, + common::Unretained(le_client_callbacks_), + remote_address, + status, + true /* locally_initiated */)); return; } @@ -470,6 +485,12 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback { if (status != ErrorCode::SUCCESS) { std::string error_code = ErrorCodeText(status); LOG_WARN("Received on_le_enhanced_connection_complete with error code %s", error_code.c_str()); + le_client_handler_->Post(common::BindOnce( + &LeConnectionCallbacks::OnLeConnectFail, + common::Unretained(le_client_callbacks_), + remote_address, + status, + false /* locally_initiated */)); return; } @@ -514,6 +535,7 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback { connection->local_resolvable_private_address_ = connection_complete.GetLocalResolvablePrivateAddress(); connection->peer_resolvable_private_address_ = connection_complete.GetPeerResolvablePrivateAddress(); connection->in_filter_accept_list_ = in_filter_accept_list; + connection->locally_initiated_ = (role == hci::Role::CENTRAL); connections.add( handle, remote_address, queue_down_end, handler_, connection->GetEventCallbacks([this](uint16_t handle) { this->connections.invalidate(handle); @@ -939,7 +961,8 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback { &LeConnectionCallbacks::OnLeConnectFail, common::Unretained(le_client_callbacks_), address_with_type, - ErrorCode::CONNECTION_ACCEPT_TIMEOUT)); + ErrorCode::CONNECTION_ACCEPT_TIMEOUT, + true /* locally_initiated */)); } } diff --git a/system/gd/hci/acl_manager/le_impl_test.cc b/system/gd/hci/acl_manager/le_impl_test.cc index e1238d49d6..dfe3446947 100644 --- a/system/gd/hci/acl_manager/le_impl_test.cc +++ b/system/gd/hci/acl_manager/le_impl_test.cc @@ -389,7 +389,8 @@ class MockLeConnectionCallbacks : public LeConnectionCallbacks { OnLeConnectSuccess, (AddressWithType address_with_type, std::unique_ptr<LeAclConnection> connection), (override)); - MOCK_METHOD(void, OnLeConnectFail, (AddressWithType address_with_type, ErrorCode reason), (override)); + MOCK_METHOD( + void, OnLeConnectFail, (AddressWithType address_with_type, ErrorCode reason, bool locally_initiated), (override)); }; class MockLeConnectionManagementCallbacks : public LeConnectionManagementCallbacks { @@ -1417,7 +1418,7 @@ TEST_F(LeImplTest, on_le_connection_canceled_on_pause) { } TEST_F(LeImplTest, on_create_connection_timeout) { - EXPECT_CALL(mock_le_connection_callbacks_, OnLeConnectFail(_, ErrorCode::CONNECTION_ACCEPT_TIMEOUT)).Times(1); + EXPECT_CALL(mock_le_connection_callbacks_, OnLeConnectFail(_, ErrorCode::CONNECTION_ACCEPT_TIMEOUT, _)).Times(1); le_impl_->create_connection_timeout_alarms_.emplace( std::piecewise_construct, std::forward_as_tuple( diff --git a/system/gd/hci/acl_manager_test.cc b/system/gd/hci/acl_manager_test.cc index 73e3228310..f22de4e85f 100644 --- a/system/gd/hci/acl_manager_test.cc +++ b/system/gd/hci/acl_manager_test.cc @@ -408,7 +408,7 @@ class AclManagerNoCallbacksTest : public ::testing::Test { connection_promise_.reset(); } } - MOCK_METHOD(void, OnConnectFail, (Address, ErrorCode reason), (override)); + MOCK_METHOD(void, OnConnectFail, (Address, ErrorCode reason, bool locally_initiated), (override)); MOCK_METHOD(void, HACK_OnEscoConnectRequest, (Address, ClassOfDevice), (override)); MOCK_METHOD(void, HACK_OnScoConnectRequest, (Address, ClassOfDevice), (override)); @@ -426,7 +426,7 @@ class AclManagerNoCallbacksTest : public ::testing::Test { le_connection_promise_.reset(); } } - MOCK_METHOD(void, OnLeConnectFail, (AddressWithType, ErrorCode reason), (override)); + MOCK_METHOD(void, OnLeConnectFail, (AddressWithType, ErrorCode reason, bool locally_initiated), (override)); std::list<std::shared_ptr<LeAclConnection>> le_connections_; std::unique_ptr<std::promise<void>> le_connection_promise_; @@ -582,7 +582,7 @@ TEST_F(AclManagerTest, invoke_registered_callback_connection_complete_fail) { last_command = test_hci_layer_->GetCommand(OpCode::CREATE_CONNECTION); } - EXPECT_CALL(mock_connection_callback_, OnConnectFail(remote, ErrorCode::PAGE_TIMEOUT)); + EXPECT_CALL(mock_connection_callback_, OnConnectFail(remote, ErrorCode::PAGE_TIMEOUT, true)); test_hci_layer_->IncomingEvent( ConnectionCompleteBuilder::Create(ErrorCode::PAGE_TIMEOUT, handle, remote, LinkType::ACL, Enable::DISABLED)); fake_registry_.SynchronizeModuleHandler(&HciLayer::Factory, std::chrono::milliseconds(20)); @@ -705,8 +705,10 @@ TEST_F(AclManagerTest, invoke_registered_callback_le_connection_complete_fail) { test_hci_layer_->IncomingEvent(LeCreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 0x01)); - EXPECT_CALL(mock_le_connection_callbacks_, - OnLeConnectFail(remote_with_type, ErrorCode::CONNECTION_REJECTED_LIMITED_RESOURCES)); + EXPECT_CALL( + mock_le_connection_callbacks_, + OnLeConnectFail( + remote_with_type, ErrorCode::CONNECTION_REJECTED_LIMITED_RESOURCES, /* locally_initiated */ true)); test_hci_layer_->IncomingLeMetaEvent(LeConnectionCompleteBuilder::Create( ErrorCode::CONNECTION_REJECTED_LIMITED_RESOURCES, 0x123, diff --git a/system/gd/hci/acl_manager_unittest.cc b/system/gd/hci/acl_manager_unittest.cc index cc22be79ce..a824bfce29 100644 --- a/system/gd/hci/acl_manager_unittest.cc +++ b/system/gd/hci/acl_manager_unittest.cc @@ -349,7 +349,7 @@ class MockConnectionCallback : public ConnectionCallbacks { connection_promise_.set_value(connections_.back()); } } - MOCK_METHOD(void, OnConnectFail, (Address, ErrorCode reason), (override)); + MOCK_METHOD(void, OnConnectFail, (Address, ErrorCode reason, bool locally_initiated), (override)); MOCK_METHOD(void, HACK_OnEscoConnectRequest, (Address, ClassOfDevice), (override)); MOCK_METHOD(void, HACK_OnScoConnectRequest, (Address, ClassOfDevice), (override)); @@ -376,7 +376,7 @@ class MockLeConnectionCallbacks : public LeConnectionCallbacks { le_connection_promise_.reset(); } } - MOCK_METHOD(void, OnLeConnectFail, (AddressWithType, ErrorCode reason), (override)); + MOCK_METHOD(void, OnLeConnectFail, (AddressWithType, ErrorCode reason, bool locally_initiated), (override)); std::deque<std::shared_ptr<LeAclConnection>> le_connections_; std::unique_ptr<std::promise<void>> le_connection_promise_; diff --git a/system/gd/hci/facade/acl_manager_facade.cc b/system/gd/hci/facade/acl_manager_facade.cc index 0911577cd8..3df393086a 100644 --- a/system/gd/hci/facade/acl_manager_facade.cc +++ b/system/gd/hci/facade/acl_manager_facade.cc @@ -374,7 +374,7 @@ class AclManagerFacadeService : public AclManagerFacade::Service, public Connect current_connection_request_++; } - void OnConnectFail(Address address, ErrorCode reason) override { + void OnConnectFail(Address address, ErrorCode reason, bool locally_initiated) override { LOG_INFO("addr=%s, reason=%s", address.ToString().c_str(), ErrorCodeText(reason).c_str()); std::unique_ptr<BasePacketBuilder> builder = ConnectionCompleteBuilder::Create(reason, 0, address, LinkType::ACL, Enable::DISABLED); diff --git a/system/gd/hci/facade/le_acl_manager_facade.cc b/system/gd/hci/facade/le_acl_manager_facade.cc index b5a2d19071..1cba077484 100644 --- a/system/gd/hci/facade/le_acl_manager_facade.cc +++ b/system/gd/hci/facade/le_acl_manager_facade.cc @@ -314,7 +314,7 @@ class LeAclManagerFacadeService : public LeAclManagerFacade::Service, public LeC } } - void OnLeConnectFail(AddressWithType address, ErrorCode reason) override { + void OnLeConnectFail(AddressWithType address, ErrorCode reason, bool locally_initiated) override { LOG_INFO("addr=%s, reason=%s", address.ToString().c_str(), ErrorCodeText(reason).c_str()); std::unique_ptr<BasePacketBuilder> builder = LeConnectionCompleteBuilder::Create( reason, 0, Role::CENTRAL, address.GetAddressType(), address.GetAddress(), 0, 0, 0, ClockAccuracy::PPM_20); diff --git a/system/gd/l2cap/classic/internal/link_manager.cc b/system/gd/l2cap/classic/internal/link_manager.cc index f8ff461d77..a34f4f4070 100644 --- a/system/gd/l2cap/classic/internal/link_manager.cc +++ b/system/gd/l2cap/classic/internal/link_manager.cc @@ -284,7 +284,7 @@ void LinkManager::OnConnectSuccess(std::unique_ptr<hci::acl_manager::ClassicAclC pending_links_.erase(device); } -void LinkManager::OnConnectFail(hci::Address device, hci::ErrorCode reason) { +void LinkManager::OnConnectFail(hci::Address device, hci::ErrorCode reason, bool locally_initiated) { // Notify all pending links for this device auto pending_link = pending_links_.find(device); if (pending_link == pending_links_.end()) { diff --git a/system/gd/l2cap/classic/internal/link_manager.h b/system/gd/l2cap/classic/internal/link_manager.h index 4d327ea5bf..5e6d5599b9 100644 --- a/system/gd/l2cap/classic/internal/link_manager.h +++ b/system/gd/l2cap/classic/internal/link_manager.h @@ -68,7 +68,7 @@ class LinkManager : public hci::acl_manager::ConnectionCallbacks { Link* GetLink(hci::Address device); void OnConnectSuccess(std::unique_ptr<hci::acl_manager::ClassicAclConnection> acl_connection) override; - void OnConnectFail(hci::Address device, hci::ErrorCode reason) override; + void OnConnectFail(hci::Address device, hci::ErrorCode reason, bool locally_initiated) override; void HACK_OnEscoConnectRequest(hci::Address, hci::ClassOfDevice) override; void HACK_OnScoConnectRequest(hci::Address, hci::ClassOfDevice) override; diff --git a/system/gd/l2cap/classic/internal/link_manager_test.cc b/system/gd/l2cap/classic/internal/link_manager_test.cc index d59e0dd9b9..b48cd8a894 100644 --- a/system/gd/l2cap/classic/internal/link_manager_test.cc +++ b/system/gd/l2cap/classic/internal/link_manager_test.cc @@ -253,9 +253,12 @@ TEST_F(L2capClassicLinkManagerTest, connect_fixed_channel_service_without_acl_wi // Step 3: ACL connection failure event should trigger connection failure callback EXPECT_CALL(mock_service_1, NotifyChannelCreation(_)).Times(0); - hci_callback_handler->Post(common::BindOnce(&hci::acl_manager::ConnectionCallbacks::OnConnectFail, - common::Unretained(hci_connection_callbacks), device, - hci::ErrorCode::PAGE_TIMEOUT)); + hci_callback_handler->Post(common::BindOnce( + &hci::acl_manager::ConnectionCallbacks::OnConnectFail, + common::Unretained(hci_connection_callbacks), + device, + hci::ErrorCode::PAGE_TIMEOUT, + true /* locally_initiated */)); SyncHandler(hci_callback_handler); SyncHandler(user_handler.get()); EXPECT_EQ(my_result.connection_result_code, FixedChannelManager::ConnectionResultCode::FAIL_HCI_ERROR); diff --git a/system/gd/l2cap/le/internal/link_manager.cc b/system/gd/l2cap/le/internal/link_manager.cc index f2677a3bfe..09b6c34107 100644 --- a/system/gd/l2cap/le/internal/link_manager.cc +++ b/system/gd/l2cap/le/internal/link_manager.cc @@ -127,7 +127,8 @@ void LinkManager::OnLeConnectSuccess(hci::AddressWithType connecting_address_wit link->ReadRemoteVersionInformation(); } -void LinkManager::OnLeConnectFail(hci::AddressWithType address_with_type, hci::ErrorCode reason) { +void LinkManager::OnLeConnectFail( + hci::AddressWithType address_with_type, hci::ErrorCode reason, bool locally_initiated) { // Notify all pending links for this device auto pending_link = pending_links_.find(address_with_type); if (pending_link == pending_links_.end()) { diff --git a/system/gd/l2cap/le/internal/link_manager.h b/system/gd/l2cap/le/internal/link_manager.h index 836a3f6e8c..fd00063bb2 100644 --- a/system/gd/l2cap/le/internal/link_manager.h +++ b/system/gd/l2cap/le/internal/link_manager.h @@ -73,7 +73,7 @@ class LinkManager : public hci::acl_manager::LeConnectionCallbacks { Link* GetLink(hci::AddressWithType address_with_type); void OnLeConnectSuccess(hci::AddressWithType connecting_address_with_type, std::unique_ptr<hci::acl_manager::LeAclConnection> acl_connection) override; - void OnLeConnectFail(hci::AddressWithType address_with_type, hci::ErrorCode reason) override; + void OnLeConnectFail(hci::AddressWithType address_with_type, hci::ErrorCode reason, bool locally_initiated) override; // FixedChannelManager methods diff --git a/system/gd/l2cap/le/internal/link_manager_test.cc b/system/gd/l2cap/le/internal/link_manager_test.cc index c7585f7f09..6d3932a885 100644 --- a/system/gd/l2cap/le/internal/link_manager_test.cc +++ b/system/gd/l2cap/le/internal/link_manager_test.cc @@ -272,9 +272,12 @@ TEST_F(L2capLeLinkManagerTest, connect_fixed_channel_service_without_acl_with_hc // Step 3: ACL connection failure event should trigger connection failure callback EXPECT_CALL(mock_service_1, NotifyChannelCreation(_)).Times(0); - hci_callback_handler->Post(common::BindOnce(&hci::acl_manager::LeConnectionCallbacks::OnLeConnectFail, - common::Unretained(hci_le_connection_callbacks), address_with_type, - hci::ErrorCode::PAGE_TIMEOUT)); + hci_callback_handler->Post(common::BindOnce( + &hci::acl_manager::LeConnectionCallbacks::OnLeConnectFail, + common::Unretained(hci_le_connection_callbacks), + address_with_type, + hci::ErrorCode::PAGE_TIMEOUT, + true /* locally_initiated */)); SyncHandler(hci_callback_handler); SyncHandler(user_handler_); EXPECT_EQ(my_result.connection_result_code, FixedChannelManager::ConnectionResultCode::FAIL_HCI_ERROR); diff --git a/system/gd/rust/linux/stack/src/bluetooth.rs b/system/gd/rust/linux/stack/src/bluetooth.rs index c06734a68c..311118094e 100644 --- a/system/gd/rust/linux/stack/src/bluetooth.rs +++ b/system/gd/rust/linux/stack/src/bluetooth.rs @@ -2,9 +2,9 @@ use bt_topshim::btif::{ BaseCallbacks, BaseCallbacksDispatcher, BluetoothInterface, BluetoothProperty, BtAclState, - BtBondState, BtConnectionState, BtDeviceType, BtDiscoveryState, BtHciErrorCode, BtPinCode, - BtPropertyType, BtScanMode, BtSspVariant, BtState, BtStatus, BtTransport, BtVendorProductInfo, - RawAddress, ToggleableProfile, Uuid, Uuid128Bit, + BtBondState, BtConnectionDirection, BtConnectionState, BtDeviceType, BtDiscoveryState, + BtHciErrorCode, BtPinCode, BtPropertyType, BtScanMode, BtSspVariant, BtState, BtStatus, + BtTransport, BtVendorProductInfo, RawAddress, ToggleableProfile, Uuid, Uuid128Bit, }; use bt_topshim::{ metrics, @@ -724,6 +724,7 @@ pub(crate) trait BtifBluetoothCallbacks { state: BtAclState, link_type: BtTransport, hci_reason: BtHciErrorCode, + conn_direction: BtConnectionDirection, ) { } @@ -1066,6 +1067,7 @@ impl BtifBluetoothCallbacks for Bluetooth { state: BtAclState, _link_type: BtTransport, _hci_reason: BtHciErrorCode, + _conn_direction: BtConnectionDirection, ) { if status != BtStatus::Success { warn!("Connection to [{}] failed. Status: {:?}", addr.to_string(), status); diff --git a/system/gd/rust/topshim/src/btif.rs b/system/gd/rust/topshim/src/btif.rs index a82e0a4aee..fcf9120a43 100644 --- a/system/gd/rust/topshim/src/btif.rs +++ b/system/gd/rust/topshim/src/btif.rs @@ -24,7 +24,7 @@ pub enum BtState { impl From<bindings::bt_state_t> for BtState { fn from(item: bindings::bt_state_t) -> Self { - BtState::from_u32(item).unwrap_or_else(|| BtState::Off) + BtState::from_u32(item).unwrap_or(BtState::Off) } } @@ -38,13 +38,13 @@ pub enum BtTransport { impl From<i32> for BtTransport { fn from(item: i32) -> Self { - BtTransport::from_i32(item).unwrap_or_else(|| BtTransport::Auto) + BtTransport::from_i32(item).unwrap_or(BtTransport::Auto) } } impl From<BtTransport> for i32 { fn from(item: BtTransport) -> Self { - item.to_i32().unwrap_or_else(|| 0) + item.to_i32().unwrap_or(0) } } @@ -59,13 +59,13 @@ pub enum BtSspVariant { impl From<bindings::bt_ssp_variant_t> for BtSspVariant { fn from(item: bindings::bt_ssp_variant_t) -> Self { - BtSspVariant::from_u32(item).unwrap_or_else(|| BtSspVariant::PasskeyConfirmation) + BtSspVariant::from_u32(item).unwrap_or(BtSspVariant::PasskeyConfirmation) } } impl From<BtSspVariant> for bindings::bt_ssp_variant_t { fn from(item: BtSspVariant) -> Self { - item.to_u32().unwrap_or_else(|| 0) + item.to_u32().unwrap_or(0) } } @@ -79,7 +79,7 @@ pub enum BtBondState { impl From<bindings::bt_bond_state_t> for BtBondState { fn from(item: bindings::bt_bond_state_t) -> Self { - BtBondState::from_u32(item).unwrap_or_else(|| BtBondState::NotBonded) + BtBondState::from_u32(item).unwrap_or(BtBondState::NotBonded) } } @@ -114,7 +114,7 @@ pub enum BtAclState { impl From<bindings::bt_acl_state_t> for BtAclState { fn from(item: bindings::bt_acl_state_t) -> Self { - BtAclState::from_u32(item).unwrap_or_else(|| BtAclState::Disconnected) + BtAclState::from_u32(item).unwrap_or(BtAclState::Disconnected) } } @@ -156,13 +156,13 @@ pub enum BtPropertyType { impl From<u32> for BtPropertyType { fn from(item: u32) -> Self { - BtPropertyType::from_u32(item).unwrap_or_else(|| BtPropertyType::Unknown) + BtPropertyType::from_u32(item).unwrap_or(BtPropertyType::Unknown) } } impl From<BtPropertyType> for u32 { fn from(item: BtPropertyType) -> Self { - item.to_u32().unwrap_or_else(|| 0) + item.to_u32().unwrap_or(0) } } @@ -175,7 +175,7 @@ pub enum BtDiscoveryState { impl From<u32> for BtDiscoveryState { fn from(item: u32) -> Self { - BtDiscoveryState::from_u32(item).unwrap_or_else(|| BtDiscoveryState::Stopped) + BtDiscoveryState::from_u32(item).unwrap_or(BtDiscoveryState::Stopped) } } @@ -851,7 +851,7 @@ pub enum BaseCallbacks { BondState(BtStatus, RawAddress, BtBondState, i32), AddressConsolidate(RawAddress, RawAddress), LeAddressAssociate(RawAddress, RawAddress), - AclState(BtStatus, RawAddress, BtAclState, BtTransport, BtHciErrorCode), + AclState(BtStatus, RawAddress, BtAclState, BtTransport, BtHciErrorCode, BtConnectionDirection), // Unimplemented so far: // thread_evt_cb // dut_mode_recv_cb @@ -914,7 +914,7 @@ cb_variant!(BaseCb, le_address_associate_cb -> BaseCallbacks::LeAddressAssociate }); cb_variant!(BaseCb, acl_state_cb -> BaseCallbacks::AclState, -u32 -> BtStatus, *mut FfiAddress, bindings::bt_acl_state_t -> BtAclState, i32 -> BtTransport, bindings::bt_hci_error_code_t -> BtHciErrorCode, { +u32 -> BtStatus, *mut FfiAddress, bindings::bt_acl_state_t -> BtAclState, i32 -> BtTransport, bindings::bt_hci_error_code_t -> BtHciErrorCode, bindings::bt_conn_direction_t -> BtConnectionDirection, { let _1 = unsafe { *(_1 as *const RawAddress) }; }); diff --git a/system/include/hardware/bluetooth.h b/system/include/hardware/bluetooth.h index 5d6587a27e..3295cecd41 100644 --- a/system/include/hardware/bluetooth.h +++ b/system/include/hardware/bluetooth.h @@ -176,6 +176,13 @@ typedef enum { BT_ACL_STATE_DISCONNECTED } bt_acl_state_t; +/** Bluetooth ACL connection direction */ +typedef enum { + BT_CONN_DIRECTION_UNKNOWN, + BT_CONN_DIRECTION_OUTGOING, + BT_CONN_DIRECTION_INCOMING +} bt_conn_direction_t; + /** Bluetooth SDP service record */ typedef struct { bluetooth::Uuid uuid; @@ -492,7 +499,8 @@ typedef void (*acl_state_changed_callback)(bt_status_t status, RawAddress* remote_bd_addr, bt_acl_state_t state, int transport_link_type, - bt_hci_error_code_t hci_reason); + bt_hci_error_code_t hci_reason, + bt_conn_direction_t direction); /** Bluetooth link quality report callback */ typedef void (*link_quality_report_callback)( diff --git a/system/main/shim/acl.cc b/system/main/shim/acl.cc index 58f9b3200f..6516db19f5 100644 --- a/system/main/shim/acl.cc +++ b/system/main/shim/acl.cc @@ -1483,7 +1483,7 @@ void shim::legacy::Acl::OnConnectSuccess( ->ReadRemoteControllerInformation(); TRY_POSTING_ON_MAIN(acl_interface_.connection.classic.on_connected, bd_addr, - handle, false); + handle, false, locally_initiated); LOG_DEBUG("Connection successful classic remote:%s handle:%hu initiator:%s", PRIVATE_ADDRESS(remote_address), handle, (locally_initiated) ? "local" : "remote"); @@ -1494,10 +1494,11 @@ void shim::legacy::Acl::OnConnectSuccess( } void shim::legacy::Acl::OnConnectFail(hci::Address address, - hci::ErrorCode reason) { + hci::ErrorCode reason, + bool locally_initiated) { const RawAddress bd_addr = ToRawAddress(address); TRY_POSTING_ON_MAIN(acl_interface_.connection.classic.on_failed, bd_addr, - ToLegacyHciErrorCode(reason)); + ToLegacyHciErrorCode(reason), locally_initiated); LOG_WARN("Connection failed classic remote:%s reason:%s", PRIVATE_ADDRESS(address), hci::ErrorCodeText(reason).c_str()); BTM_LogHistory(kBtmLogTag, ToRawAddress(address), "Connection failed", @@ -1606,7 +1607,8 @@ void shim::legacy::Acl::OnLeConnectSuccess( } void shim::legacy::Acl::OnLeConnectFail(hci::AddressWithType address_with_type, - hci::ErrorCode reason) { + hci::ErrorCode reason, + bool locally_initiated) { tBLE_BD_ADDR legacy_address_with_type = ToLegacyAddressWithType(address_with_type); @@ -1614,10 +1616,14 @@ void shim::legacy::Acl::OnLeConnectFail(hci::AddressWithType address_with_type, bool enhanced = true; /* TODO logging metrics only */ tHCI_STATUS status = ToLegacyHciErrorCode(reason); - pimpl_->shadow_acceptlist_.Remove(address_with_type); - TRY_POSTING_ON_MAIN(acl_interface_.connection.le.on_failed, - legacy_address_with_type, handle, enhanced, status); + legacy_address_with_type, handle, enhanced, status, + locally_initiated); + if (!locally_initiated) { + return; + } + + pimpl_->shadow_acceptlist_.Remove(address_with_type); LOG_WARN("Connection failed le remote:%s", PRIVATE_ADDRESS(address_with_type)); BTM_LogHistory( diff --git a/system/main/shim/acl.h b/system/main/shim/acl.h index a4ede40354..859071a315 100644 --- a/system/main/shim/acl.h +++ b/system/main/shim/acl.h @@ -54,7 +54,8 @@ class Acl : public hci::acl_manager::ConnectionCallbacks, // hci::acl_manager::ConnectionCallbacks void OnConnectSuccess( std::unique_ptr<hci::acl_manager::ClassicAclConnection>) override; - void OnConnectFail(hci::Address, hci::ErrorCode reason) override; + void OnConnectFail(hci::Address, hci::ErrorCode reason, + bool locally_initiated) override; void HACK_OnEscoConnectRequest(hci::Address, hci::ClassOfDevice) override; void HACK_OnScoConnectRequest(hci::Address, hci::ClassOfDevice) override; @@ -65,7 +66,8 @@ class Acl : public hci::acl_manager::ConnectionCallbacks, void OnLeConnectSuccess( hci::AddressWithType, std::unique_ptr<hci::acl_manager::LeAclConnection>) override; - void OnLeConnectFail(hci::AddressWithType, hci::ErrorCode reason) override; + void OnLeConnectFail(hci::AddressWithType, hci::ErrorCode reason, + bool locally_initiated) override; void OnLeLinkDisconnected(uint16_t handle, hci::ErrorCode reason); bluetooth::hci::AddressWithType GetConnectionLocalAddress( const RawAddress& remote_bda); diff --git a/system/main/shim/acl_legacy_interface.h b/system/main/shim/acl_legacy_interface.h index 5422df8335..cdc429a473 100644 --- a/system/main/shim/acl_legacy_interface.h +++ b/system/main/shim/acl_legacy_interface.h @@ -34,9 +34,10 @@ namespace shim { namespace legacy { typedef struct { - void (*on_connected)(const RawAddress& bda, uint16_t handle, - uint8_t enc_mode); - void (*on_failed)(const RawAddress& bda, tHCI_STATUS status); + void (*on_connected)(const RawAddress& bda, uint16_t handle, uint8_t enc_mode, + bool locally_initiated); + void (*on_failed)(const RawAddress& bda, tHCI_STATUS status, + bool locally_initiated); void (*on_disconnected)(tHCI_STATUS status, uint16_t handle, tHCI_STATUS reason); } acl_classic_connection_interface_t; @@ -48,7 +49,7 @@ typedef struct { const RawAddress& local_rpa, const RawAddress& peer_rpa, tBLE_ADDR_TYPE peer_addr_type); void (*on_failed)(const tBLE_BD_ADDR& address_with_type, uint16_t handle, - bool enhanced, tHCI_STATUS status); + bool enhanced, tHCI_STATUS status, bool locally_initiated); void (*on_disconnected)(tHCI_STATUS status, uint16_t handle, tHCI_STATUS reason); void (*on_iso_disconnected)(uint16_t handle, tHCI_STATUS reason); diff --git a/system/main/test/main_shim_test.cc b/system/main/test/main_shim_test.cc index fd4d108c82..71ee878dde 100644 --- a/system/main/test/main_shim_test.cc +++ b/system/main/test/main_shim_test.cc @@ -122,10 +122,12 @@ void mock_on_send_data_upwards(BT_HDR*) {} void mock_on_packets_completed(uint16_t handle, uint16_t num_packets) {} void mock_connection_classic_on_connected(const RawAddress& bda, - uint16_t handle, uint8_t enc_mode) {} + uint16_t handle, uint8_t enc_mode, + bool locally_initiated) {} void mock_connection_classic_on_failed(const RawAddress& bda, - tHCI_STATUS status) {} + tHCI_STATUS status, + bool locally_initiated) {} void mock_connection_classic_on_disconnected(tHCI_STATUS status, uint16_t handle, @@ -141,7 +143,7 @@ void mock_connection_le_on_connected( tBLE_ADDR_TYPE peer_addr_type) {} void mock_connection_le_on_failed(const tBLE_BD_ADDR& address_with_type, uint16_t handle, bool enhanced, - tHCI_STATUS status) {} + tHCI_STATUS status, bool locally_initiated) {} static std::promise<uint16_t> mock_connection_le_on_disconnected_promise; void mock_connection_le_on_disconnected(tHCI_STATUS status, uint16_t handle, tHCI_STATUS reason) { diff --git a/system/service/adapter.cc b/system/service/adapter.cc index 19e7400a62..a89477240e 100644 --- a/system/service/adapter.cc +++ b/system/service/adapter.cc @@ -692,7 +692,8 @@ class AdapterImpl : public Adapter, public hal::BluetoothInterface::Observer { void AclStateChangedCallback(bt_status_t status, const RawAddress& remote_bdaddr, bt_acl_state_t state, int transport_link_type, - bt_hci_error_code_t hci_reason) override { + bt_hci_error_code_t hci_reason, + bt_conn_direction_t direction) override { std::string device_address = BtAddrString(&remote_bdaddr); bool connected = (state == BT_ACL_STATE_CONNECTED); LOG(INFO) << "ACL state changed: " << device_address diff --git a/system/service/hal/bluetooth_interface.cc b/system/service/hal/bluetooth_interface.cc index 7167919ec5..01f2ff5714 100644 --- a/system/service/hal/bluetooth_interface.cc +++ b/system/service/hal/bluetooth_interface.cc @@ -163,7 +163,8 @@ void LeAddressAssociateCallback(RawAddress* main_bd_addr, void AclStateChangedCallback(bt_status_t status, RawAddress* remote_bd_addr, bt_acl_state_t state, int transport_link_type, - bt_hci_error_code_t hci_reason) { + bt_hci_error_code_t hci_reason, + bt_conn_direction_t direction) { shared_lock<shared_mutex_impl> lock(g_instance_lock); VERIFY_INTERFACE_OR_RETURN(); CHECK(remote_bd_addr); @@ -172,8 +173,9 @@ void AclStateChangedCallback(bt_status_t status, RawAddress* remote_bd_addr, << " - 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, transport_link_type, hci_reason)); + FOR_EACH_BLUETOOTH_OBSERVER( + AclStateChangedCallback(status, *remote_bd_addr, state, + transport_link_type, hci_reason, direction)); } void ThreadEventCallback(bt_cb_thread_evt evt) { @@ -452,7 +454,7 @@ void BluetoothInterface::Observer::BondStateChangedCallback( void BluetoothInterface::Observer::AclStateChangedCallback( bt_status_t /* status */, const RawAddress& /* remote_bdaddr */, bt_acl_state_t /* state */, int /* transport_link_type */, - bt_hci_error_code_t /* hci_reason */) { + bt_hci_error_code_t /* hci_reason */, bt_conn_direction_t /* direction */) { // Do nothing. } diff --git a/system/service/hal/bluetooth_interface.h b/system/service/hal/bluetooth_interface.h index 10f9c1e1c3..82f9f9c07a 100644 --- a/system/service/hal/bluetooth_interface.h +++ b/system/service/hal/bluetooth_interface.h @@ -76,7 +76,8 @@ class BluetoothInterface { const RawAddress& remote_bdaddr, bt_acl_state_t state, int transport_link_type, - bt_hci_error_code_t hci_reason); + bt_hci_error_code_t hci_reason, + bt_conn_direction_t direction); virtual void LinkQualityReportCallback( uint64_t timestamp, int report_id, int rssi, int snr, int retransmission_count, int packets_not_receive_count, diff --git a/system/service/hal/fake_bluetooth_interface.cc b/system/service/hal/fake_bluetooth_interface.cc index 4635408687..bcd7382b46 100644 --- a/system/service/hal/fake_bluetooth_interface.cc +++ b/system/service/hal/fake_bluetooth_interface.cc @@ -157,10 +157,12 @@ void FakeBluetoothInterface::NotifyAdapterLocalLeFeaturesPropertyChanged( void FakeBluetoothInterface::NotifyAclStateChangedCallback( bt_status_t status, const RawAddress& remote_bdaddr, bt_acl_state_t state, - int transport_link_type, bt_hci_error_code_t hci_reason) { + int transport_link_type, bt_hci_error_code_t hci_reason, + bt_conn_direction_t direction) { for (auto& observer : observers_) { observer.AclStateChangedCallback(status, remote_bdaddr, state, - transport_link_type, hci_reason); + transport_link_type, hci_reason, + direction); } } diff --git a/system/service/hal/fake_bluetooth_interface.h b/system/service/hal/fake_bluetooth_interface.h index 08f189a737..9beabe26ce 100644 --- a/system/service/hal/fake_bluetooth_interface.h +++ b/system/service/hal/fake_bluetooth_interface.h @@ -62,7 +62,8 @@ class FakeBluetoothInterface : public BluetoothInterface { const RawAddress& remote_bdaddr, bt_acl_state_t state, int transport_link_type, - bt_hci_error_code_t hci_reason); + bt_hci_error_code_t hci_reason, + bt_conn_direction_t direction); // hal::BluetoothInterface overrides: void AddObserver(Observer* observer) override; diff --git a/system/service/test/adapter_unittest.cc b/system/service/test/adapter_unittest.cc index 6c736097dc..c88dc2d6e7 100644 --- a/system/service/test/adapter_unittest.cc +++ b/system/service/test/adapter_unittest.cc @@ -262,8 +262,8 @@ TEST_F(AdapterTest, IsDeviceConnected) { // status != BT_STATUS_SUCCESS should be ignored fake_hal_iface_->NotifyAclStateChangedCallback( - BT_STATUS_FAIL, hal_addr, BT_ACL_STATE_CONNECTED, BT_TRANSPORT_LE, - 0xff); // HCI_ERR_UNDEFINED + BT_STATUS_FAIL, hal_addr, BT_ACL_STATE_CONNECTED, BT_TRANSPORT_LE, 0xff, + BT_CONN_DIRECTION_OUTGOING); // HCI_ERR_UNDEFINED EXPECT_FALSE(adapter_->IsDeviceConnected(kDeviceAddr)); EXPECT_TRUE(observer.last_connection_state_address().empty()); EXPECT_FALSE(observer.last_device_connected_state()); @@ -271,7 +271,7 @@ TEST_F(AdapterTest, IsDeviceConnected) { // Connected fake_hal_iface_->NotifyAclStateChangedCallback( BT_STATUS_SUCCESS, hal_addr, BT_ACL_STATE_CONNECTED, BT_TRANSPORT_LE, - 0x00); // HCI_SUCCESS + 0x00, BT_CONN_DIRECTION_OUTGOING); // HCI_SUCCESS EXPECT_TRUE(adapter_->IsDeviceConnected(kDeviceAddr)); EXPECT_EQ(kDeviceAddr, observer.last_connection_state_address()); EXPECT_TRUE(observer.last_device_connected_state()); @@ -279,7 +279,7 @@ TEST_F(AdapterTest, IsDeviceConnected) { // Disconnected fake_hal_iface_->NotifyAclStateChangedCallback( BT_STATUS_SUCCESS, hal_addr, BT_ACL_STATE_DISCONNECTED, BT_TRANSPORT_LE, - 0x16); // HCI_ERR_CONN_CAUSE_LOCAL_HOST + 0x16, BT_CONN_DIRECTION_OUTGOING); // HCI_ERR_CONN_CAUSE_LOCAL_HOST EXPECT_FALSE(adapter_->IsDeviceConnected(kDeviceAddr)); EXPECT_EQ(kDeviceAddr, observer.last_connection_state_address()); EXPECT_FALSE(observer.last_device_connected_state()); diff --git a/system/stack/acl/acl.h b/system/stack/acl/acl.h index 1e65b242cb..97364723e5 100644 --- a/system/stack/acl/acl.h +++ b/system/stack/acl/acl.h @@ -396,6 +396,7 @@ struct tACL_CB { uint16_t btm_acl_pkt_types_supported = kDefaultPacketTypeMask; uint16_t btm_def_link_policy; tHCI_STATUS acl_disc_reason = HCI_ERR_UNDEFINED; + bool locally_initiated; public: void SetDefaultPacketTypeMask(uint16_t packet_type_mask) { @@ -404,6 +405,8 @@ struct tACL_CB { tHCI_STATUS get_disconnect_reason() const { return acl_disc_reason; } void set_disconnect_reason(tHCI_STATUS reason) { acl_disc_reason = reason; } + bool is_locally_initiated() const { return locally_initiated; } + void set_locally_initiated(bool value) { locally_initiated = value; } uint16_t DefaultPacketTypes() const { return btm_acl_pkt_types_supported; } uint16_t DefaultLinkPolicy() const { return btm_def_link_policy; } diff --git a/system/stack/acl/ble_acl.cc b/system/stack/acl/ble_acl.cc index ea651d9e2f..e373cc1950 100644 --- a/system/stack/acl/ble_acl.cc +++ b/system/stack/acl/ble_acl.cc @@ -131,6 +131,7 @@ void acl_ble_enhanced_connection_complete_from_shim( const bool is_in_security_db = maybe_resolve_received_address( address_with_type, &resolved_address_with_type); + acl_set_locally_initiated(role == tHCI_ROLE::HCI_ROLE_CENTRAL); acl_ble_enhanced_connection_complete(resolved_address_with_type, handle, role, is_in_security_db, conn_interval, conn_latency, conn_timeout, local_rpa, @@ -142,8 +143,16 @@ void acl_ble_enhanced_connection_complete_from_shim( } void acl_ble_connection_fail(const tBLE_BD_ADDR& address_with_type, - uint16_t handle, bool enhanced, - tHCI_STATUS status) { + uint16_t handle, bool enhanced, tHCI_STATUS status, + bool locally_initiated) { + acl_set_locally_initiated(locally_initiated); + btm_acl_create_failed(address_with_type.bda, BT_TRANSPORT_LE, status); + + // Stop here if the connection is not locally initiated. + if (!locally_initiated) { + return; + } + if (status != HCI_ERR_ADVERTISING_TIMEOUT) { btm_cb.ble_ctr_cb.set_connection_state_idle(); btm_ble_clear_topology_mask(BTM_BLE_STATE_INIT_BIT); @@ -161,8 +170,6 @@ void acl_ble_connection_fail(const tBLE_BD_ADDR& address_with_type, } btm_ble_update_mode_operation(HCI_ROLE_UNKNOWN, &address_with_type.bda, status); - - btm_acl_create_failed(address_with_type.bda, BT_TRANSPORT_LE, status); } void gatt_notify_conn_update(const RawAddress& remote, uint16_t interval, diff --git a/system/stack/acl/btm_acl.cc b/system/stack/acl/btm_acl.cc index 98bdced377..9831e8cb55 100644 --- a/system/stack/acl/btm_acl.cc +++ b/system/stack/acl/btm_acl.cc @@ -1205,6 +1205,20 @@ tHCI_REASON btm_get_acl_disc_reason_code(void) { /******************************************************************************* * + * Function btm_is_acl_locally_initiated + * + * Description This function is called to get which side initiates the + * connection, at HCI connection complete event. + * + * Returns true if connection is locally initiated, else false. + * + ******************************************************************************/ +bool btm_is_acl_locally_initiated(void) { + return btm_cb.acl_cb_.is_locally_initiated(); +} + +/******************************************************************************* + * * Function BTM_GetHCIConnHandle * * Description This function is called to get the handle for an ACL @@ -2512,6 +2526,10 @@ void acl_set_disconnect_reason(tHCI_STATUS acl_disc_reason) { btm_cb.acl_cb_.set_disconnect_reason(acl_disc_reason); } +void acl_set_locally_initiated(bool locally_initiated) { + btm_cb.acl_cb_.set_locally_initiated(locally_initiated); +} + bool acl_is_role_switch_allowed() { return btm_cb.acl_cb_.DefaultLinkPolicy() & HCI_ENABLE_CENTRAL_PERIPHERAL_SWITCH; @@ -2534,7 +2552,7 @@ bool acl_set_peer_le_features_from_handle(uint16_t hci_handle, } void on_acl_br_edr_connected(const RawAddress& bda, uint16_t handle, - uint8_t enc_mode) { + uint8_t enc_mode, bool locally_initiated) { if (delayed_role_change_ != nullptr && delayed_role_change_->bd_addr == bda) { btm_sec_connected(bda, handle, HCI_SUCCESS, enc_mode, delayed_role_change_->new_role); @@ -2554,6 +2572,8 @@ void on_acl_br_edr_connected(const RawAddress& bda, uint16_t handle, return; } + acl_set_locally_initiated(locally_initiated); + /* * The legacy code path informs the upper layer via the BTA * layer after all relevant read_remote_ commands are complete. @@ -2563,7 +2583,8 @@ void on_acl_br_edr_connected(const RawAddress& bda, uint16_t handle, NotifyAclLinkUp(*p_acl); } -void on_acl_br_edr_failed(const RawAddress& bda, tHCI_STATUS status) { +void on_acl_br_edr_failed(const RawAddress& bda, tHCI_STATUS status, + bool locally_initiated) { ASSERT_LOG(status != HCI_SUCCESS, "Successful connection entering failing code path"); if (delayed_role_change_ != nullptr && delayed_role_change_->bd_addr == bda) { @@ -2576,6 +2597,7 @@ void on_acl_br_edr_failed(const RawAddress& bda, tHCI_STATUS status) { btm_acl_set_paging(false); l2c_link_hci_conn_comp(status, HCI_INVALID_HANDLE, bda); + acl_set_locally_initiated(locally_initiated); btm_acl_create_failed(bda, BT_TRANSPORT_BR_EDR, status); } @@ -2583,9 +2605,10 @@ void btm_acl_connected(const RawAddress& bda, uint16_t handle, tHCI_STATUS status, uint8_t enc_mode) { switch (status) { case HCI_SUCCESS: - return on_acl_br_edr_connected(bda, handle, enc_mode); + return on_acl_br_edr_connected(bda, handle, enc_mode, + true /* locally_initiated */); default: - return on_acl_br_edr_failed(bda, status); + return on_acl_br_edr_failed(bda, status, /* locally_initiated */ true); } } diff --git a/system/stack/include/acl_api.h b/system/stack/include/acl_api.h index cc7d458782..d296630500 100644 --- a/system/stack/include/acl_api.h +++ b/system/stack/include/acl_api.h @@ -251,6 +251,8 @@ uint8_t acl_link_role_from_handle(uint16_t handle); void acl_set_disconnect_reason(tHCI_STATUS acl_disc_reason); +void acl_set_locally_initiated(bool is_locally_initiated); + bool acl_is_role_switch_allowed(); uint16_t acl_get_supported_packet_types(); @@ -312,6 +314,8 @@ uint8_t btm_handle_to_acl_index(uint16_t hci_handle); tHCI_REASON btm_get_acl_disc_reason_code(void); +bool btm_is_acl_locally_initiated(void); + extern tBTM_STATUS btm_remove_acl(const RawAddress& bd_addr, tBT_TRANSPORT transport); diff --git a/system/stack/include/acl_hci_link_interface.h b/system/stack/include/acl_hci_link_interface.h index dcd86e30ec..45a8c86f3b 100644 --- a/system/stack/include/acl_hci_link_interface.h +++ b/system/stack/include/acl_hci_link_interface.h @@ -33,8 +33,9 @@ void btm_acl_connection_request(const RawAddress& bda, uint8_t* dc); void btm_acl_connected(const RawAddress& bda, uint16_t handle, tHCI_STATUS status, uint8_t enc_mode); void on_acl_br_edr_connected(const RawAddress& bda, uint16_t handle, - uint8_t enc_mode); -void on_acl_br_edr_failed(const RawAddress& bda, tHCI_STATUS status); + uint8_t enc_mode, bool locally_initiated); +void on_acl_br_edr_failed(const RawAddress& bda, tHCI_STATUS status, + bool locally_initiated); void btm_acl_disconnected(tHCI_STATUS status, uint16_t handle, tHCI_STATUS reason); void btm_acl_iso_disconnected(uint16_t handle, tHCI_STATUS reason); diff --git a/system/stack/include/ble_acl_interface.h b/system/stack/include/ble_acl_interface.h index d7c373cee6..e8719691ea 100644 --- a/system/stack/include/ble_acl_interface.h +++ b/system/stack/include/ble_acl_interface.h @@ -37,8 +37,8 @@ void acl_ble_enhanced_connection_complete_from_shim( const RawAddress& local_rpa, const RawAddress& peer_rpa, tBLE_ADDR_TYPE peer_addr_type); void acl_ble_connection_fail(const tBLE_BD_ADDR& address_with_type, - uint16_t handle, bool enhanced, - tHCI_STATUS status); + uint16_t handle, bool enhanced, tHCI_STATUS status, + bool locally_initiated); void acl_ble_update_event_received(tHCI_STATUS status, uint16_t handle, uint16_t interval, uint16_t latency, uint16_t timeout); diff --git a/system/stack/include/hci_error_code.h b/system/stack/include/hci_error_code.h index c2abb8d340..2ad1a82619 100644 --- a/system/stack/include/hci_error_code.h +++ b/system/stack/include/hci_error_code.h @@ -44,6 +44,7 @@ typedef enum : uint8_t { HCI_ERR_HOST_TIMEOUT = 0x10, // stack/btm/btm_ble_gap, HCI_ERR_ILLEGAL_PARAMETER_FMT = 0x12, HCI_ERR_PEER_USER = 0x13, + HCI_ERR_REMOTE_LOW_RESOURCE = 0x14, HCI_ERR_REMOTE_POWER_OFF = 0x15, HCI_ERR_CONN_CAUSE_LOCAL_HOST = 0x16, HCI_ERR_REPEATED_ATTEMPTS = 0x17, diff --git a/system/test/headless/headless.cc b/system/test/headless/headless.cc index f3ff188327..4489adc41e 100644 --- a/system/test/headless/headless.cc +++ b/system/test/headless/headless.cc @@ -117,7 +117,8 @@ void le_address_associate(RawAddress* main_bd_addr, /** Bluetooth ACL connection state changed callback */ void acl_state_changed(bt_status_t status, RawAddress* remote_bd_addr, bt_acl_state_t state, int transport_link_type, - bt_hci_error_code_t hci_reason) { + bt_hci_error_code_t hci_reason, + bt_conn_direction_t direction) { auto callback_list = interface_api_callback_map_.at(__func__); for (auto callback : callback_list) { interface_data_t params{ @@ -126,6 +127,7 @@ void acl_state_changed(bt_status_t status, RawAddress* remote_bd_addr, .params.acl_state_changed.remote_bd_addr = remote_bd_addr, .params.acl_state_changed.state = state, .params.acl_state_changed.hci_reason = hci_reason, + .params.acl_state_changed.direction = direction, }; (callback)(params); } diff --git a/system/test/headless/interface.h b/system/test/headless/interface.h index 468e5622c4..e39c26acd6 100644 --- a/system/test/headless/interface.h +++ b/system/test/headless/interface.h @@ -14,6 +14,7 @@ using acl_state_changed_params_t = struct { RawAddress* remote_bd_addr; bt_acl_state_t state; bt_hci_error_code_t hci_reason; + bt_conn_direction_t direction; }; using callback_params_t = union { diff --git a/system/test/mock/mock_bluetooth_interface.cc b/system/test/mock/mock_bluetooth_interface.cc index a80322dde4..ed63b61ab9 100644 --- a/system/test/mock/mock_bluetooth_interface.cc +++ b/system/test/mock/mock_bluetooth_interface.cc @@ -262,7 +262,8 @@ void invoke_le_address_associate_cb(RawAddress main_bd_addr, void invoke_acl_state_changed_cb(bt_status_t status, RawAddress bd_addr, bt_acl_state_t state, int transport_link_type, - bt_hci_error_code_t hci_reason) {} + bt_hci_error_code_t hci_reason, + bt_conn_direction_t direction) {} void invoke_thread_evt_cb(bt_cb_thread_evt event) {} diff --git a/system/test/mock/mock_stack_acl.cc b/system/test/mock/mock_stack_acl.cc index 91ee709ccb..2986960565 100644 --- a/system/test/mock/mock_stack_acl.cc +++ b/system/test/mock/mock_stack_acl.cc @@ -87,6 +87,7 @@ struct BTM_SetLinkSuperTout BTM_SetLinkSuperTout; struct BTM_SwitchRoleToCentral BTM_SwitchRoleToCentral; struct btm_remove_acl btm_remove_acl; struct btm_get_acl_disc_reason_code btm_get_acl_disc_reason_code; +struct btm_is_acl_locally_initiated btm_is_acl_locally_initiated; struct BTM_GetHCIConnHandle BTM_GetHCIConnHandle; struct BTM_GetMaxPacketSize BTM_GetMaxPacketSize; struct BTM_GetNumAclLinks BTM_GetNumAclLinks; @@ -358,6 +359,10 @@ tHCI_REASON btm_get_acl_disc_reason_code(void) { mock_function_count_map[__func__]++; return test::mock::stack_acl::btm_get_acl_disc_reason_code(); } +bool btm_is_acl_locally_initiated(void) { + mock_function_count_map[__func__]++; + return test::mock::stack_acl::btm_is_acl_locally_initiated(); +} uint16_t BTM_GetHCIConnHandle(const RawAddress& remote_bda, tBT_TRANSPORT transport) { mock_function_count_map[__func__]++; @@ -695,13 +700,15 @@ void hci_btm_set_link_supervision_timeout(tACL_CONN& link, uint16_t timeout) { test::mock::stack_acl::hci_btm_set_link_supervision_timeout(link, timeout); } void on_acl_br_edr_connected(const RawAddress& bda, uint16_t handle, - uint8_t enc_mode) { + uint8_t enc_mode, bool locally_initiated) { mock_function_count_map[__func__]++; - test::mock::stack_acl::on_acl_br_edr_connected(bda, handle, enc_mode); + test::mock::stack_acl::on_acl_br_edr_connected(bda, handle, enc_mode, + locally_initiated); } -void on_acl_br_edr_failed(const RawAddress& bda, tHCI_STATUS status) { +void on_acl_br_edr_failed(const RawAddress& bda, tHCI_STATUS status, + bool locally_initiated) { mock_function_count_map[__func__]++; - test::mock::stack_acl::on_acl_br_edr_failed(bda, status); + test::mock::stack_acl::on_acl_br_edr_failed(bda, status, locally_initiated); } // END mockcify generation diff --git a/system/test/mock/mock_stack_acl.h b/system/test/mock/mock_stack_acl.h index 8747ed7927..db05b80a89 100644 --- a/system/test/mock/mock_stack_acl.h +++ b/system/test/mock/mock_stack_acl.h @@ -483,6 +483,14 @@ struct btm_get_acl_disc_reason_code { tHCI_REASON operator()(void) { return body(); }; }; extern struct btm_get_acl_disc_reason_code btm_get_acl_disc_reason_code; +// Name: btm_is_acl_locally_initiated +// Params: void +// Returns: bool +struct btm_is_acl_locally_initiated { + std::function<bool(void)> body{[](void) { return true; }}; + bool operator()(void) { return body(); }; +}; +extern struct btm_is_acl_locally_initiated btm_is_acl_locally_initiated; // Name: BTM_GetHCIConnHandle // Params: const RawAddress& remote_bda, tBT_TRANSPORT transport // Returns: uint16_t @@ -1255,24 +1263,30 @@ struct hci_btm_set_link_supervision_timeout { extern struct hci_btm_set_link_supervision_timeout hci_btm_set_link_supervision_timeout; // Name: on_acl_br_edr_connected -// Params: const RawAddress& bda, uint16_t handle, uint8_t enc_mode -// Returns: void +// Params: const RawAddress& bda, uint16_t handle, uint8_t enc_mode, bool +// locally_initiated Returns: void struct on_acl_br_edr_connected { - std::function<void(const RawAddress& bda, uint16_t handle, uint8_t enc_mode)> - body{[](const RawAddress& bda, uint16_t handle, uint8_t enc_mode) { ; }}; - void operator()(const RawAddress& bda, uint16_t handle, uint8_t enc_mode) { - body(bda, handle, enc_mode); + std::function<void(const RawAddress& bda, uint16_t handle, uint8_t enc_mode, + bool locally_initiated)> + body{[](const RawAddress& bda, uint16_t handle, uint8_t enc_mode, + bool locally_initiated) { ; }}; + void operator()(const RawAddress& bda, uint16_t handle, uint8_t enc_mode, + bool locally_initiated) { + body(bda, handle, enc_mode, locally_initiated); }; }; extern struct on_acl_br_edr_connected on_acl_br_edr_connected; // Name: on_acl_br_edr_failed -// Params: const RawAddress& bda, tHCI_STATUS status +// Params: const RawAddress& bda, tHCI_STATUS status, bool locally_initiated // Returns: void struct on_acl_br_edr_failed { - std::function<void(const RawAddress& bda, tHCI_STATUS status)> body{ - [](const RawAddress& bda, tHCI_STATUS status) { ; }}; - void operator()(const RawAddress& bda, tHCI_STATUS status) { - body(bda, status); + std::function<void(const RawAddress& bda, tHCI_STATUS status, + bool locally_initiated)> + body{[](const RawAddress& bda, tHCI_STATUS status, + bool locally_initiated) { ; }}; + void operator()(const RawAddress& bda, tHCI_STATUS status, + bool locally_initiated) { + body(bda, status, locally_initiated); }; }; extern struct on_acl_br_edr_failed on_acl_br_edr_failed; diff --git a/system/test/mock/mock_stack_acl_ble.cc b/system/test/mock/mock_stack_acl_ble.cc index 7a1925425c..8e87f4d9e0 100644 --- a/system/test/mock/mock_stack_acl_ble.cc +++ b/system/test/mock/mock_stack_acl_ble.cc @@ -48,8 +48,8 @@ void acl_ble_connection_complete(const tBLE_BD_ADDR& address_with_type, mock_function_count_map[__func__]++; } void acl_ble_connection_fail(const tBLE_BD_ADDR& address_with_type, - uint16_t handle, bool enhanced, - tHCI_STATUS status) { + uint16_t handle, bool enhanced, tHCI_STATUS status, + bool locally_initiated) { mock_function_count_map[__func__]++; } void acl_ble_enhanced_connection_complete( |