Loading system/gd/hci/acl_manager/le_acl_connection.h +5 −3 Original line number Diff line number Diff line Loading @@ -95,6 +95,11 @@ class LeAclConnection : public AclConnection { // Called once before passing the connection to the client virtual LeConnectionManagementCallbacks* GetEventCallbacks(std::function<void(uint16_t)> invalidate_callbacks); protected: AddressWithType local_address_; AddressWithType remote_address_; Role role_; private: virtual bool check_connection_parameters( uint16_t conn_interval_min, Loading @@ -103,9 +108,6 @@ class LeAclConnection : public AclConnection { uint16_t expected_supervision_timeout); struct impl; struct impl* pimpl_ = nullptr; AddressWithType local_address_; AddressWithType remote_address_; Role role_; }; } // namespace acl_manager Loading system/main/shim/acl.cc +1 −1 Original line number Diff line number Diff line Loading @@ -653,7 +653,7 @@ class ClassicShimAclConnection return; } if (page_number != max_page_number) if (max_page_number != 0 && page_number != max_page_number) connection_->ReadRemoteExtendedFeatures(page_number + 1); } Loading system/main/test/main_shim_test.cc +237 −22 Original line number Diff line number Diff line Loading @@ -33,6 +33,8 @@ #include "hci/acl_manager/le_connection_callbacks.h" #include "hci/acl_manager/le_connection_management_callbacks.h" #include "hci/acl_manager_mock.h" #include "hci/address.h" #include "hci/address_with_type.h" #include "hci/controller_mock.h" #include "hci/le_advertising_manager_mock.h" #include "hci/le_scanning_manager_mock.h" Loading @@ -50,8 +52,12 @@ #include "os/thread.h" #include "packet/packet_view.h" #include "stack/btm/btm_int_types.h" #include "stack/include/acl_hci_link_interface.h" #include "stack/include/ble_acl_interface.h" #include "stack/include/bt_hdr.h" #include "stack/include/hci_error_code.h" #include "stack/include/sco_hci_link_interface.h" #include "stack/include/sec_hci_link_interface.h" #include "stack/l2cap/l2c_int.h" #include "test/common/jni_thread.h" #include "test/common/main_handler.h" Loading @@ -65,6 +71,7 @@ using ::testing::_; using namespace bluetooth; using namespace testing; using HciHandle = uint16_t; namespace test = bluetooth::hci::testing; Loading @@ -90,26 +97,19 @@ struct controller_t mock_controller { const controller_t* controller_get_interface() { return &mock_controller; } void mock_on_send_data_upwards(BT_HDR*) { mock_function_count_map[__func__]++; } void mock_on_send_data_upwards(BT_HDR*) {} void mock_on_packets_completed(uint16_t handle, uint16_t num_packets) { mock_function_count_map[__func__]++; } 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) { mock_function_count_map[__func__]++; } uint16_t handle, uint8_t enc_mode) {} void mock_connection_classic_on_failed(const RawAddress& bda, tHCI_STATUS status) { mock_function_count_map[__func__]++; } tHCI_STATUS status) {} void mock_connection_classic_on_disconnected(tHCI_STATUS status, uint16_t handle, tHCI_STATUS reason) { mock_function_count_map[__func__]++; ASSERT_TRUE(mock_function_handle_promise_map.find(__func__) != mock_function_handle_promise_map.end()); mock_function_handle_promise_map[__func__].set_value(handle); Loading @@ -118,19 +118,20 @@ void mock_connection_le_on_connected( const tBLE_BD_ADDR& address_with_type, uint16_t handle, tHCI_ROLE role, uint16_t conn_interval, uint16_t conn_latency, uint16_t conn_timeout, const RawAddress& local_rpa, const RawAddress& peer_rpa, tBLE_ADDR_TYPE peer_addr_type) { mock_function_count_map[__func__]++; } 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) { mock_function_count_map[__func__]++; } tHCI_STATUS status) {} 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) { mock_function_count_map[__func__]++; mock_connection_le_on_disconnected_promise.set_value(handle); } void mock_link_classic_on_read_remote_extended_features_complete( uint16_t handle, uint8_t current_page_number, uint8_t max_page_number, uint64_t features) {} const shim::legacy::acl_interface_t GetMockAclInterface() { shim::legacy::acl_interface_t acl_interface{ .on_send_data_upwards = mock_on_send_data_upwards, Loading Loading @@ -168,7 +169,8 @@ const shim::legacy::acl_interface_t GetMockAclInterface() { .link.classic.on_read_link_quality_complete = nullptr, .link.classic.on_read_link_supervision_timeout_complete = nullptr, .link.classic.on_read_remote_version_information_complete = nullptr, .link.classic.on_read_remote_extended_features_complete = nullptr, .link.classic.on_read_remote_extended_features_complete = mock_link_classic_on_read_remote_extended_features_complete, .link.classic.on_read_rssi_complete = nullptr, .link.classic.on_read_transmit_power_level_complete = nullptr, .link.classic.on_role_change = nullptr, Loading Loading @@ -238,6 +240,15 @@ class MockClassicAclConnection bool ReadRemoteVersionInformation() override { return true; } bool ReadRemoteSupportedFeatures() override { return true; } std::function<void(uint8_t)> read_remote_extended_features_function_{}; bool ReadRemoteExtendedFeatures(uint8_t page_number) override { if (read_remote_extended_features_function_) { read_remote_extended_features_function_(page_number); } return true; } bool Disconnect(hci::DisconnectReason reason) override { disconnect_cnt_++; disconnect_promise_.set_value(handle_); Loading @@ -252,6 +263,54 @@ class MockClassicAclConnection int disconnect_cnt_{0}; }; class MockLeAclConnection : public bluetooth::hci::acl_manager::LeAclConnection { public: MockLeAclConnection(uint16_t handle, hci::AddressWithType local_address, hci::AddressWithType remote_address, hci::Role role) { handle_ = handle; local_address_ = local_address; remote_address_ = remote_address; role_ = role; } void RegisterCallbacks( hci::acl_manager::LeConnectionManagementCallbacks* callbacks, os::Handler* handler) override { callbacks_ = callbacks; handler_ = handler; } // Returns the bidi queue for this mock connection AclConnection::QueueUpEnd* GetAclQueueEnd() const override { return &mock_acl_queue_; } mutable common::BidiQueueEnd<hci::BasePacketBuilder, packet::PacketView<hci::kLittleEndian>> mock_acl_queue_{&tx_, &rx_}; MockEnQueue<hci::BasePacketBuilder> tx_; MockDeQueue<packet::PacketView<hci::kLittleEndian>> rx_; bool ReadRemoteVersionInformation() override { return true; } bool LeReadRemoteFeatures() override { return true; } void Disconnect(hci::DisconnectReason reason) override { disconnect_cnt_++; disconnect_promise_.set_value(handle_); } std::promise<uint16_t> disconnect_promise_; hci::acl_manager::LeConnectionManagementCallbacks* callbacks_{nullptr}; os::Handler* handler_{nullptr}; hci::LeAclConnectionInterface* le_acl_connection_interface_{nullptr}; int disconnect_cnt_{0}; }; namespace bluetooth { namespace shim { void init_activity_attribution() {} Loading Loading @@ -281,9 +340,8 @@ class MainShimTest : public testing::Test { public: protected: void SetUp() override { reset_mock_function_count_map(); main_thread_start_up(); post_on_bt_main([]() { LOG_INFO("Main thread started"); }); thread_ = new os::Thread("acl_thread", os::Thread::Priority::NORMAL); handler_ = new os::Handler(thread_); Loading Loading @@ -311,7 +369,9 @@ class MainShimTest : public testing::Test { delete handler_; delete thread_; post_on_bt_main([]() { LOG_INFO("Main thread stopped"); }); main_thread_shut_down(); reset_mock_function_count_map(); } os::Thread* thread_{nullptr}; os::Handler* handler_{nullptr}; Loading @@ -334,6 +394,65 @@ class MainShimTest : public testing::Test { } }; class MainShimTestWithClassicConnection : public MainShimTest { protected: void SetUp() override { MainShimTest::SetUp(); hci::Address address({0x11, 0x22, 0x33, 0x44, 0x55, 0x66}); acl_ = MakeAcl(); // Create connection EXPECT_CALL(*test::mock_acl_manager_, CreateConnection(_)).Times(1); acl_->CreateClassicConnection(address); // Respond with a mock connection created auto connection = std::make_unique<MockClassicAclConnection>(address, 123); ASSERT_EQ(123, connection->GetHandle()); ASSERT_EQ(hci::Address({0x11, 0x22, 0x33, 0x44, 0x55, 0x66}), connection->GetAddress()); raw_connection_ = connection.get(); acl_->OnConnectSuccess(std::move(connection)); ASSERT_EQ(nullptr, connection); ASSERT_NE(nullptr, raw_connection_->callbacks_); } void TearDown() override { // Specify local disconnect request auto tx_disconnect_future = raw_connection_->disconnect_promise_.get_future(); acl_->DisconnectClassic(123, HCI_SUCCESS, {}); // Wait for disconnect to be received uint16_t result = tx_disconnect_future.get(); ASSERT_EQ(123, result); // Now emulate the remote disconnect response auto handle_promise = std::promise<uint16_t>(); auto rx_disconnect_future = handle_promise.get_future(); mock_function_handle_promise_map ["mock_connection_classic_on_disconnected"] = std::move(handle_promise); raw_connection_->callbacks_->OnDisconnection(hci::ErrorCode::SUCCESS); result = rx_disconnect_future.get(); ASSERT_EQ(123, result); // *Our* task completing indicates reactor is done std::promise<void> done; auto future = done.get_future(); handler_->Call([](std::promise<void> done) { done.set_value(); }, std::move(done)); future.wait(); acl_.reset(); MainShimTest::TearDown(); } std::unique_ptr<shim::legacy::Acl> acl_; MockClassicAclConnection* raw_connection_{nullptr}; }; TEST_F(MainShimTest, Nop) {} TEST_F(MainShimTest, Acl_Lifecycle) { Loading Loading @@ -467,7 +586,7 @@ class TestScanningCallbacks : public ::ScanningCallbacks { void OnBatchScanThresholdCrossed(int client_if) override {} }; TEST_F(MainShimTest, BleScannerInterfaceImpl_OnScanResult) { TEST_F(MainShimTest, DISABLED_BleScannerInterfaceImpl_OnScanResult) { auto* ble = static_cast<bluetooth::shim::BleScannerInterfaceImpl*>( bluetooth::shim::get_ble_scanner_instance()); Loading Loading @@ -503,3 +622,99 @@ TEST_F(MainShimTest, BleScannerInterfaceImpl_OnScanResult) { run_all_jni_thread_task(); } const char* test_flags[] = { "INIT_logging_debug_enabled_for_all=true", nullptr, }; TEST_F(MainShimTest, DISABLED_LeShimAclConnection_local_disconnect) { bluetooth::common::InitFlags::Load(test_flags); auto acl = MakeAcl(); EXPECT_CALL(*test::mock_acl_manager_, CreateLeConnection(_, _)).Times(1); hci::AddressWithType local_address( hci::Address{{0x01, 0x02, 0x03, 0x04, 0x05, 0x6}}, hci::AddressType::RANDOM_DEVICE_ADDRESS); hci::AddressWithType remote_address( hci::Address{{0x01, 0x02, 0x03, 0x04, 0x05, 0x6}}, hci::AddressType::RANDOM_DEVICE_ADDRESS); // Allow LE connections to be accepted std::promise<bool> promise; auto future = promise.get_future(); acl->AcceptLeConnectionFrom(remote_address, true, std::move(promise)); ASSERT_TRUE(future.get()); // Simulate LE connection successful uint16_t handle = 0x1234; hci::Role role; auto connection = std::make_unique<MockLeAclConnection>(handle, local_address, remote_address, role); auto raw_connection = connection.get(); acl->OnLeConnectSuccess(remote_address, std::move(connection)); ASSERT_EQ(nullptr, connection); ASSERT_NE(nullptr, raw_connection->callbacks_); // Initiate local LE disconnect mock_connection_le_on_disconnected_promise = std::promise<uint16_t>(); auto disconnect_future = mock_connection_le_on_disconnected_promise.get_future(); { raw_connection->disconnect_promise_ = std::promise<uint16_t>(); auto future = raw_connection->disconnect_promise_.get_future(); acl->DisconnectLe(0x1234, HCI_SUCCESS, __func__); uint16_t result = future.get(); ASSERT_EQ(0x1234, result); } raw_connection->callbacks_->OnDisconnection(hci::ErrorCode::SUCCESS); ASSERT_EQ(0x1234, disconnect_future.get()); } TEST_F(MainShimTestWithClassicConnection, nop) {} TEST_F(MainShimTestWithClassicConnection, read_extended_feature) { int read_remote_extended_feature_call_count = 0; raw_connection_->read_remote_extended_features_function_ = [&read_remote_extended_feature_call_count](uint8_t page_number) { read_remote_extended_feature_call_count++; }; // Handle typical case { read_remote_extended_feature_call_count = 0; const uint8_t max_page = 3; raw_connection_->callbacks_->OnReadRemoteExtendedFeaturesComplete( 1, max_page, 0xabcdef9876543210); raw_connection_->callbacks_->OnReadRemoteExtendedFeaturesComplete( 2, max_page, 0xbcdef9876543210a); raw_connection_->callbacks_->OnReadRemoteExtendedFeaturesComplete( 3, max_page, 0xcdef9876543210ab); ASSERT_EQ(static_cast<int>(max_page) - 1, read_remote_extended_feature_call_count); } // Handle extreme case { read_remote_extended_feature_call_count = 0; const uint8_t max_page = 255; for (int page = 1; page < static_cast<int>(max_page) + 1; page++) { raw_connection_->callbacks_->OnReadRemoteExtendedFeaturesComplete( static_cast<uint8_t>(page), max_page, 0xabcdef9876543210); } ASSERT_EQ(static_cast<int>(max_page - 1), read_remote_extended_feature_call_count); } // Handle case where device returns max page of zero { read_remote_extended_feature_call_count = 0; const uint8_t max_page = 0; raw_connection_->callbacks_->OnReadRemoteExtendedFeaturesComplete( 1, max_page, 0xabcdef9876543210); ASSERT_EQ(0, read_remote_extended_feature_call_count); } raw_connection_->read_remote_extended_features_function_ = {}; } system/stack/Android.bp +67 −0 Original line number Diff line number Diff line Loading @@ -1146,3 +1146,70 @@ cc_test { }, }, } cc_test { name: "net_test_stack_acl", test_suites: ["device-tests"], host_supported: true, defaults: ["fluoride_defaults"], local_include_dirs: [ "include", "test/common", ], include_dirs: [ "packages/modules/Bluetooth/system", "packages/modules/Bluetooth/system/gd", "packages/modules/Bluetooth/system/utils/include", ], generated_headers: [ "BluetoothGeneratedDumpsysDataSchema_h", "BluetoothGeneratedPackets_h", ], srcs: [ ":OsiCompatSources", ":TestCommonMainHandler", ":TestCommonMockFunctions", ":TestCommonStackConfig", ":TestMockBta", ":TestMockBtif", ":TestMockDevice", ":TestMockHci", ":TestMockLegacyHciCommands", ":TestMockLegacyHciInterface", ":TestMockMainShim", ":TestMockStackBtm", ":TestMockStackBtu", ":TestMockStackCryptotoolbox", ":TestMockStackGatt", ":TestMockStackHcic", ":TestMockStackL2cap", ":TestMockStackMetrics", ":TestMockStackSdp", ":TestMockStackSmp", "acl/*.cc", "test/stack_acl_test.cc", ], static_libs: [ "libbt-common", "libbt-protos-lite", "libgmock", "liblog", "libosi", ], shared_libs: [ "libbinder_ndk", "libcrypto", "libflatbuffers-cpp", "libprotobuf-cpp-lite", ], sanitize: { address: true, all_undefined: true, cfi: true, integer_overflow: true, scs: true, diag: { undefined : true }, }, } system/stack/acl/btm_acl.cc +1 −1 Original line number Diff line number Diff line Loading @@ -2897,7 +2897,7 @@ void acl_process_extended_features(uint16_t handle, uint8_t current_page_number, bd_features_text(p_acl->peer_lmp_feature_pages[current_page_number]) .c_str()); if (max_page_number == current_page_number) { if (max_page_number == 0 || max_page_number == current_page_number) { NotifyAclFeaturesReadComplete(*p_acl, max_page_number); } } Loading Loading
system/gd/hci/acl_manager/le_acl_connection.h +5 −3 Original line number Diff line number Diff line Loading @@ -95,6 +95,11 @@ class LeAclConnection : public AclConnection { // Called once before passing the connection to the client virtual LeConnectionManagementCallbacks* GetEventCallbacks(std::function<void(uint16_t)> invalidate_callbacks); protected: AddressWithType local_address_; AddressWithType remote_address_; Role role_; private: virtual bool check_connection_parameters( uint16_t conn_interval_min, Loading @@ -103,9 +108,6 @@ class LeAclConnection : public AclConnection { uint16_t expected_supervision_timeout); struct impl; struct impl* pimpl_ = nullptr; AddressWithType local_address_; AddressWithType remote_address_; Role role_; }; } // namespace acl_manager Loading
system/main/shim/acl.cc +1 −1 Original line number Diff line number Diff line Loading @@ -653,7 +653,7 @@ class ClassicShimAclConnection return; } if (page_number != max_page_number) if (max_page_number != 0 && page_number != max_page_number) connection_->ReadRemoteExtendedFeatures(page_number + 1); } Loading
system/main/test/main_shim_test.cc +237 −22 Original line number Diff line number Diff line Loading @@ -33,6 +33,8 @@ #include "hci/acl_manager/le_connection_callbacks.h" #include "hci/acl_manager/le_connection_management_callbacks.h" #include "hci/acl_manager_mock.h" #include "hci/address.h" #include "hci/address_with_type.h" #include "hci/controller_mock.h" #include "hci/le_advertising_manager_mock.h" #include "hci/le_scanning_manager_mock.h" Loading @@ -50,8 +52,12 @@ #include "os/thread.h" #include "packet/packet_view.h" #include "stack/btm/btm_int_types.h" #include "stack/include/acl_hci_link_interface.h" #include "stack/include/ble_acl_interface.h" #include "stack/include/bt_hdr.h" #include "stack/include/hci_error_code.h" #include "stack/include/sco_hci_link_interface.h" #include "stack/include/sec_hci_link_interface.h" #include "stack/l2cap/l2c_int.h" #include "test/common/jni_thread.h" #include "test/common/main_handler.h" Loading @@ -65,6 +71,7 @@ using ::testing::_; using namespace bluetooth; using namespace testing; using HciHandle = uint16_t; namespace test = bluetooth::hci::testing; Loading @@ -90,26 +97,19 @@ struct controller_t mock_controller { const controller_t* controller_get_interface() { return &mock_controller; } void mock_on_send_data_upwards(BT_HDR*) { mock_function_count_map[__func__]++; } void mock_on_send_data_upwards(BT_HDR*) {} void mock_on_packets_completed(uint16_t handle, uint16_t num_packets) { mock_function_count_map[__func__]++; } 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) { mock_function_count_map[__func__]++; } uint16_t handle, uint8_t enc_mode) {} void mock_connection_classic_on_failed(const RawAddress& bda, tHCI_STATUS status) { mock_function_count_map[__func__]++; } tHCI_STATUS status) {} void mock_connection_classic_on_disconnected(tHCI_STATUS status, uint16_t handle, tHCI_STATUS reason) { mock_function_count_map[__func__]++; ASSERT_TRUE(mock_function_handle_promise_map.find(__func__) != mock_function_handle_promise_map.end()); mock_function_handle_promise_map[__func__].set_value(handle); Loading @@ -118,19 +118,20 @@ void mock_connection_le_on_connected( const tBLE_BD_ADDR& address_with_type, uint16_t handle, tHCI_ROLE role, uint16_t conn_interval, uint16_t conn_latency, uint16_t conn_timeout, const RawAddress& local_rpa, const RawAddress& peer_rpa, tBLE_ADDR_TYPE peer_addr_type) { mock_function_count_map[__func__]++; } 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) { mock_function_count_map[__func__]++; } tHCI_STATUS status) {} 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) { mock_function_count_map[__func__]++; mock_connection_le_on_disconnected_promise.set_value(handle); } void mock_link_classic_on_read_remote_extended_features_complete( uint16_t handle, uint8_t current_page_number, uint8_t max_page_number, uint64_t features) {} const shim::legacy::acl_interface_t GetMockAclInterface() { shim::legacy::acl_interface_t acl_interface{ .on_send_data_upwards = mock_on_send_data_upwards, Loading Loading @@ -168,7 +169,8 @@ const shim::legacy::acl_interface_t GetMockAclInterface() { .link.classic.on_read_link_quality_complete = nullptr, .link.classic.on_read_link_supervision_timeout_complete = nullptr, .link.classic.on_read_remote_version_information_complete = nullptr, .link.classic.on_read_remote_extended_features_complete = nullptr, .link.classic.on_read_remote_extended_features_complete = mock_link_classic_on_read_remote_extended_features_complete, .link.classic.on_read_rssi_complete = nullptr, .link.classic.on_read_transmit_power_level_complete = nullptr, .link.classic.on_role_change = nullptr, Loading Loading @@ -238,6 +240,15 @@ class MockClassicAclConnection bool ReadRemoteVersionInformation() override { return true; } bool ReadRemoteSupportedFeatures() override { return true; } std::function<void(uint8_t)> read_remote_extended_features_function_{}; bool ReadRemoteExtendedFeatures(uint8_t page_number) override { if (read_remote_extended_features_function_) { read_remote_extended_features_function_(page_number); } return true; } bool Disconnect(hci::DisconnectReason reason) override { disconnect_cnt_++; disconnect_promise_.set_value(handle_); Loading @@ -252,6 +263,54 @@ class MockClassicAclConnection int disconnect_cnt_{0}; }; class MockLeAclConnection : public bluetooth::hci::acl_manager::LeAclConnection { public: MockLeAclConnection(uint16_t handle, hci::AddressWithType local_address, hci::AddressWithType remote_address, hci::Role role) { handle_ = handle; local_address_ = local_address; remote_address_ = remote_address; role_ = role; } void RegisterCallbacks( hci::acl_manager::LeConnectionManagementCallbacks* callbacks, os::Handler* handler) override { callbacks_ = callbacks; handler_ = handler; } // Returns the bidi queue for this mock connection AclConnection::QueueUpEnd* GetAclQueueEnd() const override { return &mock_acl_queue_; } mutable common::BidiQueueEnd<hci::BasePacketBuilder, packet::PacketView<hci::kLittleEndian>> mock_acl_queue_{&tx_, &rx_}; MockEnQueue<hci::BasePacketBuilder> tx_; MockDeQueue<packet::PacketView<hci::kLittleEndian>> rx_; bool ReadRemoteVersionInformation() override { return true; } bool LeReadRemoteFeatures() override { return true; } void Disconnect(hci::DisconnectReason reason) override { disconnect_cnt_++; disconnect_promise_.set_value(handle_); } std::promise<uint16_t> disconnect_promise_; hci::acl_manager::LeConnectionManagementCallbacks* callbacks_{nullptr}; os::Handler* handler_{nullptr}; hci::LeAclConnectionInterface* le_acl_connection_interface_{nullptr}; int disconnect_cnt_{0}; }; namespace bluetooth { namespace shim { void init_activity_attribution() {} Loading Loading @@ -281,9 +340,8 @@ class MainShimTest : public testing::Test { public: protected: void SetUp() override { reset_mock_function_count_map(); main_thread_start_up(); post_on_bt_main([]() { LOG_INFO("Main thread started"); }); thread_ = new os::Thread("acl_thread", os::Thread::Priority::NORMAL); handler_ = new os::Handler(thread_); Loading Loading @@ -311,7 +369,9 @@ class MainShimTest : public testing::Test { delete handler_; delete thread_; post_on_bt_main([]() { LOG_INFO("Main thread stopped"); }); main_thread_shut_down(); reset_mock_function_count_map(); } os::Thread* thread_{nullptr}; os::Handler* handler_{nullptr}; Loading @@ -334,6 +394,65 @@ class MainShimTest : public testing::Test { } }; class MainShimTestWithClassicConnection : public MainShimTest { protected: void SetUp() override { MainShimTest::SetUp(); hci::Address address({0x11, 0x22, 0x33, 0x44, 0x55, 0x66}); acl_ = MakeAcl(); // Create connection EXPECT_CALL(*test::mock_acl_manager_, CreateConnection(_)).Times(1); acl_->CreateClassicConnection(address); // Respond with a mock connection created auto connection = std::make_unique<MockClassicAclConnection>(address, 123); ASSERT_EQ(123, connection->GetHandle()); ASSERT_EQ(hci::Address({0x11, 0x22, 0x33, 0x44, 0x55, 0x66}), connection->GetAddress()); raw_connection_ = connection.get(); acl_->OnConnectSuccess(std::move(connection)); ASSERT_EQ(nullptr, connection); ASSERT_NE(nullptr, raw_connection_->callbacks_); } void TearDown() override { // Specify local disconnect request auto tx_disconnect_future = raw_connection_->disconnect_promise_.get_future(); acl_->DisconnectClassic(123, HCI_SUCCESS, {}); // Wait for disconnect to be received uint16_t result = tx_disconnect_future.get(); ASSERT_EQ(123, result); // Now emulate the remote disconnect response auto handle_promise = std::promise<uint16_t>(); auto rx_disconnect_future = handle_promise.get_future(); mock_function_handle_promise_map ["mock_connection_classic_on_disconnected"] = std::move(handle_promise); raw_connection_->callbacks_->OnDisconnection(hci::ErrorCode::SUCCESS); result = rx_disconnect_future.get(); ASSERT_EQ(123, result); // *Our* task completing indicates reactor is done std::promise<void> done; auto future = done.get_future(); handler_->Call([](std::promise<void> done) { done.set_value(); }, std::move(done)); future.wait(); acl_.reset(); MainShimTest::TearDown(); } std::unique_ptr<shim::legacy::Acl> acl_; MockClassicAclConnection* raw_connection_{nullptr}; }; TEST_F(MainShimTest, Nop) {} TEST_F(MainShimTest, Acl_Lifecycle) { Loading Loading @@ -467,7 +586,7 @@ class TestScanningCallbacks : public ::ScanningCallbacks { void OnBatchScanThresholdCrossed(int client_if) override {} }; TEST_F(MainShimTest, BleScannerInterfaceImpl_OnScanResult) { TEST_F(MainShimTest, DISABLED_BleScannerInterfaceImpl_OnScanResult) { auto* ble = static_cast<bluetooth::shim::BleScannerInterfaceImpl*>( bluetooth::shim::get_ble_scanner_instance()); Loading Loading @@ -503,3 +622,99 @@ TEST_F(MainShimTest, BleScannerInterfaceImpl_OnScanResult) { run_all_jni_thread_task(); } const char* test_flags[] = { "INIT_logging_debug_enabled_for_all=true", nullptr, }; TEST_F(MainShimTest, DISABLED_LeShimAclConnection_local_disconnect) { bluetooth::common::InitFlags::Load(test_flags); auto acl = MakeAcl(); EXPECT_CALL(*test::mock_acl_manager_, CreateLeConnection(_, _)).Times(1); hci::AddressWithType local_address( hci::Address{{0x01, 0x02, 0x03, 0x04, 0x05, 0x6}}, hci::AddressType::RANDOM_DEVICE_ADDRESS); hci::AddressWithType remote_address( hci::Address{{0x01, 0x02, 0x03, 0x04, 0x05, 0x6}}, hci::AddressType::RANDOM_DEVICE_ADDRESS); // Allow LE connections to be accepted std::promise<bool> promise; auto future = promise.get_future(); acl->AcceptLeConnectionFrom(remote_address, true, std::move(promise)); ASSERT_TRUE(future.get()); // Simulate LE connection successful uint16_t handle = 0x1234; hci::Role role; auto connection = std::make_unique<MockLeAclConnection>(handle, local_address, remote_address, role); auto raw_connection = connection.get(); acl->OnLeConnectSuccess(remote_address, std::move(connection)); ASSERT_EQ(nullptr, connection); ASSERT_NE(nullptr, raw_connection->callbacks_); // Initiate local LE disconnect mock_connection_le_on_disconnected_promise = std::promise<uint16_t>(); auto disconnect_future = mock_connection_le_on_disconnected_promise.get_future(); { raw_connection->disconnect_promise_ = std::promise<uint16_t>(); auto future = raw_connection->disconnect_promise_.get_future(); acl->DisconnectLe(0x1234, HCI_SUCCESS, __func__); uint16_t result = future.get(); ASSERT_EQ(0x1234, result); } raw_connection->callbacks_->OnDisconnection(hci::ErrorCode::SUCCESS); ASSERT_EQ(0x1234, disconnect_future.get()); } TEST_F(MainShimTestWithClassicConnection, nop) {} TEST_F(MainShimTestWithClassicConnection, read_extended_feature) { int read_remote_extended_feature_call_count = 0; raw_connection_->read_remote_extended_features_function_ = [&read_remote_extended_feature_call_count](uint8_t page_number) { read_remote_extended_feature_call_count++; }; // Handle typical case { read_remote_extended_feature_call_count = 0; const uint8_t max_page = 3; raw_connection_->callbacks_->OnReadRemoteExtendedFeaturesComplete( 1, max_page, 0xabcdef9876543210); raw_connection_->callbacks_->OnReadRemoteExtendedFeaturesComplete( 2, max_page, 0xbcdef9876543210a); raw_connection_->callbacks_->OnReadRemoteExtendedFeaturesComplete( 3, max_page, 0xcdef9876543210ab); ASSERT_EQ(static_cast<int>(max_page) - 1, read_remote_extended_feature_call_count); } // Handle extreme case { read_remote_extended_feature_call_count = 0; const uint8_t max_page = 255; for (int page = 1; page < static_cast<int>(max_page) + 1; page++) { raw_connection_->callbacks_->OnReadRemoteExtendedFeaturesComplete( static_cast<uint8_t>(page), max_page, 0xabcdef9876543210); } ASSERT_EQ(static_cast<int>(max_page - 1), read_remote_extended_feature_call_count); } // Handle case where device returns max page of zero { read_remote_extended_feature_call_count = 0; const uint8_t max_page = 0; raw_connection_->callbacks_->OnReadRemoteExtendedFeaturesComplete( 1, max_page, 0xabcdef9876543210); ASSERT_EQ(0, read_remote_extended_feature_call_count); } raw_connection_->read_remote_extended_features_function_ = {}; }
system/stack/Android.bp +67 −0 Original line number Diff line number Diff line Loading @@ -1146,3 +1146,70 @@ cc_test { }, }, } cc_test { name: "net_test_stack_acl", test_suites: ["device-tests"], host_supported: true, defaults: ["fluoride_defaults"], local_include_dirs: [ "include", "test/common", ], include_dirs: [ "packages/modules/Bluetooth/system", "packages/modules/Bluetooth/system/gd", "packages/modules/Bluetooth/system/utils/include", ], generated_headers: [ "BluetoothGeneratedDumpsysDataSchema_h", "BluetoothGeneratedPackets_h", ], srcs: [ ":OsiCompatSources", ":TestCommonMainHandler", ":TestCommonMockFunctions", ":TestCommonStackConfig", ":TestMockBta", ":TestMockBtif", ":TestMockDevice", ":TestMockHci", ":TestMockLegacyHciCommands", ":TestMockLegacyHciInterface", ":TestMockMainShim", ":TestMockStackBtm", ":TestMockStackBtu", ":TestMockStackCryptotoolbox", ":TestMockStackGatt", ":TestMockStackHcic", ":TestMockStackL2cap", ":TestMockStackMetrics", ":TestMockStackSdp", ":TestMockStackSmp", "acl/*.cc", "test/stack_acl_test.cc", ], static_libs: [ "libbt-common", "libbt-protos-lite", "libgmock", "liblog", "libosi", ], shared_libs: [ "libbinder_ndk", "libcrypto", "libflatbuffers-cpp", "libprotobuf-cpp-lite", ], sanitize: { address: true, all_undefined: true, cfi: true, integer_overflow: true, scs: true, diag: { undefined : true }, }, }
system/stack/acl/btm_acl.cc +1 −1 Original line number Diff line number Diff line Loading @@ -2897,7 +2897,7 @@ void acl_process_extended_features(uint16_t handle, uint8_t current_page_number, bd_features_text(p_acl->peer_lmp_feature_pages[current_page_number]) .c_str()); if (max_page_number == current_page_number) { if (max_page_number == 0 || max_page_number == current_page_number) { NotifyAclFeaturesReadComplete(*p_acl, max_page_number); } } Loading