Loading android/app/src/com/android/bluetooth/a2dp/A2dpService.java +3 −2 Original line number Diff line number Diff line Loading @@ -413,9 +413,10 @@ public class A2dpService extends ProfileService { if (!isOutgoingRequest) { HeadsetService headsetService = HeadsetService.getHeadsetService(); if (headsetService != null && headsetService.okToAcceptConnection(device, true)) { Log.d(TAG, "okToConnect: Fallback connection to allowed HFP profile"); Log.d(TAG, "okToConnect: return false," + " Fallback connection to allowed HFP profile"); headsetService.connect(device); return true; return false; } } // Otherwise, reject the connection if connectionPolicy is not valid. Loading android/app/src/com/android/bluetooth/hfp/HeadsetService.java +2 −2 Original line number Diff line number Diff line Loading @@ -2070,10 +2070,10 @@ public class HeadsetService extends ProfileService { if (!isOutgoingRequest) { A2dpService a2dpService = A2dpService.getA2dpService(); if (a2dpService != null && a2dpService.okToConnect(device, true)) { Log.d(TAG, "okToAcceptConnection: return temporary true," Log.d(TAG, "okToAcceptConnection: return false," + " Fallback connection to allowed A2DP profile"); a2dpService.connect(device); return true; return false; } } Log.w(TAG, "okToAcceptConnection: return false, connectionPolicy=" + connectionPolicy); Loading apex/permissions/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -6,4 +6,5 @@ prebuilt_etc { name: "privapp_allowlist_com.android.bluetooth.services.xml", src: "com.android.bluetooth.services.xml", sub_dir: "permissions", installable: false, } No newline at end of file system/bta/dm/bta_dm_act.cc +45 −18 Original line number Diff line number Diff line Loading @@ -3209,6 +3209,16 @@ void bta_dm_eir_update_uuid(uint16_t uuid16, bool adding) { } #endif static tBTA_DM_PEER_DEVICE* find_connected_device( const RawAddress& bd_addr, UNUSED_ATTR tBT_TRANSPORT transport) { for (uint8_t i = 0; i < bta_dm_cb.device_list.count; i++) { if (bta_dm_cb.device_list.peer_device[i].peer_bdaddr == bd_addr && bta_dm_cb.device_list.peer_device[i].conn_state == BTA_DM_CONNECTED) return &bta_dm_cb.device_list.peer_device[i]; } return nullptr; } /******************************************************************************* * * Function bta_dm_encrypt_cback Loading Loading @@ -3264,29 +3274,35 @@ void bta_dm_encrypt_cback(const RawAddress* bd_addr, tBT_TRANSPORT transport, void bta_dm_set_encryption(const RawAddress& bd_addr, tBT_TRANSPORT transport, tBTA_DM_ENCRYPT_CBACK* p_callback, tBTM_BLE_SEC_ACT sec_act) { uint8_t i; APPL_TRACE_DEBUG("bta_dm_set_encryption"); // todo if (!p_callback) { APPL_TRACE_ERROR("bta_dm_set_encryption callback is not provided"); if (p_callback == nullptr) { LOG_ERROR("bta_dm_set_encryption callback is not provided"); return; } for (i = 0; i < bta_dm_cb.device_list.count; i++) { if (bta_dm_cb.device_list.peer_device[i].peer_bdaddr == bd_addr && bta_dm_cb.device_list.peer_device[i].conn_state == BTA_DM_CONNECTED) break; tBTA_DM_PEER_DEVICE* device = find_connected_device(bd_addr, transport); if (device == nullptr) { LOG_ERROR("Unable to find active ACL connection device:%s transport:%s", PRIVATE_ADDRESS(bd_addr), bt_transport_text(transport).c_str()); return; } if (i < bta_dm_cb.device_list.count) { if (bta_dm_cb.device_list.peer_device[i].p_encrypt_cback) { APPL_TRACE_ERROR("earlier enc was not done for same device"); if (device->p_encrypt_cback) { LOG_ERROR( "Unable to start encryption as already in progress peer:%s " "transport:%s", PRIVATE_ADDRESS(bd_addr), bt_transport_text(transport).c_str()); (*p_callback)(bd_addr, transport, BTA_BUSY); return; } if (BTM_SetEncryption(bd_addr, transport, bta_dm_encrypt_cback, NULL, sec_act) == BTM_CMD_STARTED) { bta_dm_cb.device_list.peer_device[i].p_encrypt_cback = p_callback; } device->p_encrypt_cback = p_callback; LOG_DEBUG("Started encryption peer:%s transport:%s", PRIVATE_ADDRESS(bd_addr), bt_transport_text(transport).c_str()); } else { LOG_ERROR("Unable to start encryption process peer:%s transport:%s", PRIVATE_ADDRESS(bd_addr), bt_transport_text(transport).c_str()); } } Loading Loading @@ -4079,3 +4095,14 @@ void bta_dm_process_delete_key_RC_to_unpair(const RawAddress& bd_addr) bta_dm_cb.p_sec_cback(BTA_DM_REPORT_BONDING_EVT, ¶m); } namespace bluetooth { namespace legacy { namespace testing { tBTA_DM_PEER_DEVICE* allocate_device_for(const RawAddress& bd_addr, tBT_TRANSPORT transport) { return ::allocate_device_for(bd_addr, transport); } } // namespace testing } // namespace legacy } // namespace bluetooth system/bta/test/bta_dm_test.cc +97 −0 Original line number Diff line number Diff line Loading @@ -18,14 +18,21 @@ #include <base/location.h> #include <gtest/gtest.h> #include <chrono> #include "bta/dm/bta_dm_int.h" #include "bta/hf_client/bta_hf_client_int.h" #include "bta/include/bta_api.h" #include "bta/include/bta_dm_api.h" #include "bta/include/bta_hf_client_api.h" #include "btif/include/stack_manager.h" #include "common/message_loop_thread.h" #include "stack/include/btm_status.h" #include "test/mock/mock_osi_alarm.h" #include "test/mock/mock_stack_acl.h" #include "test/mock/mock_stack_btm_sec.h" using namespace std::chrono_literals; std::map<std::string, int> mock_function_count_map; Loading @@ -39,6 +46,12 @@ class MessageLoop; namespace { constexpr uint8_t kUnusedTimer = BTA_ID_MAX; const char* test_flags[] = { "INIT_logging_debug_enabled_for_all=true", nullptr, }; } // namespace struct alarm_t { Loading @@ -50,6 +63,7 @@ class BtaDmTest : public testing::Test { protected: void SetUp() override { mock_function_count_map.clear(); bluetooth::common::InitFlags::Load(test_flags); test::mock::osi_alarm::alarm_new.body = [](const char* name) -> alarm_t* { return new alarm_t(name); }; Loading Loading @@ -175,3 +189,86 @@ TEST_F(BtaDmTest, disable_second_pass_with_acl_links) { test::mock::stack_acl::BTM_GetNumAclLinks = {}; test::mock::osi_alarm::alarm_set_on_mloop = {}; } namespace { struct BTA_DM_ENCRYPT_CBACK_parms { const RawAddress bd_addr; tBT_TRANSPORT transport; tBTA_STATUS result; }; std::queue<BTA_DM_ENCRYPT_CBACK_parms> BTA_DM_ENCRYPT_CBACK_queue; void BTA_DM_ENCRYPT_CBACK(const RawAddress& bd_addr, tBT_TRANSPORT transport, tBTA_STATUS result) { BTA_DM_ENCRYPT_CBACK_queue.push({bd_addr, transport, result}); } } // namespace namespace bluetooth { namespace legacy { namespace testing { tBTA_DM_PEER_DEVICE* allocate_device_for(const RawAddress& bd_addr, tBT_TRANSPORT transport); } // namespace testing } // namespace legacy } // namespace bluetooth TEST_F(BtaDmTest, bta_dm_set_encryption) { const RawAddress bd_addr{{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}}; const tBT_TRANSPORT transport{BT_TRANSPORT_LE}; const tBTM_BLE_SEC_ACT sec_act{BTM_BLE_SEC_NONE}; // Callback not provided bta_dm_set_encryption(bd_addr, transport, nullptr, sec_act); // Device connection does not exist bta_dm_set_encryption(bd_addr, transport, BTA_DM_ENCRYPT_CBACK, sec_act); // Setup a connected device tBTA_DM_PEER_DEVICE* device = bluetooth::legacy::testing::allocate_device_for(bd_addr, transport); ASSERT_TRUE(device != nullptr); device->conn_state = BTA_DM_CONNECTED; device->p_encrypt_cback = nullptr; // Setup a device that is busy with another encryption // Fake indication that the encryption is in progress with non-null callback device->p_encrypt_cback = BTA_DM_ENCRYPT_CBACK; bta_dm_set_encryption(bd_addr, transport, BTA_DM_ENCRYPT_CBACK, sec_act); ASSERT_EQ(0, mock_function_count_map["BTM_SetEncryption"]); ASSERT_EQ(1UL, BTA_DM_ENCRYPT_CBACK_queue.size()); auto params = BTA_DM_ENCRYPT_CBACK_queue.front(); BTA_DM_ENCRYPT_CBACK_queue.pop(); ASSERT_EQ(BTA_BUSY, params.result); device->p_encrypt_cback = nullptr; // Setup a device that fails encryption test::mock::stack_btm_sec::BTM_SetEncryption.body = [](const RawAddress& bd_addr, tBT_TRANSPORT transport, tBTM_SEC_CALLBACK* p_callback, void* p_ref_data, tBTM_BLE_SEC_ACT sec_act) -> tBTM_STATUS { return BTM_MODE_UNSUPPORTED; }; bta_dm_set_encryption(bd_addr, transport, BTA_DM_ENCRYPT_CBACK, sec_act); ASSERT_EQ(1, mock_function_count_map["BTM_SetEncryption"]); ASSERT_EQ(0UL, BTA_DM_ENCRYPT_CBACK_queue.size()); device->p_encrypt_cback = nullptr; // Setup a device that successfully starts encryption test::mock::stack_btm_sec::BTM_SetEncryption.body = [](const RawAddress& bd_addr, tBT_TRANSPORT transport, tBTM_SEC_CALLBACK* p_callback, void* p_ref_data, tBTM_BLE_SEC_ACT sec_act) -> tBTM_STATUS { return BTM_CMD_STARTED; }; bta_dm_set_encryption(bd_addr, transport, BTA_DM_ENCRYPT_CBACK, sec_act); ASSERT_EQ(2, mock_function_count_map["BTM_SetEncryption"]); ASSERT_EQ(0UL, BTA_DM_ENCRYPT_CBACK_queue.size()); ASSERT_NE(nullptr, device->p_encrypt_cback); test::mock::stack_btm_sec::BTM_SetEncryption = {}; BTA_DM_ENCRYPT_CBACK_queue = {}; } Loading
android/app/src/com/android/bluetooth/a2dp/A2dpService.java +3 −2 Original line number Diff line number Diff line Loading @@ -413,9 +413,10 @@ public class A2dpService extends ProfileService { if (!isOutgoingRequest) { HeadsetService headsetService = HeadsetService.getHeadsetService(); if (headsetService != null && headsetService.okToAcceptConnection(device, true)) { Log.d(TAG, "okToConnect: Fallback connection to allowed HFP profile"); Log.d(TAG, "okToConnect: return false," + " Fallback connection to allowed HFP profile"); headsetService.connect(device); return true; return false; } } // Otherwise, reject the connection if connectionPolicy is not valid. Loading
android/app/src/com/android/bluetooth/hfp/HeadsetService.java +2 −2 Original line number Diff line number Diff line Loading @@ -2070,10 +2070,10 @@ public class HeadsetService extends ProfileService { if (!isOutgoingRequest) { A2dpService a2dpService = A2dpService.getA2dpService(); if (a2dpService != null && a2dpService.okToConnect(device, true)) { Log.d(TAG, "okToAcceptConnection: return temporary true," Log.d(TAG, "okToAcceptConnection: return false," + " Fallback connection to allowed A2DP profile"); a2dpService.connect(device); return true; return false; } } Log.w(TAG, "okToAcceptConnection: return false, connectionPolicy=" + connectionPolicy); Loading
apex/permissions/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -6,4 +6,5 @@ prebuilt_etc { name: "privapp_allowlist_com.android.bluetooth.services.xml", src: "com.android.bluetooth.services.xml", sub_dir: "permissions", installable: false, } No newline at end of file
system/bta/dm/bta_dm_act.cc +45 −18 Original line number Diff line number Diff line Loading @@ -3209,6 +3209,16 @@ void bta_dm_eir_update_uuid(uint16_t uuid16, bool adding) { } #endif static tBTA_DM_PEER_DEVICE* find_connected_device( const RawAddress& bd_addr, UNUSED_ATTR tBT_TRANSPORT transport) { for (uint8_t i = 0; i < bta_dm_cb.device_list.count; i++) { if (bta_dm_cb.device_list.peer_device[i].peer_bdaddr == bd_addr && bta_dm_cb.device_list.peer_device[i].conn_state == BTA_DM_CONNECTED) return &bta_dm_cb.device_list.peer_device[i]; } return nullptr; } /******************************************************************************* * * Function bta_dm_encrypt_cback Loading Loading @@ -3264,29 +3274,35 @@ void bta_dm_encrypt_cback(const RawAddress* bd_addr, tBT_TRANSPORT transport, void bta_dm_set_encryption(const RawAddress& bd_addr, tBT_TRANSPORT transport, tBTA_DM_ENCRYPT_CBACK* p_callback, tBTM_BLE_SEC_ACT sec_act) { uint8_t i; APPL_TRACE_DEBUG("bta_dm_set_encryption"); // todo if (!p_callback) { APPL_TRACE_ERROR("bta_dm_set_encryption callback is not provided"); if (p_callback == nullptr) { LOG_ERROR("bta_dm_set_encryption callback is not provided"); return; } for (i = 0; i < bta_dm_cb.device_list.count; i++) { if (bta_dm_cb.device_list.peer_device[i].peer_bdaddr == bd_addr && bta_dm_cb.device_list.peer_device[i].conn_state == BTA_DM_CONNECTED) break; tBTA_DM_PEER_DEVICE* device = find_connected_device(bd_addr, transport); if (device == nullptr) { LOG_ERROR("Unable to find active ACL connection device:%s transport:%s", PRIVATE_ADDRESS(bd_addr), bt_transport_text(transport).c_str()); return; } if (i < bta_dm_cb.device_list.count) { if (bta_dm_cb.device_list.peer_device[i].p_encrypt_cback) { APPL_TRACE_ERROR("earlier enc was not done for same device"); if (device->p_encrypt_cback) { LOG_ERROR( "Unable to start encryption as already in progress peer:%s " "transport:%s", PRIVATE_ADDRESS(bd_addr), bt_transport_text(transport).c_str()); (*p_callback)(bd_addr, transport, BTA_BUSY); return; } if (BTM_SetEncryption(bd_addr, transport, bta_dm_encrypt_cback, NULL, sec_act) == BTM_CMD_STARTED) { bta_dm_cb.device_list.peer_device[i].p_encrypt_cback = p_callback; } device->p_encrypt_cback = p_callback; LOG_DEBUG("Started encryption peer:%s transport:%s", PRIVATE_ADDRESS(bd_addr), bt_transport_text(transport).c_str()); } else { LOG_ERROR("Unable to start encryption process peer:%s transport:%s", PRIVATE_ADDRESS(bd_addr), bt_transport_text(transport).c_str()); } } Loading Loading @@ -4079,3 +4095,14 @@ void bta_dm_process_delete_key_RC_to_unpair(const RawAddress& bd_addr) bta_dm_cb.p_sec_cback(BTA_DM_REPORT_BONDING_EVT, ¶m); } namespace bluetooth { namespace legacy { namespace testing { tBTA_DM_PEER_DEVICE* allocate_device_for(const RawAddress& bd_addr, tBT_TRANSPORT transport) { return ::allocate_device_for(bd_addr, transport); } } // namespace testing } // namespace legacy } // namespace bluetooth
system/bta/test/bta_dm_test.cc +97 −0 Original line number Diff line number Diff line Loading @@ -18,14 +18,21 @@ #include <base/location.h> #include <gtest/gtest.h> #include <chrono> #include "bta/dm/bta_dm_int.h" #include "bta/hf_client/bta_hf_client_int.h" #include "bta/include/bta_api.h" #include "bta/include/bta_dm_api.h" #include "bta/include/bta_hf_client_api.h" #include "btif/include/stack_manager.h" #include "common/message_loop_thread.h" #include "stack/include/btm_status.h" #include "test/mock/mock_osi_alarm.h" #include "test/mock/mock_stack_acl.h" #include "test/mock/mock_stack_btm_sec.h" using namespace std::chrono_literals; std::map<std::string, int> mock_function_count_map; Loading @@ -39,6 +46,12 @@ class MessageLoop; namespace { constexpr uint8_t kUnusedTimer = BTA_ID_MAX; const char* test_flags[] = { "INIT_logging_debug_enabled_for_all=true", nullptr, }; } // namespace struct alarm_t { Loading @@ -50,6 +63,7 @@ class BtaDmTest : public testing::Test { protected: void SetUp() override { mock_function_count_map.clear(); bluetooth::common::InitFlags::Load(test_flags); test::mock::osi_alarm::alarm_new.body = [](const char* name) -> alarm_t* { return new alarm_t(name); }; Loading Loading @@ -175,3 +189,86 @@ TEST_F(BtaDmTest, disable_second_pass_with_acl_links) { test::mock::stack_acl::BTM_GetNumAclLinks = {}; test::mock::osi_alarm::alarm_set_on_mloop = {}; } namespace { struct BTA_DM_ENCRYPT_CBACK_parms { const RawAddress bd_addr; tBT_TRANSPORT transport; tBTA_STATUS result; }; std::queue<BTA_DM_ENCRYPT_CBACK_parms> BTA_DM_ENCRYPT_CBACK_queue; void BTA_DM_ENCRYPT_CBACK(const RawAddress& bd_addr, tBT_TRANSPORT transport, tBTA_STATUS result) { BTA_DM_ENCRYPT_CBACK_queue.push({bd_addr, transport, result}); } } // namespace namespace bluetooth { namespace legacy { namespace testing { tBTA_DM_PEER_DEVICE* allocate_device_for(const RawAddress& bd_addr, tBT_TRANSPORT transport); } // namespace testing } // namespace legacy } // namespace bluetooth TEST_F(BtaDmTest, bta_dm_set_encryption) { const RawAddress bd_addr{{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}}; const tBT_TRANSPORT transport{BT_TRANSPORT_LE}; const tBTM_BLE_SEC_ACT sec_act{BTM_BLE_SEC_NONE}; // Callback not provided bta_dm_set_encryption(bd_addr, transport, nullptr, sec_act); // Device connection does not exist bta_dm_set_encryption(bd_addr, transport, BTA_DM_ENCRYPT_CBACK, sec_act); // Setup a connected device tBTA_DM_PEER_DEVICE* device = bluetooth::legacy::testing::allocate_device_for(bd_addr, transport); ASSERT_TRUE(device != nullptr); device->conn_state = BTA_DM_CONNECTED; device->p_encrypt_cback = nullptr; // Setup a device that is busy with another encryption // Fake indication that the encryption is in progress with non-null callback device->p_encrypt_cback = BTA_DM_ENCRYPT_CBACK; bta_dm_set_encryption(bd_addr, transport, BTA_DM_ENCRYPT_CBACK, sec_act); ASSERT_EQ(0, mock_function_count_map["BTM_SetEncryption"]); ASSERT_EQ(1UL, BTA_DM_ENCRYPT_CBACK_queue.size()); auto params = BTA_DM_ENCRYPT_CBACK_queue.front(); BTA_DM_ENCRYPT_CBACK_queue.pop(); ASSERT_EQ(BTA_BUSY, params.result); device->p_encrypt_cback = nullptr; // Setup a device that fails encryption test::mock::stack_btm_sec::BTM_SetEncryption.body = [](const RawAddress& bd_addr, tBT_TRANSPORT transport, tBTM_SEC_CALLBACK* p_callback, void* p_ref_data, tBTM_BLE_SEC_ACT sec_act) -> tBTM_STATUS { return BTM_MODE_UNSUPPORTED; }; bta_dm_set_encryption(bd_addr, transport, BTA_DM_ENCRYPT_CBACK, sec_act); ASSERT_EQ(1, mock_function_count_map["BTM_SetEncryption"]); ASSERT_EQ(0UL, BTA_DM_ENCRYPT_CBACK_queue.size()); device->p_encrypt_cback = nullptr; // Setup a device that successfully starts encryption test::mock::stack_btm_sec::BTM_SetEncryption.body = [](const RawAddress& bd_addr, tBT_TRANSPORT transport, tBTM_SEC_CALLBACK* p_callback, void* p_ref_data, tBTM_BLE_SEC_ACT sec_act) -> tBTM_STATUS { return BTM_CMD_STARTED; }; bta_dm_set_encryption(bd_addr, transport, BTA_DM_ENCRYPT_CBACK, sec_act); ASSERT_EQ(2, mock_function_count_map["BTM_SetEncryption"]); ASSERT_EQ(0UL, BTA_DM_ENCRYPT_CBACK_queue.size()); ASSERT_NE(nullptr, device->p_encrypt_cback); test::mock::stack_btm_sec::BTM_SetEncryption = {}; BTA_DM_ENCRYPT_CBACK_queue = {}; }