diff --git a/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java b/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java index f2407fc85aa710293e86417fe2c0faaf31d29159..a7636ecfe7da44ce567bfb9e3b98397b8725131b 100644 --- a/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java +++ b/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java @@ -929,6 +929,11 @@ final class RemoteDevices { }) void aclStateChangeCallback(int status, byte[] address, int newState, int transportLinkType, int hciReason) { + if (status != AbstractionLayer.BT_STATUS_SUCCESS) { + debugLog("aclStateChangeCallback status is " + status + ", skipping"); + return; + } + BluetoothDevice device = getDevice(address); if (device == null) { diff --git a/system/bta/dm/bta_dm_act.cc b/system/bta/dm/bta_dm_act.cc index 65389ad1ff1853f8246120a5e29ec0e154b44db4..8f4809aef51643dc63b0c23f68fe8445eaaa5a75 100644 --- a/system/bta/dm/bta_dm_act.cc +++ b/system/bta/dm/bta_dm_act.cc @@ -2506,6 +2506,23 @@ void BTA_dm_acl_up(const RawAddress bd_addr, tBT_TRANSPORT transport) { do_in_main_thread(FROM_HERE, base::Bind(bta_dm_acl_up, bd_addr, transport)); } +static void bta_dm_acl_up_failed(const RawAddress bd_addr, + tBT_TRANSPORT transport, tHCI_STATUS status) { + if (bta_dm_cb.p_sec_cback) { + tBTA_DM_SEC conn = {}; + conn.link_up_failed.bd_addr = bd_addr; + conn.link_up_failed.transport_link_type = transport; + conn.link_up_failed.status = status; + bta_dm_cb.p_sec_cback(BTA_DM_LINK_UP_FAILED_EVT, &conn); + } +} + +void BTA_dm_acl_up_failed(const RawAddress bd_addr, tBT_TRANSPORT transport, + tHCI_STATUS status) { + do_in_main_thread( + FROM_HERE, base::Bind(bta_dm_acl_up_failed, bd_addr, transport, status)); +} + static void bta_dm_acl_down(const RawAddress& bd_addr, tBT_TRANSPORT transport) { bool issue_unpair_cb = false; diff --git a/system/bta/include/bta_api.h b/system/bta/include/bta_api.h index 58c4c28551a0016357e16a3f4d84715726202dee..84e3f609d751a9af9d22dbb0bd862e77b1d2fcc9 100644 --- a/system/bta/include/bta_api.h +++ b/system/bta/include/bta_api.h @@ -225,6 +225,7 @@ typedef enum : uint8_t { BTA_DM_BLE_SC_CR_LOC_OOB_EVT = 31, /* SMP SC Create Local OOB request event */ BTA_DM_REPORT_BONDING_EVT = 32, /*handle for pin or key missing*/ BTA_DM_LE_ADDR_ASSOC_EVT = 33, /* identity address association event */ + BTA_DM_LINK_UP_FAILED_EVT = 34, /* Create connection failed event */ } tBTA_DM_SEC_EVT; /* Structure associated with BTA_DM_PIN_REQ_EVT */ @@ -313,10 +314,18 @@ typedef struct { tBT_TRANSPORT transport_link_type; } tBTA_DM_LINK_UP; +/* Structure associated with BTA_DM_LINK_UP_FAILED_EVT */ +typedef struct { + RawAddress bd_addr; /* BD address peer device. */ + tBT_TRANSPORT transport_link_type; + tHCI_STATUS status; /* The HCI error code associated with this event */ +} tBTA_DM_LINK_UP_FAILED; + /* Structure associated with BTA_DM_LINK_DOWN_EVT */ typedef struct { RawAddress bd_addr; /* BD address peer device. */ tBT_TRANSPORT transport_link_type; + tHCI_STATUS status; } tBTA_DM_LINK_DOWN; #define BTA_AUTH_SP_YES \ @@ -393,7 +402,8 @@ typedef struct { typedef union { tBTA_DM_PIN_REQ pin_req; /* PIN request. */ tBTA_DM_AUTH_CMPL auth_cmpl; /* Authentication complete indication. */ - tBTA_DM_LINK_UP link_up; /* ACL connection down event */ + tBTA_DM_LINK_UP link_up; /* ACL connection up event */ + tBTA_DM_LINK_UP_FAILED link_up_failed; /* ACL connection up failure event */ tBTA_DM_LINK_DOWN link_down; /* ACL connection down event */ tBTA_DM_SP_CFM_REQ cfm_req; /* user confirm request */ tBTA_DM_SP_KEY_NOTIF key_notif; /* passkey notification */ diff --git a/system/bta/include/bta_dm_acl.h b/system/bta/include/bta_dm_acl.h index aaaa94eb35aac55e5de7ebf822fa57bd40adc2a0..a49d8ee8261758a9029debea4aa410df8acb243a 100644 --- a/system/bta/include/bta_dm_acl.h +++ b/system/bta/include/bta_dm_acl.h @@ -25,6 +25,8 @@ #include "types/raw_address.h" void BTA_dm_acl_up(const RawAddress bd_addr, tBT_TRANSPORT transport); +void BTA_dm_acl_up_failed(const RawAddress bd_addr, tBT_TRANSPORT transport, + tHCI_STATUS hci_status); void BTA_dm_acl_down(const RawAddress bd_addr, tBT_TRANSPORT transport); void BTA_dm_report_role_change(const RawAddress bd_addr, tHCI_ROLE new_role, tHCI_STATUS hci_status); diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc index 9b6e1d04e8cc51df5c4c2ea03be258511ead5802..e6029ba68d6a8485f1e1848a8f4ae52a35f458a0 100644 --- a/system/btif/src/btif_dm.cc +++ b/system/btif/src/btif_dm.cc @@ -1828,11 +1828,19 @@ static void btif_dm_upstreams_evt(uint16_t event, char* p_param) { (int)p_data->link_up.transport_link_type, HCI_SUCCESS); 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); + break; + 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); + invoke_acl_state_changed_cb( BT_STATUS_SUCCESS, bd_addr, BT_ACL_STATE_DISCONNECTED, (int)p_data->link_down.transport_link_type, diff --git a/system/stack/acl/ble_acl.cc b/system/stack/acl/ble_acl.cc index 18759f9b0e45dacf7165c678a544fb1cc2c91019..ea651d9e2f9df44fbb04e3020b0399d819c4189b 100644 --- a/system/stack/acl/ble_acl.cc +++ b/system/stack/acl/ble_acl.cc @@ -161,6 +161,8 @@ 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 0c51dae30dd77a5f79c31d0adadc6f8e1f8d1046..98bdced377c3e3dc78a52763fbd413f26cf66dd8 100644 --- a/system/stack/acl/btm_acl.cc +++ b/system/stack/acl/btm_acl.cc @@ -441,6 +441,11 @@ void btm_acl_created(const RawAddress& bda, uint16_t hci_handle, } } +void btm_acl_create_failed(const RawAddress& bda, tBT_TRANSPORT transport, + tHCI_STATUS hci_status) { + BTA_dm_acl_up_failed(bda, transport, hci_status); +} + void btm_acl_update_conn_addr(uint16_t handle, const RawAddress& address) { tACL_CONN* p_acl = internal_.acl_get_connection_from_handle(handle); if (p_acl == nullptr) { @@ -2570,6 +2575,8 @@ void on_acl_br_edr_failed(const RawAddress& bda, tHCI_STATUS status) { delayed_role_change_ = nullptr; btm_acl_set_paging(false); l2c_link_hci_conn_comp(status, HCI_INVALID_HANDLE, bda); + + btm_acl_create_failed(bda, BT_TRANSPORT_BR_EDR, status); } void btm_acl_connected(const RawAddress& bda, uint16_t handle, diff --git a/system/stack/include/acl_api.h b/system/stack/include/acl_api.h index 8faf15c748a206a820bb714c7b2fad0ee1e8949c..cc7d4587829dfb4ff2b69fc538e437d6cc6d70f4 100644 --- a/system/stack/include/acl_api.h +++ b/system/stack/include/acl_api.h @@ -292,6 +292,9 @@ bool BTM_ReadPowerMode(const RawAddress& remote_bda, tBTM_PM_MODE* p_mode); void btm_acl_created(const RawAddress& bda, uint16_t hci_handle, tHCI_ROLE link_role, tBT_TRANSPORT transport); +void btm_acl_create_failed(const RawAddress& bda, tBT_TRANSPORT transport, + tHCI_STATUS reason); + void btm_acl_removed(uint16_t handle); void acl_disconnect_from_handle(uint16_t handle, tHCI_STATUS reason, diff --git a/system/test/mock/mock_bta_dm_act.cc b/system/test/mock/mock_bta_dm_act.cc index f77e90b9b5334b3b91ae956b22972693dad3689b..b64f5f62fc6de231792522db51f777554c52edfe 100644 --- a/system/test/mock/mock_bta_dm_act.cc +++ b/system/test/mock/mock_bta_dm_act.cc @@ -42,6 +42,7 @@ namespace bta_dm_act { struct BTA_DmSetVisibility BTA_DmSetVisibility; struct BTA_dm_acl_down BTA_dm_acl_down; struct BTA_dm_acl_up BTA_dm_acl_up; +struct BTA_dm_acl_up_failed BTA_dm_acl_up_failed; struct BTA_dm_notify_remote_features_complete BTA_dm_notify_remote_features_complete; struct BTA_dm_on_hw_off BTA_dm_on_hw_off; @@ -119,6 +120,11 @@ void BTA_dm_acl_up(const RawAddress bd_addr, tBT_TRANSPORT transport) { mock_function_count_map[__func__]++; test::mock::bta_dm_act::BTA_dm_acl_up(bd_addr, transport); } +void BTA_dm_acl_up_failed(const RawAddress bd_addr, tBT_TRANSPORT transport, + tHCI_STATUS hci_status) { + mock_function_count_map[__func__]++; + test::mock::bta_dm_act::BTA_dm_acl_up_failed(bd_addr, transport, hci_status); +} void BTA_dm_notify_remote_features_complete(const RawAddress bd_addr) { mock_function_count_map[__func__]++; test::mock::bta_dm_act::BTA_dm_notify_remote_features_complete(bd_addr); diff --git a/system/test/mock/mock_bta_dm_act.h b/system/test/mock/mock_bta_dm_act.h index af586006e615eea1340a05924bfb993e1fddfed6..755e04d1815ad60ad342b1785901d37f44f73f34 100644 --- a/system/test/mock/mock_bta_dm_act.h +++ b/system/test/mock/mock_bta_dm_act.h @@ -99,6 +99,21 @@ struct BTA_dm_acl_up { }; extern struct BTA_dm_acl_up BTA_dm_acl_up; +// Name: BTA_dm_acl_up_failed +// Params: const RawAddress bd_addr, tBT_TRANSPORT transport, tHCI_STATUS +// hci_status Return: void +struct BTA_dm_acl_up_failed { + std::function<void(const RawAddress bd_addr, tBT_TRANSPORT transport, + tHCI_STATUS hci_status)> + body{[](const RawAddress bd_addr, tBT_TRANSPORT transport, + tHCI_STATUS hci_status) {}}; + void operator()(const RawAddress bd_addr, tBT_TRANSPORT transport, + tHCI_STATUS hci_status) { + body(bd_addr, transport, hci_status); + }; +}; +extern struct BTA_dm_acl_up_failed BTA_dm_acl_up_failed; + // Name: BTA_dm_notify_remote_features_complete // Params: const RawAddress bd_addr // Return: void