Loading tools/rootcanal/Android.bp +33 −0 Original line number Diff line number Diff line Loading @@ -117,6 +117,39 @@ cc_library_static { srcs: ["model/devices/scripted_beacon_ble_payload.proto"], } cc_test_host { name: "rootcanal_hci_test", defaults: [ "clang_file_coverage", "clang_coverage_bin", "rootcanal_defaults", ], srcs: [ "test/controller/le/le_add_device_to_resolving_list_test.cc", "test/controller/le/le_clear_resolving_list_test.cc", "test/controller/le/le_remove_device_from_resolving_list_test.cc", "test/controller/le/le_set_address_resolution_enable_test.cc", ], header_libs: [ "libbluetooth_headers", ], local_include_dirs: [ "include", ".", ], include_dirs: [ "packages/modules/Bluetooth/system", "packages/modules/Bluetooth/system/gd", ], shared_libs: [ "liblog", ], static_libs: [ "libbt-rootcanal", "libjsoncpp", ], } // test-vendor unit tests for host cc_test_host { name: "rootcanal_test_host", Loading tools/rootcanal/model/controller/dual_mode_controller.cc +15 −15 Original line number Diff line number Diff line Loading @@ -2041,7 +2041,7 @@ void DualModeController::LeSetAddressResolutionEnable(CommandView command) { gd_hci::LeSecurityCommandView::Create( gd_hci::SecurityCommandView::Create(command))); ASSERT(command_view.IsValid()); auto status = link_layer_controller_.LeSetAddressResolutionEnable( ErrorCode status = link_layer_controller_.LeSetAddressResolutionEnable( command_view.GetAddressResolutionEnable() == bluetooth::hci::Enable::ENABLED); send_event_( Loading Loading @@ -2374,9 +2374,9 @@ void DualModeController::LeClearResolvingList(CommandView command) { auto command_view = gd_hci::LeClearResolvingListView::Create( gd_hci::LeSecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); link_layer_controller_.LeResolvingListClear(); ErrorCode status = link_layer_controller_.LeClearResolvingList(); send_event_(bluetooth::hci::LeClearResolvingListCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); kNumCommandPackets, status)); } void DualModeController::LeReadResolvingListSize(CommandView command) { Loading Loading @@ -2438,17 +2438,17 @@ void DualModeController::LeAddDeviceToResolvingList(CommandView command) { auto command_view = gd_hci::LeAddDeviceToResolvingListView::Create( gd_hci::LeSecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); AddressType peer_address_type; AddressType peer_identity_address_type; switch (command_view.GetPeerIdentityAddressType()) { case bluetooth::hci::PeerAddressType::PUBLIC_DEVICE_OR_IDENTITY_ADDRESS: peer_address_type = AddressType::PUBLIC_DEVICE_ADDRESS; peer_identity_address_type = AddressType::PUBLIC_DEVICE_ADDRESS; break; case bluetooth::hci::PeerAddressType::RANDOM_DEVICE_OR_IDENTITY_ADDRESS: peer_address_type = AddressType::RANDOM_DEVICE_ADDRESS; peer_identity_address_type = AddressType::RANDOM_DEVICE_ADDRESS; break; } auto status = link_layer_controller_.LeResolvingListAddDevice( command_view.GetPeerIdentityAddress(), peer_address_type, ErrorCode status = link_layer_controller_.LeAddDeviceToResolvingList( peer_identity_address_type, command_view.GetPeerIdentityAddress(), command_view.GetPeerIrk(), command_view.GetLocalIrk()); send_event_(bluetooth::hci::LeAddDeviceToResolvingListCompleteBuilder::Create( kNumCommandPackets, status)); Loading @@ -2459,20 +2459,20 @@ void DualModeController::LeRemoveDeviceFromResolvingList(CommandView command) { gd_hci::LeSecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); AddressType peer_address_type; AddressType peer_identity_address_type; switch (command_view.GetPeerIdentityAddressType()) { case bluetooth::hci::PeerAddressType::PUBLIC_DEVICE_OR_IDENTITY_ADDRESS: peer_address_type = AddressType::PUBLIC_DEVICE_ADDRESS; peer_identity_address_type = AddressType::PUBLIC_DEVICE_ADDRESS; break; case bluetooth::hci::PeerAddressType::RANDOM_DEVICE_OR_IDENTITY_ADDRESS: peer_address_type = AddressType::RANDOM_DEVICE_ADDRESS; peer_identity_address_type = AddressType::RANDOM_DEVICE_ADDRESS; break; } link_layer_controller_.LeResolvingListRemoveDevice( command_view.GetPeerIdentityAddress(), peer_address_type); ErrorCode status = link_layer_controller_.LeRemoveDeviceFromResolvingList( peer_identity_address_type, command_view.GetPeerIdentityAddress()); send_event_( bluetooth::hci::LeRemoveDeviceFromResolvingListCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); kNumCommandPackets, status)); } void DualModeController::LeSetExtendedScanParameters(CommandView command) { Loading Loading @@ -2571,7 +2571,7 @@ void DualModeController::LeSetPrivacyMode(CommandView command) { break; } if (link_layer_controller_.LeResolvingListContainsDevice( peer_identity_address, peer_identity_address_type)) { peer_identity_address_type, peer_identity_address)) { link_layer_controller_.LeSetPrivacyMode( peer_identity_address_type, peer_identity_address, privacy_mode); } Loading tools/rootcanal/model/controller/link_layer_controller.cc +151 −66 Original line number Diff line number Diff line Loading @@ -67,6 +67,35 @@ bool LinkLayerController::IsLeEventUnmasked(SubeventCode subevent) const { (le_event_mask_ & bit) != 0; } bool LinkLayerController::LeResolvingListContainsDevice( AddressType peer_identity_address_type, Address peer_identity_address) { for (auto const& entry : le_resolving_list_) { if (entry.peer_identity_address_type == peer_identity_address_type && entry.peer_identity_address == peer_identity_address) { return true; } } return false; } bool LinkLayerController::LeResolvingListContainsDevice( bluetooth::hci::PeerAddressType peer_identity_address_type, Address peer_identity_address) { AddressType peer_address_type; switch (peer_identity_address_type) { case bluetooth::hci::PeerAddressType::PUBLIC_DEVICE_OR_IDENTITY_ADDRESS: peer_address_type = AddressType::PUBLIC_DEVICE_ADDRESS; break; case bluetooth::hci::PeerAddressType::RANDOM_DEVICE_OR_IDENTITY_ADDRESS: peer_address_type = AddressType::RANDOM_DEVICE_ADDRESS; break; } return LeResolvingListContainsDevice(peer_address_type, peer_identity_address); } // ============================================================================= // General LE Coommands // ============================================================================= Loading Loading @@ -130,6 +159,122 @@ ErrorCode LinkLayerController::LeSetHostFeature(uint8_t bit_number, return ErrorCode::SUCCESS; } // ============================================================================= // LE Resolving List // ============================================================================= // HCI command LE_Add_Device_To_Resolving_List (Vol 4, Part E § 7.8.38). ErrorCode LinkLayerController::LeAddDeviceToResolvingList( AddressType peer_identity_address_type, Address peer_identity_address, std::array<uint8_t, kIrkSize> peer_irk, std::array<uint8_t, kIrkSize> local_irk) { // This command shall not be used when address resolution is enabled in the // Controller and: // • Advertising (other than periodic advertising) is enabled, // • Scanning is enabled, or // • an HCI_LE_Create_Connection, HCI_LE_Extended_Create_Connection, or // HCI_LE_Periodic_Advertising_Create_Sync command is pending. if (ResolvingListBusy()) { LOG_INFO( "device is currently advertising, scanning, or establishing an" " LE connection"); return ErrorCode::COMMAND_DISALLOWED; } // When a Controller cannot add a device to the list because there is no space // available, it shall return the error code Memory Capacity Exceeded (0x07). if (le_resolving_list_.size() >= properties_.le_resolving_list_size) { LOG_INFO("resolving list is full"); return ErrorCode::MEMORY_CAPACITY_EXCEEDED; } // If there is an existing entry in the resolving list with the same // Peer_Identity_Address and Peer_Identity_Address_Type, or with the same // Peer_IRK, the Controller should return the error code Invalid HCI Command // Parameters (0x12). for (auto const& entry : le_resolving_list_) { if ((entry.peer_identity_address_type == peer_identity_address_type && entry.peer_identity_address == peer_identity_address) || entry.peer_irk == peer_irk) { LOG_INFO("device is already present in the resolving list"); return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } } le_resolving_list_.emplace_back(ResolvingListEntry{ peer_identity_address_type, peer_identity_address, peer_irk, local_irk}); return ErrorCode::SUCCESS; } // HCI command LE_Remove_Device_From_Resolving_List (Vol 4, Part E § 7.8.39). ErrorCode LinkLayerController::LeRemoveDeviceFromResolvingList( AddressType peer_identity_address_type, Address peer_identity_address) { // This command shall not be used when address resolution is enabled in the // Controller and: // • Advertising (other than periodic advertising) is enabled, // • Scanning is enabled, or // • an HCI_LE_Create_Connection, HCI_LE_Extended_Create_Connection, or // HCI_LE_Periodic_Advertising_Create_Sync command is pending. if (ResolvingListBusy()) { LOG_INFO( "device is currently advertising, scanning, or establishing an" " LE connection"); return ErrorCode::COMMAND_DISALLOWED; } for (auto it = le_resolving_list_.begin(); it != le_resolving_list_.end(); it++) { if (it->peer_identity_address_type == peer_identity_address_type && it->peer_identity_address == peer_identity_address) { le_resolving_list_.erase(it); return ErrorCode::SUCCESS; } } // When a Controller cannot remove a device from the resolving list because // it is not found, it shall return the error code // Unknown Connection Identifier (0x02). LOG_INFO("peer address not found in the resolving list"); return ErrorCode::UNKNOWN_CONNECTION; } // HCI command LE_Clear_Resolving_List (Vol 4, Part E § 7.8.40). ErrorCode LinkLayerController::LeClearResolvingList() { // This command shall not be used when address resolution is enabled in the // Controller and: // • Advertising (other than periodic advertising) is enabled, // • Scanning is enabled, or // • an HCI_LE_Create_Connection, HCI_LE_Extended_Create_Connection, or // HCI_LE_Periodic_Advertising_Create_Sync command is pending. if (ResolvingListBusy()) { LOG_INFO( "device is currently advertising, scanning," " or establishing an LE connection"); return ErrorCode::COMMAND_DISALLOWED; } le_resolving_list_.clear(); return ErrorCode::SUCCESS; } // HCI command LE_Set_Address_Resolution_Enable (Vol 4, Part E § 7.8.44). ErrorCode LinkLayerController::LeSetAddressResolutionEnable(bool enable) { // This command shall not be used when: // • Advertising (other than periodic advertising) is enabled, // • Scanning is enabled, or // • an HCI_LE_Create_Connection, HCI_LE_Extended_Create_Connection, or // HCI_LE_Periodic_Advertising_Create_Sync command is pending. if (ResolvingListBusy()) { LOG_INFO( "device is currently advertising, scanning," " or establishing an LE connection"); return ErrorCode::COMMAND_DISALLOWED; } le_resolving_list_enabled_ = enable; return ErrorCode::SUCCESS; } void LinkLayerController::SetSecureSimplePairingSupport(bool enable) { uint64_t bit = 0x1; secure_simple_pairing_host_support_ = enable; Loading Loading @@ -1596,10 +1741,10 @@ void LinkLayerController::IncomingLeLegacyAdvertisingPdu( for (const auto& entry : le_resolving_list_) { if (rpa_matches_irk(advertising_address, entry.peer_irk)) { LOG_INFO("Matched against IRK for %s", entry.address.ToString().c_str()); entry.peer_identity_address.ToString().c_str()); resolved = true; resolved_address = entry.address; resolved_address_type = entry.address_type; resolved_address = entry.peer_identity_address; resolved_address_type = entry.peer_identity_address_type; rpa = generate_rpa(entry.local_irk); } } Loading Loading @@ -3418,8 +3563,9 @@ ErrorCode LinkLayerController::SetLeExtendedAdvertisingParameters( own_address_type == bluetooth::hci::OwnAddressType::RESOLVABLE_OR_RANDOM_ADDRESS) { for (const auto& entry : le_resolving_list_) { if (entry.address == peer_address.GetAddress() && entry.address_type == peer_address.GetAddressType()) { if (entry.peer_identity_address == peer_address.GetAddress() && entry.peer_identity_address_type == peer_address.GetAddressType()) { return generate_rpa(entry.local_irk); } } Loading Loading @@ -3540,24 +3686,6 @@ ErrorCode LinkLayerController::LeFilterAcceptListClear() { return ErrorCode::SUCCESS; } ErrorCode LinkLayerController::LeSetAddressResolutionEnable(bool enable) { if (ResolvingListBusy()) { return ErrorCode::COMMAND_DISALLOWED; } le_resolving_list_enabled_ = enable; return ErrorCode::SUCCESS; } ErrorCode LinkLayerController::LeResolvingListClear() { if (ResolvingListBusy()) { return ErrorCode::COMMAND_DISALLOWED; } le_resolving_list_.clear(); return ErrorCode::SUCCESS; } ErrorCode LinkLayerController::LeFilterAcceptListAddDevice( Address addr, AddressType addr_type) { if (FilterAcceptListBusy()) { Loading @@ -3575,20 +3703,6 @@ ErrorCode LinkLayerController::LeFilterAcceptListAddDevice( return ErrorCode::SUCCESS; } ErrorCode LinkLayerController::LeResolvingListAddDevice( Address addr, AddressType addr_type, std::array<uint8_t, kIrkSize> peerIrk, std::array<uint8_t, kIrkSize> localIrk) { if (ResolvingListBusy()) { return ErrorCode::COMMAND_DISALLOWED; } if (LeResolvingListFull()) { return ErrorCode::MEMORY_CAPACITY_EXCEEDED; } le_resolving_list_.emplace_back( ResolvingListEntry{addr, addr_type, peerIrk, localIrk}); return ErrorCode::SUCCESS; } bool LinkLayerController::HasAclConnection() { return (connections_.GetAclHandles().size() > 0); } Loading Loading @@ -3949,20 +4063,6 @@ ErrorCode LinkLayerController::LeFilterAcceptListRemoveDevice( return ErrorCode::SUCCESS; } ErrorCode LinkLayerController::LeResolvingListRemoveDevice( Address addr, AddressType addr_type) { if (ResolvingListBusy()) { return ErrorCode::COMMAND_DISALLOWED; } for (size_t i = 0; i < le_resolving_list_.size(); i++) { auto curr = le_resolving_list_[i]; if (curr.address == addr && curr.address_type == addr_type) { le_resolving_list_.erase(le_resolving_list_.begin() + i); } } return ErrorCode::SUCCESS; } bool LinkLayerController::LeFilterAcceptListContainsDevice( Address addr, AddressType addr_type) { for (size_t i = 0; i < le_connect_list_.size(); i++) { Loading @@ -3974,25 +4074,10 @@ bool LinkLayerController::LeFilterAcceptListContainsDevice( return false; } bool LinkLayerController::LeResolvingListContainsDevice(Address addr, AddressType addr_type) { for (size_t i = 0; i < le_connect_list_.size(); i++) { auto curr = le_connect_list_[i]; if (curr.address == addr && curr.address_type == addr_type) { return true; } } return false; } bool LinkLayerController::LeFilterAcceptListFull() { return le_connect_list_.size() >= properties_.le_filter_accept_list_size; } bool LinkLayerController::LeResolvingListFull() { return le_resolving_list_.size() >= properties_.le_resolving_list_size; } void LinkLayerController::Reset() { connections_ = AclConnectionHandler(); le_connect_list_.clear(); Loading tools/rootcanal/model/controller/link_layer_controller.h +37 −16 Original line number Diff line number Diff line Loading @@ -48,12 +48,6 @@ class LinkLayerController { public: static constexpr size_t kIrkSize = 16; // HCI LE Set Random Address command (Vol 4, Part E § 7.8.4). ErrorCode LeSetRandomAddress(Address random_address); // HCI LE Set Host Feature command (Vol 4, Part E § 7.8.115). ErrorCode LeSetHostFeature(uint8_t bit_number, uint8_t bit_value); LinkLayerController(const Address& address, const ControllerProperties& properties); Loading Loading @@ -218,15 +212,13 @@ class LinkLayerController { ErrorCode LeFilterAcceptListRemoveDevice(Address addr, AddressType addr_type); bool LeFilterAcceptListContainsDevice(Address addr, AddressType addr_type); bool LeFilterAcceptListFull(); bool ResolvingListBusy(); ErrorCode LeSetAddressResolutionEnable(bool enable); ErrorCode LeResolvingListClear(); ErrorCode LeResolvingListAddDevice(Address addr, AddressType addr_type, std::array<uint8_t, kIrkSize> peerIrk, std::array<uint8_t, kIrkSize> localIrk); ErrorCode LeResolvingListRemoveDevice(Address addr, AddressType addr_type); bool LeResolvingListContainsDevice(Address addr, AddressType addr_type); bool LeResolvingListFull(); bool LeResolvingListContainsDevice(AddressType peer_identity_address_type, Address peer_identity_address); bool LeResolvingListContainsDevice( bluetooth::hci::PeerAddressType peer_identity_address_type, Address peer_identity_address); void LeSetPrivacyMode(AddressType address_type, Address addr, uint8_t mode); void LeReadIsoTxSync(uint16_t handle); Loading Loading @@ -401,6 +393,32 @@ class LinkLayerController { void HandleIso(bluetooth::hci::IsoView iso); // LE Commands // HCI LE Set Random Address command (Vol 4, Part E § 7.8.4). ErrorCode LeSetRandomAddress(Address random_address); // HCI LE Set Host Feature command (Vol 4, Part E § 7.8.115). ErrorCode LeSetHostFeature(uint8_t bit_number, uint8_t bit_value); // LE Address Resolving // HCI command LE_Add_Device_To_Resolving_List (Vol 4, Part E § 7.8.38). ErrorCode LeAddDeviceToResolvingList(AddressType peer_identity_address_type, Address peer_address, std::array<uint8_t, kIrkSize> peer_irk, std::array<uint8_t, kIrkSize> local_irk); // HCI command LE_Remove_Device_From_Resolving_List (Vol 4, Part E § 7.8.39). ErrorCode LeRemoveDeviceFromResolvingList( AddressType peer_identity_address_type, Address peer_identity_address); // HCI command LE_Clear_Resolving_List (Vol 4, Part E § 7.8.40). ErrorCode LeClearResolvingList(); // HCI command LE_Set_Address_Resolution_Enable (Vol 4, Part E § 7.8.44). ErrorCode LeSetAddressResolutionEnable(bool enable); protected: void SendLeLinkLayerPacketWithRssi( Address source, Address dest, uint8_t rssi, Loading Loading @@ -761,12 +779,14 @@ class LinkLayerController { AddressType address_type; }; std::vector<ConnectListEntry> le_connect_list_; struct ResolvingListEntry { Address address; AddressType address_type; AddressType peer_identity_address_type; Address peer_identity_address; std::array<uint8_t, kIrkSize> peer_irk; std::array<uint8_t, kIrkSize> local_irk; }; std::vector<ResolvingListEntry> le_resolving_list_; bool le_resolving_list_enabled_{false}; Loading Loading @@ -803,6 +823,7 @@ class LinkLayerController { #else SecurityManager security_manager_{10}; #endif /* ROOTCANAL_LMP */ std::chrono::steady_clock::time_point last_inquiry_; model::packets::InquiryType inquiry_mode_{ model::packets::InquiryType::STANDARD}; Loading tools/rootcanal/test/controller/le/le_add_device_to_resolving_list_test.cc 0 → 100644 +128 −0 Original line number Diff line number Diff line /* * Copyright 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <gtest/gtest.h> #include "model/controller/link_layer_controller.h" namespace rootcanal { using namespace bluetooth::hci; class LeAddDeviceToResolvingListTest : public ::testing::Test { public: LeAddDeviceToResolvingListTest() { // Reduce the size of the resolving list to simplify testing. properties_.le_resolving_list_size = 2; } ~LeAddDeviceToResolvingListTest() override = default; protected: Address address_{0}; ControllerProperties properties_{}; LinkLayerController controller_{address_, properties_}; }; TEST_F(LeAddDeviceToResolvingListTest, Success) { ASSERT_EQ(controller_.LeAddDeviceToResolvingList( AddressType::PUBLIC_DEVICE_ADDRESS, Address{1}, std::array<uint8_t, 16>{1}, std::array<uint8_t, 16>{1}), ErrorCode::SUCCESS); ASSERT_EQ(controller_.LeAddDeviceToResolvingList( AddressType::RANDOM_DEVICE_ADDRESS, Address{1}, std::array<uint8_t, 16>{2}, std::array<uint8_t, 16>{2}), ErrorCode::SUCCESS); } TEST_F(LeAddDeviceToResolvingListTest, ListFull) { ASSERT_EQ(controller_.LeAddDeviceToResolvingList( AddressType::PUBLIC_DEVICE_ADDRESS, Address{1}, std::array<uint8_t, 16>{1}, std::array<uint8_t, 16>{1}), ErrorCode::SUCCESS); ASSERT_EQ(controller_.LeAddDeviceToResolvingList( AddressType::PUBLIC_DEVICE_ADDRESS, Address{2}, std::array<uint8_t, 16>{2}, std::array<uint8_t, 16>{2}), ErrorCode::SUCCESS); ASSERT_EQ(controller_.LeAddDeviceToResolvingList( AddressType::PUBLIC_DEVICE_ADDRESS, Address{3}, std::array<uint8_t, 16>{3}, std::array<uint8_t, 16>{3}), ErrorCode::MEMORY_CAPACITY_EXCEEDED); } TEST_F(LeAddDeviceToResolvingListTest, ScanningActive) { ASSERT_EQ(controller_.LeSetAddressResolutionEnable(true), ErrorCode::SUCCESS); controller_.SetLeScanEnable(OpCode::LE_SET_SCAN_ENABLE); ASSERT_EQ(controller_.LeAddDeviceToResolvingList( AddressType::PUBLIC_DEVICE_ADDRESS, Address{1}, std::array<uint8_t, 16>{1}, std::array<uint8_t, 16>{1}), ErrorCode::COMMAND_DISALLOWED); } TEST_F(LeAddDeviceToResolvingListTest, LegacyAdvertisingActive) { ASSERT_EQ(controller_.LeSetAddressResolutionEnable(true), ErrorCode::SUCCESS); ASSERT_EQ(controller_.SetLeAdvertisingEnable(1), ErrorCode::SUCCESS); ASSERT_EQ(controller_.LeAddDeviceToResolvingList( AddressType::PUBLIC_DEVICE_ADDRESS, Address{1}, std::array<uint8_t, 16>{1}, std::array<uint8_t, 16>{1}), ErrorCode::COMMAND_DISALLOWED); } TEST_F(LeAddDeviceToResolvingListTest, ExtendedAdvertisingActive) { EnabledSet enabled_set; enabled_set.advertising_handle_ = 1; enabled_set.duration_ = 0; ASSERT_EQ(controller_.LeSetAddressResolutionEnable(true), ErrorCode::SUCCESS); ASSERT_EQ(controller_.SetLeExtendedAdvertisingEnable(Enable::ENABLED, {enabled_set}), ErrorCode::SUCCESS); ASSERT_EQ(controller_.LeAddDeviceToResolvingList( AddressType::PUBLIC_DEVICE_ADDRESS, Address{1}, std::array<uint8_t, 16>{1}, std::array<uint8_t, 16>{1}), ErrorCode::COMMAND_DISALLOWED); } TEST_F(LeAddDeviceToResolvingListTest, PeerAddressDuplicate) { ASSERT_EQ(controller_.LeAddDeviceToResolvingList( AddressType::PUBLIC_DEVICE_ADDRESS, Address{1}, std::array<uint8_t, 16>{1}, std::array<uint8_t, 16>{1}), ErrorCode::SUCCESS); ASSERT_EQ(controller_.LeAddDeviceToResolvingList( AddressType::PUBLIC_DEVICE_ADDRESS, Address{1}, std::array<uint8_t, 16>{2}, std::array<uint8_t, 16>{2}), ErrorCode::INVALID_HCI_COMMAND_PARAMETERS); } TEST_F(LeAddDeviceToResolvingListTest, PeerIrkDuplicate) { ASSERT_EQ(controller_.LeAddDeviceToResolvingList( AddressType::PUBLIC_DEVICE_ADDRESS, Address{1}, std::array<uint8_t, 16>{1}, std::array<uint8_t, 16>{1}), ErrorCode::SUCCESS); ASSERT_EQ(controller_.LeAddDeviceToResolvingList( AddressType::RANDOM_DEVICE_ADDRESS, Address{1}, std::array<uint8_t, 16>{1}, std::array<uint8_t, 16>{1}), ErrorCode::INVALID_HCI_COMMAND_PARAMETERS); } } // namespace rootcanal Loading
tools/rootcanal/Android.bp +33 −0 Original line number Diff line number Diff line Loading @@ -117,6 +117,39 @@ cc_library_static { srcs: ["model/devices/scripted_beacon_ble_payload.proto"], } cc_test_host { name: "rootcanal_hci_test", defaults: [ "clang_file_coverage", "clang_coverage_bin", "rootcanal_defaults", ], srcs: [ "test/controller/le/le_add_device_to_resolving_list_test.cc", "test/controller/le/le_clear_resolving_list_test.cc", "test/controller/le/le_remove_device_from_resolving_list_test.cc", "test/controller/le/le_set_address_resolution_enable_test.cc", ], header_libs: [ "libbluetooth_headers", ], local_include_dirs: [ "include", ".", ], include_dirs: [ "packages/modules/Bluetooth/system", "packages/modules/Bluetooth/system/gd", ], shared_libs: [ "liblog", ], static_libs: [ "libbt-rootcanal", "libjsoncpp", ], } // test-vendor unit tests for host cc_test_host { name: "rootcanal_test_host", Loading
tools/rootcanal/model/controller/dual_mode_controller.cc +15 −15 Original line number Diff line number Diff line Loading @@ -2041,7 +2041,7 @@ void DualModeController::LeSetAddressResolutionEnable(CommandView command) { gd_hci::LeSecurityCommandView::Create( gd_hci::SecurityCommandView::Create(command))); ASSERT(command_view.IsValid()); auto status = link_layer_controller_.LeSetAddressResolutionEnable( ErrorCode status = link_layer_controller_.LeSetAddressResolutionEnable( command_view.GetAddressResolutionEnable() == bluetooth::hci::Enable::ENABLED); send_event_( Loading Loading @@ -2374,9 +2374,9 @@ void DualModeController::LeClearResolvingList(CommandView command) { auto command_view = gd_hci::LeClearResolvingListView::Create( gd_hci::LeSecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); link_layer_controller_.LeResolvingListClear(); ErrorCode status = link_layer_controller_.LeClearResolvingList(); send_event_(bluetooth::hci::LeClearResolvingListCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); kNumCommandPackets, status)); } void DualModeController::LeReadResolvingListSize(CommandView command) { Loading Loading @@ -2438,17 +2438,17 @@ void DualModeController::LeAddDeviceToResolvingList(CommandView command) { auto command_view = gd_hci::LeAddDeviceToResolvingListView::Create( gd_hci::LeSecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); AddressType peer_address_type; AddressType peer_identity_address_type; switch (command_view.GetPeerIdentityAddressType()) { case bluetooth::hci::PeerAddressType::PUBLIC_DEVICE_OR_IDENTITY_ADDRESS: peer_address_type = AddressType::PUBLIC_DEVICE_ADDRESS; peer_identity_address_type = AddressType::PUBLIC_DEVICE_ADDRESS; break; case bluetooth::hci::PeerAddressType::RANDOM_DEVICE_OR_IDENTITY_ADDRESS: peer_address_type = AddressType::RANDOM_DEVICE_ADDRESS; peer_identity_address_type = AddressType::RANDOM_DEVICE_ADDRESS; break; } auto status = link_layer_controller_.LeResolvingListAddDevice( command_view.GetPeerIdentityAddress(), peer_address_type, ErrorCode status = link_layer_controller_.LeAddDeviceToResolvingList( peer_identity_address_type, command_view.GetPeerIdentityAddress(), command_view.GetPeerIrk(), command_view.GetLocalIrk()); send_event_(bluetooth::hci::LeAddDeviceToResolvingListCompleteBuilder::Create( kNumCommandPackets, status)); Loading @@ -2459,20 +2459,20 @@ void DualModeController::LeRemoveDeviceFromResolvingList(CommandView command) { gd_hci::LeSecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); AddressType peer_address_type; AddressType peer_identity_address_type; switch (command_view.GetPeerIdentityAddressType()) { case bluetooth::hci::PeerAddressType::PUBLIC_DEVICE_OR_IDENTITY_ADDRESS: peer_address_type = AddressType::PUBLIC_DEVICE_ADDRESS; peer_identity_address_type = AddressType::PUBLIC_DEVICE_ADDRESS; break; case bluetooth::hci::PeerAddressType::RANDOM_DEVICE_OR_IDENTITY_ADDRESS: peer_address_type = AddressType::RANDOM_DEVICE_ADDRESS; peer_identity_address_type = AddressType::RANDOM_DEVICE_ADDRESS; break; } link_layer_controller_.LeResolvingListRemoveDevice( command_view.GetPeerIdentityAddress(), peer_address_type); ErrorCode status = link_layer_controller_.LeRemoveDeviceFromResolvingList( peer_identity_address_type, command_view.GetPeerIdentityAddress()); send_event_( bluetooth::hci::LeRemoveDeviceFromResolvingListCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); kNumCommandPackets, status)); } void DualModeController::LeSetExtendedScanParameters(CommandView command) { Loading Loading @@ -2571,7 +2571,7 @@ void DualModeController::LeSetPrivacyMode(CommandView command) { break; } if (link_layer_controller_.LeResolvingListContainsDevice( peer_identity_address, peer_identity_address_type)) { peer_identity_address_type, peer_identity_address)) { link_layer_controller_.LeSetPrivacyMode( peer_identity_address_type, peer_identity_address, privacy_mode); } Loading
tools/rootcanal/model/controller/link_layer_controller.cc +151 −66 Original line number Diff line number Diff line Loading @@ -67,6 +67,35 @@ bool LinkLayerController::IsLeEventUnmasked(SubeventCode subevent) const { (le_event_mask_ & bit) != 0; } bool LinkLayerController::LeResolvingListContainsDevice( AddressType peer_identity_address_type, Address peer_identity_address) { for (auto const& entry : le_resolving_list_) { if (entry.peer_identity_address_type == peer_identity_address_type && entry.peer_identity_address == peer_identity_address) { return true; } } return false; } bool LinkLayerController::LeResolvingListContainsDevice( bluetooth::hci::PeerAddressType peer_identity_address_type, Address peer_identity_address) { AddressType peer_address_type; switch (peer_identity_address_type) { case bluetooth::hci::PeerAddressType::PUBLIC_DEVICE_OR_IDENTITY_ADDRESS: peer_address_type = AddressType::PUBLIC_DEVICE_ADDRESS; break; case bluetooth::hci::PeerAddressType::RANDOM_DEVICE_OR_IDENTITY_ADDRESS: peer_address_type = AddressType::RANDOM_DEVICE_ADDRESS; break; } return LeResolvingListContainsDevice(peer_address_type, peer_identity_address); } // ============================================================================= // General LE Coommands // ============================================================================= Loading Loading @@ -130,6 +159,122 @@ ErrorCode LinkLayerController::LeSetHostFeature(uint8_t bit_number, return ErrorCode::SUCCESS; } // ============================================================================= // LE Resolving List // ============================================================================= // HCI command LE_Add_Device_To_Resolving_List (Vol 4, Part E § 7.8.38). ErrorCode LinkLayerController::LeAddDeviceToResolvingList( AddressType peer_identity_address_type, Address peer_identity_address, std::array<uint8_t, kIrkSize> peer_irk, std::array<uint8_t, kIrkSize> local_irk) { // This command shall not be used when address resolution is enabled in the // Controller and: // • Advertising (other than periodic advertising) is enabled, // • Scanning is enabled, or // • an HCI_LE_Create_Connection, HCI_LE_Extended_Create_Connection, or // HCI_LE_Periodic_Advertising_Create_Sync command is pending. if (ResolvingListBusy()) { LOG_INFO( "device is currently advertising, scanning, or establishing an" " LE connection"); return ErrorCode::COMMAND_DISALLOWED; } // When a Controller cannot add a device to the list because there is no space // available, it shall return the error code Memory Capacity Exceeded (0x07). if (le_resolving_list_.size() >= properties_.le_resolving_list_size) { LOG_INFO("resolving list is full"); return ErrorCode::MEMORY_CAPACITY_EXCEEDED; } // If there is an existing entry in the resolving list with the same // Peer_Identity_Address and Peer_Identity_Address_Type, or with the same // Peer_IRK, the Controller should return the error code Invalid HCI Command // Parameters (0x12). for (auto const& entry : le_resolving_list_) { if ((entry.peer_identity_address_type == peer_identity_address_type && entry.peer_identity_address == peer_identity_address) || entry.peer_irk == peer_irk) { LOG_INFO("device is already present in the resolving list"); return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } } le_resolving_list_.emplace_back(ResolvingListEntry{ peer_identity_address_type, peer_identity_address, peer_irk, local_irk}); return ErrorCode::SUCCESS; } // HCI command LE_Remove_Device_From_Resolving_List (Vol 4, Part E § 7.8.39). ErrorCode LinkLayerController::LeRemoveDeviceFromResolvingList( AddressType peer_identity_address_type, Address peer_identity_address) { // This command shall not be used when address resolution is enabled in the // Controller and: // • Advertising (other than periodic advertising) is enabled, // • Scanning is enabled, or // • an HCI_LE_Create_Connection, HCI_LE_Extended_Create_Connection, or // HCI_LE_Periodic_Advertising_Create_Sync command is pending. if (ResolvingListBusy()) { LOG_INFO( "device is currently advertising, scanning, or establishing an" " LE connection"); return ErrorCode::COMMAND_DISALLOWED; } for (auto it = le_resolving_list_.begin(); it != le_resolving_list_.end(); it++) { if (it->peer_identity_address_type == peer_identity_address_type && it->peer_identity_address == peer_identity_address) { le_resolving_list_.erase(it); return ErrorCode::SUCCESS; } } // When a Controller cannot remove a device from the resolving list because // it is not found, it shall return the error code // Unknown Connection Identifier (0x02). LOG_INFO("peer address not found in the resolving list"); return ErrorCode::UNKNOWN_CONNECTION; } // HCI command LE_Clear_Resolving_List (Vol 4, Part E § 7.8.40). ErrorCode LinkLayerController::LeClearResolvingList() { // This command shall not be used when address resolution is enabled in the // Controller and: // • Advertising (other than periodic advertising) is enabled, // • Scanning is enabled, or // • an HCI_LE_Create_Connection, HCI_LE_Extended_Create_Connection, or // HCI_LE_Periodic_Advertising_Create_Sync command is pending. if (ResolvingListBusy()) { LOG_INFO( "device is currently advertising, scanning," " or establishing an LE connection"); return ErrorCode::COMMAND_DISALLOWED; } le_resolving_list_.clear(); return ErrorCode::SUCCESS; } // HCI command LE_Set_Address_Resolution_Enable (Vol 4, Part E § 7.8.44). ErrorCode LinkLayerController::LeSetAddressResolutionEnable(bool enable) { // This command shall not be used when: // • Advertising (other than periodic advertising) is enabled, // • Scanning is enabled, or // • an HCI_LE_Create_Connection, HCI_LE_Extended_Create_Connection, or // HCI_LE_Periodic_Advertising_Create_Sync command is pending. if (ResolvingListBusy()) { LOG_INFO( "device is currently advertising, scanning," " or establishing an LE connection"); return ErrorCode::COMMAND_DISALLOWED; } le_resolving_list_enabled_ = enable; return ErrorCode::SUCCESS; } void LinkLayerController::SetSecureSimplePairingSupport(bool enable) { uint64_t bit = 0x1; secure_simple_pairing_host_support_ = enable; Loading Loading @@ -1596,10 +1741,10 @@ void LinkLayerController::IncomingLeLegacyAdvertisingPdu( for (const auto& entry : le_resolving_list_) { if (rpa_matches_irk(advertising_address, entry.peer_irk)) { LOG_INFO("Matched against IRK for %s", entry.address.ToString().c_str()); entry.peer_identity_address.ToString().c_str()); resolved = true; resolved_address = entry.address; resolved_address_type = entry.address_type; resolved_address = entry.peer_identity_address; resolved_address_type = entry.peer_identity_address_type; rpa = generate_rpa(entry.local_irk); } } Loading Loading @@ -3418,8 +3563,9 @@ ErrorCode LinkLayerController::SetLeExtendedAdvertisingParameters( own_address_type == bluetooth::hci::OwnAddressType::RESOLVABLE_OR_RANDOM_ADDRESS) { for (const auto& entry : le_resolving_list_) { if (entry.address == peer_address.GetAddress() && entry.address_type == peer_address.GetAddressType()) { if (entry.peer_identity_address == peer_address.GetAddress() && entry.peer_identity_address_type == peer_address.GetAddressType()) { return generate_rpa(entry.local_irk); } } Loading Loading @@ -3540,24 +3686,6 @@ ErrorCode LinkLayerController::LeFilterAcceptListClear() { return ErrorCode::SUCCESS; } ErrorCode LinkLayerController::LeSetAddressResolutionEnable(bool enable) { if (ResolvingListBusy()) { return ErrorCode::COMMAND_DISALLOWED; } le_resolving_list_enabled_ = enable; return ErrorCode::SUCCESS; } ErrorCode LinkLayerController::LeResolvingListClear() { if (ResolvingListBusy()) { return ErrorCode::COMMAND_DISALLOWED; } le_resolving_list_.clear(); return ErrorCode::SUCCESS; } ErrorCode LinkLayerController::LeFilterAcceptListAddDevice( Address addr, AddressType addr_type) { if (FilterAcceptListBusy()) { Loading @@ -3575,20 +3703,6 @@ ErrorCode LinkLayerController::LeFilterAcceptListAddDevice( return ErrorCode::SUCCESS; } ErrorCode LinkLayerController::LeResolvingListAddDevice( Address addr, AddressType addr_type, std::array<uint8_t, kIrkSize> peerIrk, std::array<uint8_t, kIrkSize> localIrk) { if (ResolvingListBusy()) { return ErrorCode::COMMAND_DISALLOWED; } if (LeResolvingListFull()) { return ErrorCode::MEMORY_CAPACITY_EXCEEDED; } le_resolving_list_.emplace_back( ResolvingListEntry{addr, addr_type, peerIrk, localIrk}); return ErrorCode::SUCCESS; } bool LinkLayerController::HasAclConnection() { return (connections_.GetAclHandles().size() > 0); } Loading Loading @@ -3949,20 +4063,6 @@ ErrorCode LinkLayerController::LeFilterAcceptListRemoveDevice( return ErrorCode::SUCCESS; } ErrorCode LinkLayerController::LeResolvingListRemoveDevice( Address addr, AddressType addr_type) { if (ResolvingListBusy()) { return ErrorCode::COMMAND_DISALLOWED; } for (size_t i = 0; i < le_resolving_list_.size(); i++) { auto curr = le_resolving_list_[i]; if (curr.address == addr && curr.address_type == addr_type) { le_resolving_list_.erase(le_resolving_list_.begin() + i); } } return ErrorCode::SUCCESS; } bool LinkLayerController::LeFilterAcceptListContainsDevice( Address addr, AddressType addr_type) { for (size_t i = 0; i < le_connect_list_.size(); i++) { Loading @@ -3974,25 +4074,10 @@ bool LinkLayerController::LeFilterAcceptListContainsDevice( return false; } bool LinkLayerController::LeResolvingListContainsDevice(Address addr, AddressType addr_type) { for (size_t i = 0; i < le_connect_list_.size(); i++) { auto curr = le_connect_list_[i]; if (curr.address == addr && curr.address_type == addr_type) { return true; } } return false; } bool LinkLayerController::LeFilterAcceptListFull() { return le_connect_list_.size() >= properties_.le_filter_accept_list_size; } bool LinkLayerController::LeResolvingListFull() { return le_resolving_list_.size() >= properties_.le_resolving_list_size; } void LinkLayerController::Reset() { connections_ = AclConnectionHandler(); le_connect_list_.clear(); Loading
tools/rootcanal/model/controller/link_layer_controller.h +37 −16 Original line number Diff line number Diff line Loading @@ -48,12 +48,6 @@ class LinkLayerController { public: static constexpr size_t kIrkSize = 16; // HCI LE Set Random Address command (Vol 4, Part E § 7.8.4). ErrorCode LeSetRandomAddress(Address random_address); // HCI LE Set Host Feature command (Vol 4, Part E § 7.8.115). ErrorCode LeSetHostFeature(uint8_t bit_number, uint8_t bit_value); LinkLayerController(const Address& address, const ControllerProperties& properties); Loading Loading @@ -218,15 +212,13 @@ class LinkLayerController { ErrorCode LeFilterAcceptListRemoveDevice(Address addr, AddressType addr_type); bool LeFilterAcceptListContainsDevice(Address addr, AddressType addr_type); bool LeFilterAcceptListFull(); bool ResolvingListBusy(); ErrorCode LeSetAddressResolutionEnable(bool enable); ErrorCode LeResolvingListClear(); ErrorCode LeResolvingListAddDevice(Address addr, AddressType addr_type, std::array<uint8_t, kIrkSize> peerIrk, std::array<uint8_t, kIrkSize> localIrk); ErrorCode LeResolvingListRemoveDevice(Address addr, AddressType addr_type); bool LeResolvingListContainsDevice(Address addr, AddressType addr_type); bool LeResolvingListFull(); bool LeResolvingListContainsDevice(AddressType peer_identity_address_type, Address peer_identity_address); bool LeResolvingListContainsDevice( bluetooth::hci::PeerAddressType peer_identity_address_type, Address peer_identity_address); void LeSetPrivacyMode(AddressType address_type, Address addr, uint8_t mode); void LeReadIsoTxSync(uint16_t handle); Loading Loading @@ -401,6 +393,32 @@ class LinkLayerController { void HandleIso(bluetooth::hci::IsoView iso); // LE Commands // HCI LE Set Random Address command (Vol 4, Part E § 7.8.4). ErrorCode LeSetRandomAddress(Address random_address); // HCI LE Set Host Feature command (Vol 4, Part E § 7.8.115). ErrorCode LeSetHostFeature(uint8_t bit_number, uint8_t bit_value); // LE Address Resolving // HCI command LE_Add_Device_To_Resolving_List (Vol 4, Part E § 7.8.38). ErrorCode LeAddDeviceToResolvingList(AddressType peer_identity_address_type, Address peer_address, std::array<uint8_t, kIrkSize> peer_irk, std::array<uint8_t, kIrkSize> local_irk); // HCI command LE_Remove_Device_From_Resolving_List (Vol 4, Part E § 7.8.39). ErrorCode LeRemoveDeviceFromResolvingList( AddressType peer_identity_address_type, Address peer_identity_address); // HCI command LE_Clear_Resolving_List (Vol 4, Part E § 7.8.40). ErrorCode LeClearResolvingList(); // HCI command LE_Set_Address_Resolution_Enable (Vol 4, Part E § 7.8.44). ErrorCode LeSetAddressResolutionEnable(bool enable); protected: void SendLeLinkLayerPacketWithRssi( Address source, Address dest, uint8_t rssi, Loading Loading @@ -761,12 +779,14 @@ class LinkLayerController { AddressType address_type; }; std::vector<ConnectListEntry> le_connect_list_; struct ResolvingListEntry { Address address; AddressType address_type; AddressType peer_identity_address_type; Address peer_identity_address; std::array<uint8_t, kIrkSize> peer_irk; std::array<uint8_t, kIrkSize> local_irk; }; std::vector<ResolvingListEntry> le_resolving_list_; bool le_resolving_list_enabled_{false}; Loading Loading @@ -803,6 +823,7 @@ class LinkLayerController { #else SecurityManager security_manager_{10}; #endif /* ROOTCANAL_LMP */ std::chrono::steady_clock::time_point last_inquiry_; model::packets::InquiryType inquiry_mode_{ model::packets::InquiryType::STANDARD}; Loading
tools/rootcanal/test/controller/le/le_add_device_to_resolving_list_test.cc 0 → 100644 +128 −0 Original line number Diff line number Diff line /* * Copyright 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <gtest/gtest.h> #include "model/controller/link_layer_controller.h" namespace rootcanal { using namespace bluetooth::hci; class LeAddDeviceToResolvingListTest : public ::testing::Test { public: LeAddDeviceToResolvingListTest() { // Reduce the size of the resolving list to simplify testing. properties_.le_resolving_list_size = 2; } ~LeAddDeviceToResolvingListTest() override = default; protected: Address address_{0}; ControllerProperties properties_{}; LinkLayerController controller_{address_, properties_}; }; TEST_F(LeAddDeviceToResolvingListTest, Success) { ASSERT_EQ(controller_.LeAddDeviceToResolvingList( AddressType::PUBLIC_DEVICE_ADDRESS, Address{1}, std::array<uint8_t, 16>{1}, std::array<uint8_t, 16>{1}), ErrorCode::SUCCESS); ASSERT_EQ(controller_.LeAddDeviceToResolvingList( AddressType::RANDOM_DEVICE_ADDRESS, Address{1}, std::array<uint8_t, 16>{2}, std::array<uint8_t, 16>{2}), ErrorCode::SUCCESS); } TEST_F(LeAddDeviceToResolvingListTest, ListFull) { ASSERT_EQ(controller_.LeAddDeviceToResolvingList( AddressType::PUBLIC_DEVICE_ADDRESS, Address{1}, std::array<uint8_t, 16>{1}, std::array<uint8_t, 16>{1}), ErrorCode::SUCCESS); ASSERT_EQ(controller_.LeAddDeviceToResolvingList( AddressType::PUBLIC_DEVICE_ADDRESS, Address{2}, std::array<uint8_t, 16>{2}, std::array<uint8_t, 16>{2}), ErrorCode::SUCCESS); ASSERT_EQ(controller_.LeAddDeviceToResolvingList( AddressType::PUBLIC_DEVICE_ADDRESS, Address{3}, std::array<uint8_t, 16>{3}, std::array<uint8_t, 16>{3}), ErrorCode::MEMORY_CAPACITY_EXCEEDED); } TEST_F(LeAddDeviceToResolvingListTest, ScanningActive) { ASSERT_EQ(controller_.LeSetAddressResolutionEnable(true), ErrorCode::SUCCESS); controller_.SetLeScanEnable(OpCode::LE_SET_SCAN_ENABLE); ASSERT_EQ(controller_.LeAddDeviceToResolvingList( AddressType::PUBLIC_DEVICE_ADDRESS, Address{1}, std::array<uint8_t, 16>{1}, std::array<uint8_t, 16>{1}), ErrorCode::COMMAND_DISALLOWED); } TEST_F(LeAddDeviceToResolvingListTest, LegacyAdvertisingActive) { ASSERT_EQ(controller_.LeSetAddressResolutionEnable(true), ErrorCode::SUCCESS); ASSERT_EQ(controller_.SetLeAdvertisingEnable(1), ErrorCode::SUCCESS); ASSERT_EQ(controller_.LeAddDeviceToResolvingList( AddressType::PUBLIC_DEVICE_ADDRESS, Address{1}, std::array<uint8_t, 16>{1}, std::array<uint8_t, 16>{1}), ErrorCode::COMMAND_DISALLOWED); } TEST_F(LeAddDeviceToResolvingListTest, ExtendedAdvertisingActive) { EnabledSet enabled_set; enabled_set.advertising_handle_ = 1; enabled_set.duration_ = 0; ASSERT_EQ(controller_.LeSetAddressResolutionEnable(true), ErrorCode::SUCCESS); ASSERT_EQ(controller_.SetLeExtendedAdvertisingEnable(Enable::ENABLED, {enabled_set}), ErrorCode::SUCCESS); ASSERT_EQ(controller_.LeAddDeviceToResolvingList( AddressType::PUBLIC_DEVICE_ADDRESS, Address{1}, std::array<uint8_t, 16>{1}, std::array<uint8_t, 16>{1}), ErrorCode::COMMAND_DISALLOWED); } TEST_F(LeAddDeviceToResolvingListTest, PeerAddressDuplicate) { ASSERT_EQ(controller_.LeAddDeviceToResolvingList( AddressType::PUBLIC_DEVICE_ADDRESS, Address{1}, std::array<uint8_t, 16>{1}, std::array<uint8_t, 16>{1}), ErrorCode::SUCCESS); ASSERT_EQ(controller_.LeAddDeviceToResolvingList( AddressType::PUBLIC_DEVICE_ADDRESS, Address{1}, std::array<uint8_t, 16>{2}, std::array<uint8_t, 16>{2}), ErrorCode::INVALID_HCI_COMMAND_PARAMETERS); } TEST_F(LeAddDeviceToResolvingListTest, PeerIrkDuplicate) { ASSERT_EQ(controller_.LeAddDeviceToResolvingList( AddressType::PUBLIC_DEVICE_ADDRESS, Address{1}, std::array<uint8_t, 16>{1}, std::array<uint8_t, 16>{1}), ErrorCode::SUCCESS); ASSERT_EQ(controller_.LeAddDeviceToResolvingList( AddressType::RANDOM_DEVICE_ADDRESS, Address{1}, std::array<uint8_t, 16>{1}, std::array<uint8_t, 16>{1}), ErrorCode::INVALID_HCI_COMMAND_PARAMETERS); } } // namespace rootcanal