diff options
| author | 2024-09-19 18:54:56 +0200 | |
|---|---|---|
| committer | 2024-09-19 21:45:05 +0000 | |
| commit | 3aafc82a94ad9e6e7a74fe6b3f047be4aa1a03bb (patch) | |
| tree | 409e2781559d95d9b12cda84f0bd30b4cd36fd74 | |
| parent | c0734ca3619e3235f32d1c92c3f6fc07ff62a924 (diff) | |
poof!
Preparation for potential connection manager refactor. It's thightly tied to unused l2cap, which is tied to unused SMP implementation. Get rid of all this dead code to speed up development.
Bug: None
Change-Id: Ib32fa50d1741c33d8e9ade03662905ad8b555cf8
216 files changed, 0 insertions, 29608 deletions
diff --git a/system/gd/Android.bp b/system/gd/Android.bp index 4623d0d5fe..c5dc79e6c0 100644 --- a/system/gd/Android.bp +++ b/system/gd/Android.bp @@ -143,12 +143,10 @@ cc_defaults { ":BluetoothDumpsysSources", ":BluetoothHalSources", ":BluetoothHciSources", - ":BluetoothL2capSources", ":BluetoothMetricsSources", ":BluetoothNeighborSources", ":BluetoothOsSources", ":BluetoothPacketSources", - ":BluetoothSecuritySources", ":BluetoothStorageSources", "module.cc", "module_dumper.cc", @@ -298,7 +296,6 @@ cc_binary { srcs: [ ":BluetoothFacade_hci_hal", ":BluetoothFacade_hci_layer", - ":BluetoothFacade_l2cap_layer", ":BluetoothFacade_neighbor", ":TestMockMainShimStack", "facade/facade_main.cc", @@ -476,11 +473,9 @@ cc_test { ":BluetoothCryptoToolboxTestSources", ":BluetoothHalTestSources", ":BluetoothHciUnitTestSources", - ":BluetoothL2capUnitTestSources", ":BluetoothMetricsTestSources", ":BluetoothOsTestSources", ":BluetoothPacketTestSources", - ":BluetoothSecurityUnitTestSources", ":BluetoothStorageUnitTestSources", "module_unittest.cc", "stack_manager_unittest.cc", @@ -699,7 +694,6 @@ cc_fuzz { defaults: ["gd_fuzz_defaults"], srcs: [ ":BluetoothHciFuzzTestSources", - ":BluetoothL2capFuzzTestSources", "fuzz_test.cc", ], fuzz_config: { @@ -767,7 +761,6 @@ genrule { "dumpsys_data.fbs", "hci/hci_acl_manager.fbs", "hci/hci_controller.fbs", - "l2cap/classic/l2cap_classic_module.fbs", "module_unittest.fbs", "os/wakelock_manager.fbs", "shim/dumpsys.fbs", @@ -778,7 +771,6 @@ genrule { "hci_acl_manager.bfbs", "hci_controller.bfbs", "init_flags.bfbs", - "l2cap_classic_module.bfbs", "wakelock_manager.bfbs", ], } @@ -794,7 +786,6 @@ genrule { "dumpsys_data.fbs", "hci/hci_acl_manager.fbs", "hci/hci_controller.fbs", - "l2cap/classic/l2cap_classic_module.fbs", "module_unittest.fbs", "os/wakelock_manager.fbs", "shim/dumpsys.fbs", @@ -805,7 +796,6 @@ genrule { "hci_acl_manager_generated.h", "hci_controller_generated.h", "init_flags_generated.h", - "l2cap_classic_module_generated.h", "wakelock_manager_generated.h", ], } diff --git a/system/gd/BUILD.gn b/system/gd/BUILD.gn index 7f8c0b5d28..23efaf2654 100644 --- a/system/gd/BUILD.gn +++ b/system/gd/BUILD.gn @@ -83,10 +83,8 @@ static_library("libbluetooth_gd") { "//bt/system/gd/hal:BluetoothHalSources", "//bt/system/gd/hal:BluetoothHalSources_hci_host", "//bt/system/gd/hal:BluetoothHalSources_ranging_host", - "//bt/system/gd/l2cap:BluetoothL2capSources", "//bt/system/gd/metrics:BluetoothMetricsSources", "//bt/system/gd/neighbor:BluetoothNeighborSources", - "//bt/system/gd/security:BluetoothSecuritySources", "//bt/system/gd/shim:BluetoothShimSources", "//bt/system/gd/storage:BluetoothStorageSources", "//bt/system/gd/sysprops:BluetoothSyspropsSources", @@ -100,7 +98,6 @@ flatbuffer("BluetoothGeneratedDumpsysDataSchema_h") { "dumpsys_data.fbs", "hci/hci_acl_manager.fbs", "hci/hci_controller.fbs", - "l2cap/classic/l2cap_classic_module.fbs", "os/wakelock_manager.fbs", "shim/dumpsys.fbs", ] @@ -112,7 +109,6 @@ bt_flatc_binary_schema("BluetoothGeneratedDumpsysBinarySchema_bfbs") { "dumpsys_data.fbs", "hci/hci_acl_manager.fbs", "hci/hci_controller.fbs", - "l2cap/classic/l2cap_classic_module.fbs", "os/wakelock_manager.fbs", "shim/dumpsys.fbs", ] diff --git a/system/gd/dumpsys_data.fbs b/system/gd/dumpsys_data.fbs index e2e4454f3e..f19b53593c 100644 --- a/system/gd/dumpsys_data.fbs +++ b/system/gd/dumpsys_data.fbs @@ -12,7 +12,6 @@ include "common/init_flags.fbs"; include "hci/hci_acl_manager.fbs"; include "hci/hci_controller.fbs"; -include "l2cap/classic/l2cap_classic_module.fbs"; include "module_unittest.fbs"; include "os/wakelock_manager.fbs"; include "shim/dumpsys.fbs"; @@ -26,7 +25,6 @@ table DumpsysData { init_flags:common.InitFlagsData (privacy:"Any"); wakelock_manager_data:bluetooth.os.WakelockManagerData (privacy:"Any"); shim_dumpsys_data:bluetooth.shim.DumpsysModuleData (privacy:"Any"); - l2cap_classic_dumpsys_data:bluetooth.l2cap.classic.L2capClassicModuleData (privacy:"Any"); hci_acl_manager_dumpsys_data:bluetooth.hci.AclManagerData (privacy:"Any"); hci_controller_dumpsys_data:bluetooth.hci.ControllerData (privacy:"Any"); module_unittest_data:bluetooth.ModuleUnitTestData; // private diff --git a/system/gd/facade/grpc_root_server.cc b/system/gd/facade/grpc_root_server.cc index 07d067a1de..886e6d9b30 100644 --- a/system/gd/facade/grpc_root_server.cc +++ b/system/gd/facade/grpc_root_server.cc @@ -29,8 +29,6 @@ #include "hci/facade/le_advertising_manager_facade.h" #include "hci/facade/le_initiator_address_facade.h" #include "hci/facade/le_scanning_manager_facade.h" -#include "l2cap/classic/facade.h" -#include "l2cap/le/facade.h" #include "neighbor/facade/facade.h" #include "os/log.h" #include "os/thread.h" @@ -77,26 +75,6 @@ public: modules.add<::bluetooth::hci::facade::LeScanningManagerFacadeModule>(); modules.add<::bluetooth::neighbor::facade::NeighborFacadeModule>(); break; - case BluetoothModule::L2CAP: - modules.add<::bluetooth::hci::facade::ControllerFacadeModule>(); - modules.add<::bluetooth::hci::facade::LeAdvertisingManagerFacadeModule>(); - modules.add<::bluetooth::hci::facade::LeInitiatorAddressFacadeModule>(); - modules.add<::bluetooth::neighbor::facade::NeighborFacadeModule>(); - modules.add<::bluetooth::facade::ReadOnlyPropertyServerModule>(); - modules.add<::bluetooth::l2cap::classic::L2capClassicModuleFacadeModule>(); - modules.add<::bluetooth::l2cap::le::L2capLeModuleFacadeModule>(); - modules.add<::bluetooth::hci::facade::HciFacadeModule>(); - break; - case BluetoothModule::SECURITY: - modules.add<::bluetooth::facade::ReadOnlyPropertyServerModule>(); - modules.add<::bluetooth::hci::facade::ControllerFacadeModule>(); - modules.add<::bluetooth::neighbor::facade::NeighborFacadeModule>(); - modules.add<::bluetooth::l2cap::classic::L2capClassicModuleFacadeModule>(); - modules.add<::bluetooth::hci::facade::HciFacadeModule>(); - modules.add<::bluetooth::hci::facade::ControllerFacadeModule>(); - modules.add<::bluetooth::hci::facade::LeAdvertisingManagerFacadeModule>(); - modules.add<::bluetooth::hci::facade::LeScanningManagerFacadeModule>(); - break; default: return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "invalid module under test"); } diff --git a/system/gd/fuzz_test.cc b/system/gd/fuzz_test.cc index c9358b069b..bdb007b295 100644 --- a/system/gd/fuzz_test.cc +++ b/system/gd/fuzz_test.cc @@ -17,13 +17,9 @@ #include <stddef.h> #include <stdint.h> -void RunL2capClassicDynamicChannelAllocatorFuzzTest(const uint8_t* data, size_t size); -void RunL2capPacketFuzzTest(const uint8_t* data, size_t size); void RunHciPacketFuzzTest(const uint8_t* data, size_t size); extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - RunL2capClassicDynamicChannelAllocatorFuzzTest(data, size); - RunL2capPacketFuzzTest(data, size); RunHciPacketFuzzTest(data, size); return 0; } diff --git a/system/gd/l2cap/Android.bp b/system/gd/l2cap/Android.bp deleted file mode 100644 index 500f60395f..0000000000 --- a/system/gd/l2cap/Android.bp +++ /dev/null @@ -1,100 +0,0 @@ -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "system_bt_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["system_bt_license"], -} - -filegroup { - name: "BluetoothL2capSources", - srcs: [ - "classic/dynamic_channel_manager.cc", - "classic/dynamic_channel_service.cc", - "classic/fixed_channel.cc", - "classic/fixed_channel_manager.cc", - "classic/fixed_channel_service.cc", - "classic/internal/dumpsys_helper.cc", - "classic/internal/dynamic_channel_service_manager_impl.cc", - "classic/internal/fixed_channel_impl.cc", - "classic/internal/fixed_channel_service_manager_impl.cc", - "classic/internal/link.cc", - "classic/internal/link_manager.cc", - "classic/internal/signalling_manager.cc", - "classic/l2cap_classic_module.cc", - "dynamic_channel.cc", - "fcs.cc", - "internal/basic_mode_channel_data_controller.cc", - "internal/data_pipeline_manager.cc", - "internal/dynamic_channel_allocator.cc", - "internal/dynamic_channel_impl.cc", - "internal/enhanced_retransmission_mode_channel_data_controller.cc", - "internal/le_credit_based_channel_data_controller.cc", - "internal/receiver.cc", - "internal/scheduler_fifo.cc", - "internal/sender.cc", - "le/dynamic_channel.cc", - "le/dynamic_channel_manager.cc", - "le/dynamic_channel_service.cc", - "le/fixed_channel.cc", - "le/fixed_channel_manager.cc", - "le/fixed_channel_service.cc", - "le/internal/dynamic_channel_service_manager_impl.cc", - "le/internal/fixed_channel_impl.cc", - "le/internal/fixed_channel_service_manager_impl.cc", - "le/internal/link.cc", - "le/internal/link_manager.cc", - "le/internal/signalling_manager.cc", - "le/l2cap_le_module.cc", - "le/link_options.cc", - ], -} - -filegroup { - name: "BluetoothL2capTestSources", - srcs: [ - "classic/internal/dynamic_channel_service_manager_test.cc", - "classic/internal/fixed_channel_impl_test.cc", - "classic/internal/fixed_channel_service_manager_test.cc", - "classic/internal/link_manager_test.cc", - "classic/internal/link_test.cc", - "classic/internal/signalling_manager_test.cc", - "internal/basic_mode_channel_data_controller_test.cc", - "internal/dynamic_channel_allocator_test.cc", - "internal/dynamic_channel_impl_test.cc", - "internal/enhanced_retransmission_mode_channel_data_controller_test.cc", - "internal/fixed_channel_allocator_test.cc", - "internal/le_credit_based_channel_data_controller_test.cc", - "internal/scheduler_fifo_test.cc", - "internal/sender_test.cc", - "le/internal/dynamic_channel_service_manager_test.cc", - "le/internal/fixed_channel_impl_test.cc", - "le/internal/fixed_channel_service_manager_test.cc", - "le/internal/link_manager_test.cc", - ], -} - -filegroup { - name: "BluetoothL2capUnitTestSources", - srcs: [ - "l2cap_packet_test.cc", - "signal_id_test.cc", - ], -} - -filegroup { - name: "BluetoothFacade_l2cap_layer", - srcs: [ - "classic/facade.cc", - "le/facade.cc", - ], -} - -filegroup { - name: "BluetoothL2capFuzzTestSources", - srcs: [ - "internal/dynamic_channel_allocator_fuzz_test.cc", - "l2cap_packet_fuzz_test.cc", - ], -} diff --git a/system/gd/l2cap/BUILD.gn b/system/gd/l2cap/BUILD.gn deleted file mode 100644 index 5eccbc5864..0000000000 --- a/system/gd/l2cap/BUILD.gn +++ /dev/null @@ -1,60 +0,0 @@ -# -# Copyright 2021 Google, Inc. -# -# 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. - -source_set("BluetoothL2capSources") { - sources = [ - "classic/dynamic_channel_manager.cc", - "classic/dynamic_channel_service.cc", - "classic/fixed_channel.cc", - "classic/fixed_channel_manager.cc", - "classic/fixed_channel_service.cc", - "classic/internal/dumpsys_helper.cc", - "classic/internal/dynamic_channel_service_manager_impl.cc", - "classic/internal/fixed_channel_impl.cc", - "classic/internal/fixed_channel_service_manager_impl.cc", - "classic/internal/link.cc", - "classic/internal/link_manager.cc", - "classic/internal/signalling_manager.cc", - "classic/l2cap_classic_module.cc", - "dynamic_channel.cc", - "fcs.cc", - "internal/basic_mode_channel_data_controller.cc", - "internal/data_pipeline_manager.cc", - "internal/dynamic_channel_allocator.cc", - "internal/dynamic_channel_impl.cc", - "internal/enhanced_retransmission_mode_channel_data_controller.cc", - "internal/le_credit_based_channel_data_controller.cc", - "internal/receiver.cc", - "internal/scheduler_fifo.cc", - "internal/sender.cc", - "le/dynamic_channel.cc", - "le/dynamic_channel_manager.cc", - "le/dynamic_channel_service.cc", - "le/fixed_channel.cc", - "le/fixed_channel_manager.cc", - "le/fixed_channel_service.cc", - "le/internal/dynamic_channel_service_manager_impl.cc", - "le/internal/fixed_channel_impl.cc", - "le/internal/fixed_channel_service_manager_impl.cc", - "le/internal/link.cc", - "le/internal/link_manager.cc", - "le/internal/signalling_manager.cc", - "le/l2cap_le_module.cc", - "le/link_options.cc", - ] - - configs += [ "//bt/system/gd:gd_defaults" ] - deps = [ "//bt/system/gd:gd_default_deps" ] -} diff --git a/system/gd/l2cap/cid.h b/system/gd/l2cap/cid.h deleted file mode 100644 index 9a21abb034..0000000000 --- a/system/gd/l2cap/cid.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <cstdint> - -namespace bluetooth { -namespace l2cap { - -using Cid = uint16_t; - -constexpr Cid kInvalidCid = 0; -constexpr Cid kFirstFixedChannel = 1; -constexpr Cid kLastFixedChannel = 63; -constexpr Cid kFirstDynamicChannel = kLastFixedChannel + 1; -constexpr Cid kLastDynamicChannel = (uint16_t)(0xffff); - -constexpr Cid kClassicSignallingCid = 1; -constexpr Cid kConnectionlessCid = 2; -constexpr Cid kLeAttributeCid = 4; -constexpr Cid kLeSignallingCid = 5; -constexpr Cid kSmpCid = 6; -constexpr Cid kSmpBrCid = 7; - -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/dynamic_channel.h b/system/gd/l2cap/classic/dynamic_channel.h deleted file mode 100644 index 0bd5a82ece..0000000000 --- a/system/gd/l2cap/classic/dynamic_channel.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include "l2cap/dynamic_channel.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { - -using DynamicChannel = l2cap::DynamicChannel; - -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/dynamic_channel_configuration_option.h b/system/gd/l2cap/classic/dynamic_channel_configuration_option.h deleted file mode 100644 index 27bfe5fed2..0000000000 --- a/system/gd/l2cap/classic/dynamic_channel_configuration_option.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include "l2cap/mtu.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { - -/** - * Configuration Option specified by L2CAP Channel user on a dynamic channel. L2CAP module will - * configure the channel based on user provided option. - */ -struct DynamicChannelConfigurationOption { - enum class RetransmissionAndFlowControlMode { - L2CAP_BASIC, - ENHANCED_RETRANSMISSION, - ENHANCED_RETRANSMISSION_OPTIONAL, - }; - /** - * Retransmission and flow control mode. Currently L2CAP_BASIC and ENHANCED_RETRANSMISSION. - * If the remote doesn't support a mode, it might fall back to basic, as this is a negotiable - * option. - */ - RetransmissionAndFlowControlMode channel_mode = RetransmissionAndFlowControlMode::L2CAP_BASIC; - - /** - * Maximum SDU size that the L2CAP Channel user is able to process. - */ - Mtu incoming_mtu = kDefaultClassicMtu; - - /** - * Minimum MTU that we enforce the remote channel to have - */ - Mtu minimal_remote_mtu = kMinimumClassicMtu; -}; - -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/dynamic_channel_manager.cc b/system/gd/l2cap/classic/dynamic_channel_manager.cc deleted file mode 100644 index 005074c7ef..0000000000 --- a/system/gd/l2cap/classic/dynamic_channel_manager.cc +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/classic/dynamic_channel_manager.h" - -#include "l2cap/classic/internal/dynamic_channel_service_impl.h" -#include "l2cap/classic/internal/dynamic_channel_service_manager_impl.h" -#include "l2cap/classic/internal/link.h" -#include "l2cap/classic/internal/link_manager.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { - -void DynamicChannelManager::ConnectChannel(hci::Address device, - DynamicChannelConfigurationOption configuration_option, - Psm psm, OnConnectionOpenCallback on_connection_open, - OnConnectionFailureCallback on_fail_callback) { - internal::Link::PendingDynamicChannelConnection pending_connection{ - .on_open_callback_ = std::move(on_connection_open), - .on_fail_callback_ = std::move(on_fail_callback), - .configuration_ = configuration_option, - }; - l2cap_layer_handler_->CallOn(link_manager_, &internal::LinkManager::ConnectDynamicChannelServices, - device, std::move(pending_connection), psm); -} - -void DynamicChannelManager::RegisterService(Psm psm, - DynamicChannelConfigurationOption configuration_option, - const classic::SecurityPolicy& security_policy, - OnRegistrationCompleteCallback on_registration_complete, - OnConnectionOpenCallback on_connection_open) { - internal::DynamicChannelServiceImpl::PendingRegistration pending_registration{ - .security_policy_ = security_policy, - .on_registration_complete_callback_ = std::move(on_registration_complete), - .on_connection_open_callback_ = std::move(on_connection_open), - .configuration_ = configuration_option, - }; - l2cap_layer_handler_->CallOn(service_manager_, - &internal::DynamicChannelServiceManagerImpl::Register, psm, - std::move(pending_registration)); -} - -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/dynamic_channel_manager.h b/system/gd/l2cap/classic/dynamic_channel_manager.h deleted file mode 100644 index a5cf983457..0000000000 --- a/system/gd/l2cap/classic/dynamic_channel_manager.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright 2019 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. - */ -#pragma once - -#include <string> - -#include "common/contextual_callback.h" -#include "hci/acl_manager.h" -#include "hci/address.h" -#include "l2cap/classic/dynamic_channel.h" -#include "l2cap/classic/dynamic_channel_configuration_option.h" -#include "l2cap/classic/dynamic_channel_service.h" -#include "l2cap/classic/security_policy.h" -#include "l2cap/l2cap_packets.h" -#include "l2cap/psm.h" -#include "os/handler.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { - -class L2capClassicModule; - -namespace internal { -class LinkManager; -class DynamicChannelServiceManagerImpl; -} // namespace internal - -class DynamicChannelManager { -public: - enum class ConnectionResultCode { - SUCCESS = 0, - FAIL_NO_SERVICE_REGISTERED = 1, // No service is registered - FAIL_HCI_ERROR = 2, // See hci_error - FAIL_L2CAP_ERROR = 3, // See l2cap_connection_response_result - FAIL_REMOTE_NOT_SUPPORT = 4, // Remote not support required retansmission and flow control mode - FAIL_SECURITY_BLOCK = 5, // Cannot enhance required security level - }; - - struct ConnectionResult { - ConnectionResultCode connection_result_code = ConnectionResultCode::SUCCESS; - hci::ErrorCode hci_error = hci::ErrorCode::SUCCESS; - ConnectionResponseResult l2cap_connection_response_result = ConnectionResponseResult::SUCCESS; - }; - - using OnConnectionFailureCallback = common::ContextualOnceCallback<void(ConnectionResult result)>; - - using OnConnectionOpenCallback = - common::ContextualCallback<void(std::unique_ptr<DynamicChannel>)>; - - enum class RegistrationResult { - SUCCESS = 0, - FAIL_DUPLICATE_SERVICE = 1, // Duplicate service registration for the same PSM - FAIL_INVALID_SERVICE = 2, // Invalid PSM - }; - - using OnRegistrationCompleteCallback = common::ContextualOnceCallback<void( - RegistrationResult, std::unique_ptr<DynamicChannelService>)>; - - /** - * Connect to a Dynamic channel on a remote device - * - * - This method is asynchronous - * - When false is returned, the connection fails immediately - * - When true is returned, method caller should wait for on_fail_callback or on_open_callback - * - If an ACL connection does not exist, this method will create an ACL connection - * - If HCI connection failed, on_fail_callback will be triggered with FAIL_HCI_ERROR - * - If Dynamic channel on a remote device is already reported as connected via on_open_callback, - * it won't be reported again - * - * @param device: Remote device to make this connection. - * @param psm: Service PSM to connect. PSM is defined in Core spec Vol 3 Part A 4.2. - * @param on_open_callback: A callback to indicate success of a connection initiated from a remote - * device. - * @param on_fail_callback: A callback to indicate connection failure along with a status code. - * @param configuration_option: The configuration options for this channel - */ - virtual void ConnectChannel(hci::Address device, - DynamicChannelConfigurationOption configuration_option, Psm psm, - OnConnectionOpenCallback on_connection_open, - OnConnectionFailureCallback on_fail_callback); - - /** - * Register a service to receive incoming connections bound to a specific channel. - * - * - This method is asynchronous. - * - When false is returned, the registration fails immediately. - * - When true is returned, method caller should wait for on_service_registered callback that - * contains a DynamicChannelService object. The registered service can be managed from that - * object. - * - If a PSM is already registered or some other error happens, on_registration_complete will be - * triggered with a non-SUCCESS value - * - After a service is registered, a DynamicChannel is delivered through on_open_callback when - * the remote initiates a channel open and channel is opened successfully - * - on_open_callback, will only be triggered after on_service_registered callback - * - * @param security_policy: The security policy used for the connection. - * @param psm: Service PSM to register. PSM is defined in Core spec Vol 3 Part A 4.2. - * @param on_registration_complete: A callback to indicate the service setup has completed. If the - * return status is not SUCCESS, it means service is not registered due to reasons like PSM - * already take - * @param on_open_callback: A callback to indicate success of a connection initiated from a remote - * device. - * @param configuration_option: The configuration options for this channel - */ - virtual void RegisterService(Psm psm, DynamicChannelConfigurationOption configuration_option, - const SecurityPolicy& security_policy, - OnRegistrationCompleteCallback on_registration_complete, - OnConnectionOpenCallback on_connection_open); - - friend class L2capClassicModule; - - DynamicChannelManager(const DynamicChannelManager&) = delete; - DynamicChannelManager& operator=(const DynamicChannelManager&) = delete; - - virtual ~DynamicChannelManager() = default; - -protected: - DynamicChannelManager() = default; - -private: - // The constructor is not to be used by user code - DynamicChannelManager(internal::DynamicChannelServiceManagerImpl* service_manager, - internal::LinkManager* link_manager, os::Handler* l2cap_layer_handler) - : service_manager_(service_manager), - link_manager_(link_manager), - l2cap_layer_handler_(l2cap_layer_handler) { - log::assert_that(service_manager_ != nullptr, "assert failed: service_manager_ != nullptr"); - log::assert_that(link_manager_ != nullptr, "assert failed: link_manager_ != nullptr"); - log::assert_that(l2cap_layer_handler_ != nullptr, - "assert failed: l2cap_layer_handler_ != nullptr"); - } - internal::DynamicChannelServiceManagerImpl* service_manager_ = nullptr; - internal::LinkManager* link_manager_ = nullptr; - os::Handler* l2cap_layer_handler_ = nullptr; -}; - -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/dynamic_channel_service.cc b/system/gd/l2cap/classic/dynamic_channel_service.cc deleted file mode 100644 index 748f6788cc..0000000000 --- a/system/gd/l2cap/classic/dynamic_channel_service.cc +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/classic/dynamic_channel_service.h" - -#include "common/bind.h" -#include "l2cap/classic/internal/dynamic_channel_service_manager_impl.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { - -void DynamicChannelService::Unregister(OnUnregisteredCallback on_unregistered) { - log::assert_that(manager_ != nullptr, "this service is invalid"); - l2cap_layer_handler_->CallOn(manager_, &internal::DynamicChannelServiceManagerImpl::Unregister, - psm_, std::move(on_unregistered)); -} - -Psm DynamicChannelService::GetPsm() const { return psm_; } - -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/dynamic_channel_service.h b/system/gd/l2cap/classic/dynamic_channel_service.h deleted file mode 100644 index 87be835304..0000000000 --- a/system/gd/l2cap/classic/dynamic_channel_service.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <bluetooth/log.h> - -#include "common/contextual_callback.h" -#include "l2cap/psm.h" -#include "os/handler.h" -#include "os/log.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { - -namespace internal { -class DynamicChannelServiceManagerImpl; -} - -class DynamicChannelService { -public: - DynamicChannelService() = default; - DynamicChannelService(const DynamicChannelService&) = delete; - DynamicChannelService& operator=(const DynamicChannelService&) = delete; - - using OnUnregisteredCallback = common::ContextualOnceCallback<void()>; - - /** - * Unregister a service from L2CAP module. This operation cannot fail. - * All channels opened for this service will be closed. - * - * @param on_unregistered will be triggered when unregistration is complete - */ - void Unregister(OnUnregisteredCallback on_unregistered); - - friend internal::DynamicChannelServiceManagerImpl; - - Psm GetPsm() const; - -protected: - DynamicChannelService(Psm psm, internal::DynamicChannelServiceManagerImpl* manager, - os::Handler* handler) - : psm_(psm), manager_(manager), l2cap_layer_handler_(handler) { - log::assert_that(IsPsmValid(psm), "assert failed: IsPsmValid(psm)"); - log::assert_that(manager_ != nullptr, "assert failed: manager_ != nullptr"); - log::assert_that(l2cap_layer_handler_ != nullptr, - "assert failed: l2cap_layer_handler_ != nullptr"); - } - -private: - Psm psm_ = kDefaultPsm; - internal::DynamicChannelServiceManagerImpl* manager_ = nullptr; - os::Handler* l2cap_layer_handler_; -}; - -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/facade.cc b/system/gd/l2cap/classic/facade.cc deleted file mode 100644 index b4c9b7916e..0000000000 --- a/system/gd/l2cap/classic/facade.cc +++ /dev/null @@ -1,468 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/classic/facade.h" - -#include <bluetooth/log.h> - -#include <condition_variable> -#include <cstdint> -#include <unordered_map> - -#include "blueberry/facade/l2cap/classic/facade.grpc.pb.h" -#include "common/bidi_queue.h" -#include "common/bind.h" -#include "common/callback.h" -#include "grpc/grpc_event_queue.h" -#include "hci/address.h" -#include "l2cap/classic/l2cap_classic_module.h" -#include "os/log.h" -#include "packet/raw_builder.h" - -using ::grpc::ServerAsyncResponseWriter; -using ::grpc::ServerAsyncWriter; -using ::grpc::ServerContext; - -using ::bluetooth::packet::RawBuilder; - -namespace bluetooth { -namespace l2cap { -namespace classic { - -using namespace blueberry::facade::l2cap::classic; - -class L2capClassicModuleFacadeService : public L2capClassicModuleFacade::Service, - public LinkSecurityInterfaceListener { -public: - L2capClassicModuleFacadeService(L2capClassicModule* l2cap_layer, os::Handler* facade_handler) - : l2cap_layer_(l2cap_layer), facade_handler_(facade_handler), security_interface_(nullptr) { - log::assert_that(l2cap_layer_ != nullptr, "assert failed: l2cap_layer_ != nullptr"); - log::assert_that(facade_handler_ != nullptr, "assert failed: facade_handler_ != nullptr"); - } - - ::grpc::Status FetchConnectionComplete( - ::grpc::ServerContext* context, const ::google::protobuf::Empty* /* request */, - ::grpc::ServerWriter<classic::ConnectionCompleteEvent>* writer) override { - return pending_connection_complete_.RunLoop(context, writer); - } - - ::grpc::Status FetchConnectionClose( - ::grpc::ServerContext* context, const ::google::protobuf::Empty* /* request */, - ::grpc::ServerWriter<classic::ConnectionCloseEvent>* writer) override { - return pending_connection_close_.RunLoop(context, writer); - } - - ::grpc::Status SendDynamicChannelPacket(::grpc::ServerContext* /* context */, - const DynamicChannelPacket* request, - ::google::protobuf::Empty* /* response */) override { - std::unique_lock<std::mutex> lock(channel_map_mutex_); - if (dynamic_channel_helper_map_.find(request->psm()) == dynamic_channel_helper_map_.end()) { - return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Psm not registered"); - } - std::vector<uint8_t> packet(request->payload().begin(), request->payload().end()); - if (!dynamic_channel_helper_map_[request->psm()]->SendPacket(packet)) { - return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Channel not open"); - } - return ::grpc::Status::OK; - } - - ::grpc::Status OpenChannel(::grpc::ServerContext* /* context */, - const ::bluetooth::l2cap::classic::OpenChannelRequest* request, - ::google::protobuf::Empty* /* response */) override { - auto service_helper = dynamic_channel_helper_map_.find(request->psm()); - if (service_helper == dynamic_channel_helper_map_.end()) { - return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Psm not registered"); - } - hci::Address peer; - log::assert_that(hci::Address::FromString(request->remote().address(), peer), - "assert failed: hci::Address::FromString(request->remote().address(), peer)"); - dynamic_channel_helper_map_[request->psm()]->Connect(peer); - return ::grpc::Status::OK; - } - - ::grpc::Status CloseChannel(::grpc::ServerContext* /* context */, - const ::bluetooth::l2cap::classic::CloseChannelRequest* request, - ::google::protobuf::Empty* /* response */) override { - auto psm = request->psm(); - if (dynamic_channel_helper_map_.find(request->psm()) == dynamic_channel_helper_map_.end()) { - return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Psm not registered"); - } - dynamic_channel_helper_map_[psm]->Disconnect(); - return ::grpc::Status::OK; - } - - ::grpc::Status FetchL2capData(::grpc::ServerContext* context, - const ::google::protobuf::Empty* /* request */, - ::grpc::ServerWriter<classic::L2capPacket>* writer) override { - auto status = pending_l2cap_data_.RunLoop(context, writer); - - return status; - } - - ::grpc::Status SetDynamicChannel(::grpc::ServerContext* /* context */, - const SetEnableDynamicChannelRequest* request, - google::protobuf::Empty* /* response */) override { - dynamic_channel_helper_map_.emplace(request->psm(), - std::make_unique<L2capDynamicChannelHelper>( - this, l2cap_layer_, facade_handler_, request->psm(), - request->retransmission_mode())); - return ::grpc::Status::OK; - } - - ::grpc::Status SetTrafficPaused(::grpc::ServerContext* /* context */, - const SetTrafficPausedRequest* request, - ::google::protobuf::Empty* /* response */) override { - auto psm = request->psm(); - if (dynamic_channel_helper_map_.find(request->psm()) == dynamic_channel_helper_map_.end()) { - return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Psm not registered"); - } - if (request->paused()) { - dynamic_channel_helper_map_[psm]->SuspendDequeue(); - } else { - dynamic_channel_helper_map_[psm]->ResumeDequeue(); - } - return ::grpc::Status::OK; - } - - ::grpc::Status GetChannelQueueDepth(::grpc::ServerContext* /* context */, - const ::google::protobuf::Empty* /* request */, - GetChannelQueueDepthResponse* response) override { - // Use the value kChannelQueueSize (5) in internal/dynamic_channel_impl.h - response->set_size(5); - return ::grpc::Status::OK; - } - - ::grpc::Status InitiateConnectionForSecurity(::grpc::ServerContext* /* context */, - const blueberry::facade::BluetoothAddress* request, - ::google::protobuf::Empty* /* response */) override { - hci::Address peer; - log::assert_that(hci::Address::FromString(request->address(), peer), - "assert failed: hci::Address::FromString(request->address(), peer)"); - outgoing_pairing_remote_devices_.insert(peer); - security_interface_->InitiateConnectionForSecurity(peer); - return ::grpc::Status::OK; - } - - void SecurityConnectionEventOccurred(hci::ErrorCode /* hci_status */, hci::Address remote, - LinkSecurityInterfaceCallbackEventType event_type) { - LinkSecurityInterfaceCallbackEvent msg; - msg.mutable_address()->set_address(remote.ToString()); - msg.set_event_type(event_type); - security_connection_events_.OnIncomingEvent(msg); - } - - ::grpc::Status FetchSecurityConnectionEvents( - ::grpc::ServerContext* context, const ::google::protobuf::Empty* /* request */, - ::grpc::ServerWriter<LinkSecurityInterfaceCallbackEvent>* writer) override { - security_interface_ = l2cap_layer_->GetSecurityInterface(facade_handler_, this); - return security_connection_events_.RunLoop(context, writer); - } - - ::grpc::Status SecurityLinkHold(::grpc::ServerContext* /* context */, - const blueberry::facade::BluetoothAddress* request, - ::google::protobuf::Empty* /* response */) override { - hci::Address peer; - log::assert_that(hci::Address::FromString(request->address(), peer), - "assert failed: hci::Address::FromString(request->address(), peer)"); - auto entry = security_link_map_.find(peer); - if (entry == security_link_map_.end()) { - log::warn("Unknown address '{}'", peer); - } else { - entry->second->Hold(); - } - return ::grpc::Status::OK; - } - - ::grpc::Status SecurityLinkEnsureAuthenticated( - ::grpc::ServerContext* /* context */, const blueberry::facade::BluetoothAddress* request, - ::google::protobuf::Empty* /* response */) override { - hci::Address peer; - log::assert_that(hci::Address::FromString(request->address(), peer), - "assert failed: hci::Address::FromString(request->address(), peer)"); - auto entry = security_link_map_.find(peer); - if (entry == security_link_map_.end()) { - log::warn("Unknown address '{}'", peer); - } else { - entry->second->EnsureAuthenticated(); - } - return ::grpc::Status::OK; - } - - ::grpc::Status SecurityLinkRelease(::grpc::ServerContext* /* context */, - const blueberry::facade::BluetoothAddress* request, - ::google::protobuf::Empty* /* response */) override { - hci::Address peer; - log::assert_that(hci::Address::FromString(request->address(), peer), - "assert failed: hci::Address::FromString(request->address(), peer)"); - outgoing_pairing_remote_devices_.erase(peer); - auto entry = security_link_map_.find(peer); - if (entry == security_link_map_.end()) { - log::warn("Unknown address '{}'", peer); - } else { - entry->second->Release(); - } - return ::grpc::Status::OK; - } - - ::grpc::Status SecurityLinkDisconnect(::grpc::ServerContext* /* context */, - const blueberry::facade::BluetoothAddress* request, - ::google::protobuf::Empty* /* response */) override { - hci::Address peer; - log::assert_that(hci::Address::FromString(request->address(), peer), - "assert failed: hci::Address::FromString(request->address(), peer)"); - outgoing_pairing_remote_devices_.erase(peer); - auto entry = security_link_map_.find(peer); - if (entry == security_link_map_.end()) { - log::warn("Unknown address '{}'", peer); - } else { - entry->second->Disconnect(); - } - return ::grpc::Status::OK; - } - - void OnLinkConnected(std::unique_ptr<LinkSecurityInterface> link) override { - auto remote = link->GetRemoteAddress(); - if (outgoing_pairing_remote_devices_.count(remote) == 1) { - link->Hold(); - link->EnsureAuthenticated(); - outgoing_pairing_remote_devices_.erase(remote); - } - security_link_map_.emplace(remote, std::move(link)); - SecurityConnectionEventOccurred(hci::ErrorCode::SUCCESS, remote, - LinkSecurityInterfaceCallbackEventType::ON_CONNECTED); - } - - void OnLinkDisconnected(hci::Address remote) override { - auto entry = security_link_map_.find(remote); - if (entry == security_link_map_.end()) { - log::warn("Unknown address '{}'", remote); - return; - } - entry->second.reset(); - security_link_map_.erase(entry); - SecurityConnectionEventOccurred(hci::ErrorCode::SUCCESS, remote, - LinkSecurityInterfaceCallbackEventType::ON_DISCONNECTED); - } - - void OnAuthenticationComplete(hci::ErrorCode hci_status, hci::Address remote) override { - auto entry = security_link_map_.find(remote); - if (entry != security_link_map_.end()) { - entry->second->EnsureEncrypted(); - return; - } - SecurityConnectionEventOccurred( - hci_status, remote, LinkSecurityInterfaceCallbackEventType::ON_AUTHENTICATION_COMPLETE); - } - - void OnEncryptionChange(hci::Address remote, bool /* encrypted */) override { - SecurityConnectionEventOccurred(hci::ErrorCode::SUCCESS, remote, - LinkSecurityInterfaceCallbackEventType::ON_ENCRYPTION_CHANGE); - } - - class L2capDynamicChannelHelper { - public: - L2capDynamicChannelHelper(L2capClassicModuleFacadeService* service, - L2capClassicModule* l2cap_layer, os::Handler* handler, Psm psm, - RetransmissionFlowControlMode mode) - : facade_service_(service), - l2cap_layer_(l2cap_layer), - handler_(handler), - psm_(psm), - mode_(mode) { - dynamic_channel_manager_ = l2cap_layer_->GetDynamicChannelManager(); - DynamicChannelConfigurationOption configuration_option = {}; - configuration_option.channel_mode = - (DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode)mode; - dynamic_channel_manager_->RegisterService( - psm, configuration_option, - SecurityPolicy::_SDP_ONLY_NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK, - handler_->BindOnceOn( - this, &L2capDynamicChannelHelper::on_l2cap_service_registration_complete), - handler_->BindOn(this, &L2capDynamicChannelHelper::on_connection_open)); - } - - ~L2capDynamicChannelHelper() { - if (dequeue_registered_) { - channel_->GetQueueUpEnd()->UnregisterDequeue(); - channel_ = nullptr; - } - enqueue_buffer_.reset(); - } - - void Connect(hci::Address address) { - DynamicChannelConfigurationOption configuration_option = - l2cap::classic::DynamicChannelConfigurationOption(); - configuration_option.channel_mode = - (DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode)mode_; - - dynamic_channel_manager_->ConnectChannel( - address, configuration_option, psm_, - handler_->BindOn(this, &L2capDynamicChannelHelper::on_connection_open), - handler_->BindOnceOn(this, &L2capDynamicChannelHelper::on_connect_fail)); - std::unique_lock<std::mutex> lock(channel_open_cv_mutex_); - if (!channel_open_cv_.wait_for(lock, std::chrono::seconds(2), - [this] { return channel_ != nullptr; })) { - log::warn("Channel is not open for psm {}", psm_); - } - } - - void Disconnect() { - if (channel_ == nullptr) { - std::unique_lock<std::mutex> lock(channel_open_cv_mutex_); - if (!channel_open_cv_.wait_for(lock, std::chrono::seconds(2), - [this] { return channel_ != nullptr; })) { - log::warn("Channel is not open for psm {}", psm_); - return; - } - } - channel_->Close(); - } - - void on_l2cap_service_registration_complete( - DynamicChannelManager::RegistrationResult /* registration_result */, - std::unique_ptr<DynamicChannelService> /* service */) {} - - // invoked from Facade Handler - void on_connection_open(std::unique_ptr<DynamicChannel> channel) { - ConnectionCompleteEvent event; - event.mutable_remote()->set_address(channel->GetDevice().GetAddress().ToString()); - facade_service_->pending_connection_complete_.OnIncomingEvent(event); - { - std::unique_lock<std::mutex> lock(channel_open_cv_mutex_); - channel_ = std::move(channel); - enqueue_buffer_ = - std::make_unique<os::EnqueueBuffer<BasePacketBuilder>>(channel_->GetQueueUpEnd()); - } - channel_open_cv_.notify_all(); - channel_->RegisterOnCloseCallback(facade_service_->facade_handler_->BindOnceOn( - this, &L2capDynamicChannelHelper::on_close_callback)); - dequeue_registered_ = true; - channel_->GetQueueUpEnd()->RegisterDequeue( - facade_service_->facade_handler_, - common::Bind(&L2capDynamicChannelHelper::on_incoming_packet, - common::Unretained(this))); - } - - void on_close_callback(hci::ErrorCode error_code) { - { - std::unique_lock<std::mutex> lock(channel_open_cv_mutex_); - if (dequeue_registered_.exchange(false)) { - channel_->GetQueueUpEnd()->UnregisterDequeue(); - } - } - classic::ConnectionCloseEvent event; - event.mutable_remote()->set_address(channel_->GetDevice().GetAddress().ToString()); - event.set_reason(static_cast<uint32_t>(error_code)); - facade_service_->pending_connection_close_.OnIncomingEvent(event); - channel_ = nullptr; - enqueue_buffer_.reset(); - } - - void SuspendDequeue() { - if (dequeue_registered_.exchange(false)) { - channel_->GetQueueUpEnd()->UnregisterDequeue(); - } - } - - void ResumeDequeue() { - if (!dequeue_registered_.exchange(true)) { - channel_->GetQueueUpEnd()->RegisterDequeue( - facade_service_->facade_handler_, - common::Bind(&L2capDynamicChannelHelper::on_incoming_packet, - common::Unretained(this))); - } - } - - void on_connect_fail(DynamicChannelManager::ConnectionResult /* result */) {} - - void on_incoming_packet() { - auto packet = channel_->GetQueueUpEnd()->TryDequeue(); - std::string data = std::string(packet->begin(), packet->end()); - L2capPacket l2cap_data; - l2cap_data.set_psm(psm_); - l2cap_data.set_payload(data); - facade_service_->pending_l2cap_data_.OnIncomingEvent(l2cap_data); - } - - bool SendPacket(std::vector<uint8_t> packet) { - if (channel_ == nullptr) { - std::unique_lock<std::mutex> lock(channel_open_cv_mutex_); - if (!channel_open_cv_.wait_for(lock, std::chrono::seconds(2), - [this] { return channel_ != nullptr; })) { - log::warn("Channel is not open"); - return false; - } - } - auto packet_one = std::make_unique<packet::RawBuilder>(2000); - packet_one->AddOctets(packet); - enqueue_buffer_->Enqueue(std::move(packet_one), handler_); - return true; - } - L2capClassicModuleFacadeService* facade_service_; - L2capClassicModule* l2cap_layer_; - os::Handler* handler_; - std::unique_ptr<DynamicChannelManager> dynamic_channel_manager_; - std::unique_ptr<DynamicChannelService> service_; - std::unique_ptr<DynamicChannel> channel_ = nullptr; - std::unique_ptr<os::EnqueueBuffer<BasePacketBuilder>> enqueue_buffer_ = nullptr; - Psm psm_; - RetransmissionFlowControlMode mode_ = RetransmissionFlowControlMode::BASIC; - std::atomic_bool dequeue_registered_ = false; - std::condition_variable channel_open_cv_; - std::mutex channel_open_cv_mutex_; - }; - - L2capClassicModule* l2cap_layer_; - ::bluetooth::os::Handler* facade_handler_; - std::mutex channel_map_mutex_; - std::map<Psm, std::unique_ptr<L2capDynamicChannelHelper>> dynamic_channel_helper_map_; - ::bluetooth::grpc::GrpcEventQueue<classic::ConnectionCompleteEvent> pending_connection_complete_{ - "FetchConnectionComplete"}; - ::bluetooth::grpc::GrpcEventQueue<classic::ConnectionCloseEvent> pending_connection_close_{ - "FetchConnectionClose"}; - ::bluetooth::grpc::GrpcEventQueue<L2capPacket> pending_l2cap_data_{"FetchL2capData"}; - ::bluetooth::grpc::GrpcEventQueue<LinkSecurityInterfaceCallbackEvent> security_connection_events_{ - "Security Connection Events"}; - SecurityInterface* security_interface_; - std::unordered_map<hci::Address, std::unique_ptr<l2cap::classic::LinkSecurityInterface>> - security_link_map_; - std::set<hci::Address> outgoing_pairing_remote_devices_; -}; - -void L2capClassicModuleFacadeModule::ListDependencies(ModuleList* list) const { - ::bluetooth::grpc::GrpcFacadeModule::ListDependencies(list); - list->add<l2cap::classic::L2capClassicModule>(); -} - -void L2capClassicModuleFacadeModule::Start() { - ::bluetooth::grpc::GrpcFacadeModule::Start(); - service_ = new L2capClassicModuleFacadeService( - GetDependency<l2cap::classic::L2capClassicModule>(), GetHandler()); -} - -void L2capClassicModuleFacadeModule::Stop() { - delete service_; - ::bluetooth::grpc::GrpcFacadeModule::Stop(); -} - -::grpc::Service* L2capClassicModuleFacadeModule::GetService() const { return service_; } - -const ModuleFactory L2capClassicModuleFacadeModule::Factory = - ::bluetooth::ModuleFactory([]() { return new L2capClassicModuleFacadeModule(); }); - -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/facade.h b/system/gd/l2cap/classic/facade.h deleted file mode 100644 index 9d4a6c8aff..0000000000 --- a/system/gd/l2cap/classic/facade.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2019 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. - */ -#pragma once - -#include <grpc++/grpc++.h> - -#include "grpc/grpc_module.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { - -class L2capClassicModuleFacadeService; - -class L2capClassicModuleFacadeModule : public ::bluetooth::grpc::GrpcFacadeModule { -public: - static const ModuleFactory Factory; - - void ListDependencies(ModuleList* list) const override; - void Start() override; - void Stop() override; - - ::grpc::Service* GetService() const override; - -private: - L2capClassicModuleFacadeService* service_; -}; - -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/fixed_channel.cc b/system/gd/l2cap/classic/fixed_channel.cc deleted file mode 100644 index 20a117d3d6..0000000000 --- a/system/gd/l2cap/classic/fixed_channel.cc +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/classic/fixed_channel.h" - -#include "common/bind.h" -#include "l2cap/classic/internal/fixed_channel_impl.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { - -hci::Address FixedChannel::GetDevice() const { return impl_->GetDevice(); } - -void FixedChannel::RegisterOnCloseCallback(os::Handler* user_handler, - FixedChannel::OnCloseCallback on_close_callback) { - l2cap_handler_->Post(common::BindOnce(&internal::FixedChannelImpl::RegisterOnCloseCallback, impl_, - user_handler, std::move(on_close_callback))); -} - -void FixedChannel::Acquire() { - l2cap_handler_->Post(common::BindOnce(&internal::FixedChannelImpl::Acquire, impl_)); -} - -void FixedChannel::Release() { - l2cap_handler_->Post(common::BindOnce(&internal::FixedChannelImpl::Release, impl_)); -} - -common::BidiQueueEnd<packet::BasePacketBuilder, packet::PacketView<packet::kLittleEndian>>* -FixedChannel::GetQueueUpEnd() const { - return impl_->GetQueueUpEnd(); -} -} // namespace classic -} // namespace l2cap -} // namespace bluetooth
\ No newline at end of file diff --git a/system/gd/l2cap/classic/fixed_channel.h b/system/gd/l2cap/classic/fixed_channel.h deleted file mode 100644 index 4e8bdf1725..0000000000 --- a/system/gd/l2cap/classic/fixed_channel.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2019 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. - */ -#pragma once - -#include "common/bidi_queue.h" -#include "common/callback.h" -#include "hci/acl_manager.h" -#include "l2cap/cid.h" -#include "os/handler.h" -#include "packet/base_packet_builder.h" -#include "packet/packet_view.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { - -namespace internal { -class FixedChannelImpl; -} // namespace internal - -/** - * L2CAP fixed channel object. When a new object is created, it must be - * acquired through calling {@link FixedChannel#Acquire()} within X seconds. - * Otherwise, {@link FixedChannel#Release()} will be called automatically. - * - */ -class FixedChannel { -public: - // Should only be constructed by modules that have access to LinkManager - FixedChannel(std::shared_ptr<internal::FixedChannelImpl> impl, os::Handler* l2cap_handler) - : impl_(std::move(impl)), l2cap_handler_(l2cap_handler) { - log::assert_that(impl_ != nullptr, "assert failed: impl_ != nullptr"); - log::assert_that(l2cap_handler_ != nullptr, "assert failed: l2cap_handler_ != nullptr"); - } - - hci::Address GetDevice() const; - - /** - * Register close callback. If close callback is registered, when a channel is closed, the - * channel's resource will only be freed after on_close callback is invoked. Otherwise, if no - * on_close callback is registered, the channel's resource will be freed immediately after - * closing. - * - * @param user_handler The handler used to invoke the callback on - * @param on_close_callback The callback invoked upon channel closing. - */ - using OnCloseCallback = common::OnceCallback<void(hci::ErrorCode)>; - void RegisterOnCloseCallback(os::Handler* user_handler, OnCloseCallback on_close_callback); - - /** - * Indicate that this Fixed Channel is being used. This will prevent ACL connection from being - * disconnected. - */ - void Acquire(); - - /** - * Indicate that this Fixed Channel is no longer being used. ACL connection will be disconnected - * after kLinkIdleDisconnectTimeout if no other DynamicChannel is connected or no other Fixed - * Channel is using this ACL connection. However a module can still receive data on this channel - * as long as it remains open. - */ - void Release(); - - /** - * This method will retrieve the data channel queue to send and receive packets. - * - * {@see BidiQueueEnd} - * - * @return The upper end of a bi-directional queue. - */ - common::BidiQueueEnd<packet::BasePacketBuilder, packet::PacketView<packet::kLittleEndian>>* - GetQueueUpEnd() const; - -private: - std::shared_ptr<internal::FixedChannelImpl> impl_; - os::Handler* l2cap_handler_; -}; - -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/fixed_channel_manager.cc b/system/gd/l2cap/classic/fixed_channel_manager.cc deleted file mode 100644 index aabfbdfff5..0000000000 --- a/system/gd/l2cap/classic/fixed_channel_manager.cc +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/classic/fixed_channel_manager.h" - -#include "l2cap/classic/internal/fixed_channel_service_impl.h" -#include "l2cap/classic/internal/fixed_channel_service_manager_impl.h" -#include "l2cap/classic/internal/link_manager.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { - -bool FixedChannelManager::ConnectServices(hci::Address device, - OnConnectionFailureCallback on_fail_callback, - os::Handler* handler) { - internal::LinkManager::PendingFixedChannelConnection pending_fixed_channel_connection{ - .handler_ = handler, - .on_fail_callback_ = std::move(on_fail_callback), - }; - l2cap_layer_handler_->Post(common::BindOnce(&internal::LinkManager::ConnectFixedChannelServices, - common::Unretained(link_manager_), device, - std::move(pending_fixed_channel_connection))); - return true; -} - -bool FixedChannelManager::RegisterService(Cid cid, - OnRegistrationCompleteCallback on_registration_complete, - OnConnectionOpenCallback on_connection_open, - os::Handler* handler) { - internal::FixedChannelServiceImpl::PendingRegistration pending_registration{ - .user_handler_ = handler, - .on_registration_complete_callback_ = std::move(on_registration_complete), - .on_connection_open_callback_ = std::move(on_connection_open)}; - l2cap_layer_handler_->Post(common::BindOnce(&internal::FixedChannelServiceManagerImpl::Register, - common::Unretained(service_manager_), cid, - std::move(pending_registration))); - return true; -} - -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/fixed_channel_manager.h b/system/gd/l2cap/classic/fixed_channel_manager.h deleted file mode 100644 index eb032ad343..0000000000 --- a/system/gd/l2cap/classic/fixed_channel_manager.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright 2019 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. - */ -#pragma once - -#include <string> - -#include "hci/acl_manager.h" -#include "hci/address.h" -#include "l2cap/cid.h" -#include "l2cap/classic/fixed_channel.h" -#include "l2cap/classic/fixed_channel_service.h" -#include "os/handler.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { - -class L2capClassicModule; - -namespace testing { -class MockFixedChannelManager; -} - -namespace internal { -class LinkManager; -class FixedChannelServiceManagerImpl; -} // namespace internal - -class FixedChannelManager { -public: - enum class ConnectionResultCode { - SUCCESS = 0, - FAIL_NO_SERVICE_REGISTERED = 1, // No service is registered - FAIL_ALL_SERVICES_HAVE_CHANNEL = 2, // All registered services already have a channel - FAIL_HCI_ERROR = 3, // See hci_error - }; - - struct ConnectionResult { - ConnectionResultCode connection_result_code = ConnectionResultCode::SUCCESS; - hci::ErrorCode hci_error = hci::ErrorCode::SUCCESS; - }; - /** - * OnConnectionFailureCallback(std::string failure_reason); - */ - using OnConnectionFailureCallback = common::OnceCallback<void(ConnectionResult result)>; - - /** - * OnConnectionOpenCallback(FixedChannel channel); - */ - using OnConnectionOpenCallback = common::Callback<void(std::unique_ptr<FixedChannel>)>; - - enum class RegistrationResult { - SUCCESS = 0, - FAIL_DUPLICATE_SERVICE = 1, // Duplicate service registration for the same CID - FAIL_INVALID_SERVICE = 2, // Invalid CID - }; - - /** - * OnRegistrationFailureCallback(RegistrationResult result, FixedChannelService service); - */ - using OnRegistrationCompleteCallback = - common::OnceCallback<void(RegistrationResult, std::unique_ptr<FixedChannelService>)>; - - /** - * Connect to ALL fixed channels on a remote device - * - * - This method is asynchronous - * - When false is returned, the connection fails immediately - * - When true is returned, method caller should wait for on_fail_callback or on_open_callback - * registered through RegisterService() API. - * - If an ACL connection does not exist, this method will create an ACL connection. As a result, - * on_open_callback supplied through RegisterService() will be triggered to provide the actual - * FixedChannel objects - * - If HCI connection failed, on_fail_callback will be triggered with FAIL_HCI_ERROR - * - If fixed channel on a remote device is already reported as connected via on_open_callback and - * has been acquired via FixedChannel#Acquire() API, it won't be reported again - * - If no service is registered, on_fail_callback will be triggered with - * FAIL_NO_SERVICE_REGISTERED - * - If there is an ACL connection and channels for each service is allocated, on_fail_callback - * will be triggered with FAIL_ALL_SERVICES_HAVE_CHANNEL - * - * NOTE: - * This call will initiate an effort to connect all fixed channel services on a remote device. - * Due to the connectionless nature of fixed channels, all fixed channels will be connected - * together. If a fixed channel service does not need a particular fixed channel. It should - * release the received channel immediately after receiving on_open_callback via - * FixedChannel#Release() - * - * A module calling ConnectServices() must have called RegisterService() before. - * The callback will come back from on_open_callback in the service that is registered - * - * @param device: Remote device to make this connection. - * @param on_fail_callback: A callback to indicate connection failure along with a status code. - * @param handler: The handler context in which to execute the @callback parameters. - * - * Returns: true if connection was able to be initiated, false otherwise. - */ - virtual bool ConnectServices(hci::Address device, OnConnectionFailureCallback on_fail_callback, - os::Handler* handler); - - /** - * Register a service to receive incoming connections bound to a specific channel. - * - * - This method is asynchronous. - * - When false is returned, the registration fails immediately. - * - When true is returned, method caller should wait for on_service_registered callback that - * contains a FixedChannelService object. The registered service can be managed from that object. - * - If a CID is already registered or some other error happens, on_registration_complete will be - * triggered with a non-SUCCESS value - * - After a service is registered, any classic ACL connection will create a FixedChannel object - * that is delivered through on_open_callback - * - on_open_callback, will only be triggered after on_service_registered callback - * - * @param cid: cid used to receive incoming connections - * @param on_registration_complete: A callback to indicate the service setup has completed. If the - * return status is not SUCCESS, it means service is not registered due to reasons like CID - * already take - * @param on_open_callback: A callback to indicate success of a connection initiated from a remote - * device. - * @param handler: The handler context in which to execute the @callback parameter. - */ - virtual bool RegisterService(Cid cid, OnRegistrationCompleteCallback on_registration_complete, - OnConnectionOpenCallback on_connection_open, os::Handler* handler); - - FixedChannelManager(const FixedChannelManager&) = delete; - FixedChannelManager& operator=(const FixedChannelManager&) = delete; - - virtual ~FixedChannelManager() = default; - - friend class L2capClassicModule; - friend class testing::MockFixedChannelManager; - -private: - // The constructor is not to be used by user code - FixedChannelManager(internal::FixedChannelServiceManagerImpl* service_manager, - internal::LinkManager* link_manager, os::Handler* l2cap_layer_handler) - : service_manager_(service_manager), - link_manager_(link_manager), - l2cap_layer_handler_(l2cap_layer_handler) {} - - internal::FixedChannelServiceManagerImpl* service_manager_ = nullptr; - internal::LinkManager* link_manager_ = nullptr; - os::Handler* l2cap_layer_handler_ = nullptr; -}; - -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/fixed_channel_manager_mock.h b/system/gd/l2cap/classic/fixed_channel_manager_mock.h deleted file mode 100644 index bfaec3be45..0000000000 --- a/system/gd/l2cap/classic/fixed_channel_manager_mock.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2019 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. - */ -#pragma once - -#include <gmock/gmock.h> - -#include "l2cap/classic/fixed_channel_manager.h" - -// Unit test interfaces -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace testing { - -class MockFixedChannelManager : public FixedChannelManager { -public: - MockFixedChannelManager() : FixedChannelManager(nullptr, nullptr, nullptr) {} - MOCK_METHOD(bool, ConnectServices, - (hci::Address device, OnConnectionFailureCallback on_fail_callback, - os::Handler* handler), - (override)); - MOCK_METHOD(bool, RegisterService, - (Cid cid, OnRegistrationCompleteCallback on_registration_complete, - OnConnectionOpenCallback on_connection_open, os::Handler* handler), - (override)); -}; - -} // namespace testing -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/fixed_channel_mock.h b/system/gd/l2cap/classic/fixed_channel_mock.h deleted file mode 100644 index 82fb1725f4..0000000000 --- a/system/gd/l2cap/classic/fixed_channel_mock.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2019 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. - */ -#pragma once - -#include <gmock/gmock.h> - -#include <utility> - -#include "l2cap/classic/fixed_channel.h" -#include "l2cap/classic/internal/fixed_channel_impl_mock.h" -#include "os/handler.h" - -// Unit test interfaces -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace testing { - -class MockFixedChannel : public FixedChannel { -public: - MockFixedChannel() : FixedChannel(nullptr, nullptr) {} - MOCK_METHOD(void, Acquire, ()); - MOCK_METHOD(void, Release, ()); - MOCK_METHOD(void, RegisterOnCloseCallback, - (os::Handler * handler, OnCloseCallback on_close_callback)); -}; - -} // namespace testing -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/fixed_channel_service.cc b/system/gd/l2cap/classic/fixed_channel_service.cc deleted file mode 100644 index 3a87a1b780..0000000000 --- a/system/gd/l2cap/classic/fixed_channel_service.cc +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/classic/fixed_channel_service.h" - -#include "common/bind.h" -#include "l2cap/classic/internal/fixed_channel_service_manager_impl.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { - -void FixedChannelService::Unregister(OnUnregisteredCallback on_unregistered, - os::Handler* on_unregistered_handler) { - log::assert_that(manager_ != nullptr, "this service is invalid"); - l2cap_layer_handler_->Post(common::BindOnce(&internal::FixedChannelServiceManagerImpl::Unregister, - common::Unretained(manager_), cid_, - std::move(on_unregistered), on_unregistered_handler)); -} - -} // namespace classic -} // namespace l2cap -} // namespace bluetooth
\ No newline at end of file diff --git a/system/gd/l2cap/classic/fixed_channel_service.h b/system/gd/l2cap/classic/fixed_channel_service.h deleted file mode 100644 index 29ac93a4a5..0000000000 --- a/system/gd/l2cap/classic/fixed_channel_service.h +++ /dev/null @@ -1,61 +0,0 @@ - -/* - * Copyright 2019 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. - */ -#pragma once - -#include "common/callback.h" -#include "hci/address.h" -#include "l2cap/cid.h" -#include "os/handler.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { - -namespace internal { -class FixedChannelServiceManagerImpl; -} // namespace internal - -class FixedChannelService { -public: - FixedChannelService() = default; - FixedChannelService(const FixedChannelService&) = delete; - FixedChannelService& operator=(const FixedChannelService&) = delete; - - using OnUnregisteredCallback = common::OnceCallback<void()>; - - /** - * Unregister a service from L2CAP module. This operation cannot fail. - * All channels opened for this service will be invalidated. - * - * @param on_unregistered will be triggered when unregistration is complete - */ - void Unregister(OnUnregisteredCallback on_unregistered, os::Handler* on_unregistered_handler); - - friend internal::FixedChannelServiceManagerImpl; - -private: - FixedChannelService(Cid cid, internal::FixedChannelServiceManagerImpl* manager, - os::Handler* handler) - : cid_(cid), manager_(manager), l2cap_layer_handler_(handler) {} - Cid cid_ = kInvalidCid; - internal::FixedChannelServiceManagerImpl* manager_ = nullptr; - os::Handler* l2cap_layer_handler_; -}; - -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/fixed_channel_service_mock.h b/system/gd/l2cap/classic/fixed_channel_service_mock.h deleted file mode 100644 index f6997ce0e1..0000000000 --- a/system/gd/l2cap/classic/fixed_channel_service_mock.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2019 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. - */ -#pragma once - -#include <gmock/gmock.h> - -#include "l2cap/classic/fixed_channel_service.h" - -// Unit test interfaces -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace testing { - -class MockFixedChannelService : public FixedChannelService { -public: - MockFixedChannelService() : FixedChannelService() {} - MOCK_METHOD(void, Unregister, - (OnUnregisteredCallback on_unregistered, os::Handler* on_unregistered_handler)); -}; - -} // namespace testing -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/internal/channel_configuration_state.h b/system/gd/l2cap/classic/internal/channel_configuration_state.h deleted file mode 100644 index 2ebc2f2093..0000000000 --- a/system/gd/l2cap/classic/internal/channel_configuration_state.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include "l2cap/l2cap_packets.h" -#include "l2cap/mtu.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace internal { - -struct ChannelConfigurationState { -public: - enum State { - /** - * for the initiator path, a request has been sent but a positive response has not yet been - * received, and for the acceptor path, a request with acceptable options has not yet been - * received. - */ - WAIT_CONFIG_REQ_RSP, - /** - * the acceptor path is complete after having responded to acceptable options, but for the - * initiator path, a positive response on the recent request has not yet been received. - */ - WAIT_CONFIG_RSP, - /** - * the initiator path is complete after having received a positive response, but for the - * acceptor path, a request with acceptable options has not yet been received. - */ - WAIT_CONFIG_REQ, - /** - * Configuration is complete - */ - CONFIGURED, - }; - State state_ = State::WAIT_CONFIG_REQ_RSP; - - RetransmissionAndFlowControlModeOption retransmission_and_flow_control_mode_; - RetransmissionAndFlowControlConfigurationOption local_retransmission_and_flow_control_; - RetransmissionAndFlowControlConfigurationOption remote_retransmission_and_flow_control_; - FcsType fcs_type_ = FcsType::DEFAULT; -}; -} // namespace internal -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/internal/dumpsys_helper.cc b/system/gd/l2cap/classic/internal/dumpsys_helper.cc deleted file mode 100644 index c107bd6af9..0000000000 --- a/system/gd/l2cap/classic/internal/dumpsys_helper.cc +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2020 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 "l2cap/classic/internal/dumpsys_helper.h" - -#include <string> - -#include "l2cap/classic/internal/fixed_channel_impl.h" -#include "l2cap/classic/internal/link.h" -#include "l2cap/classic/internal/link_manager.h" -#include "l2cap/internal/dynamic_channel_impl.h" -#include "l2cap_classic_module_generated.h" -#include "os/log.h" - -bluetooth::l2cap::classic::internal::DumpsysHelper::DumpsysHelper(const LinkManager& link_manager) - : link_manager_(link_manager) {} - -std::vector<flatbuffers::Offset<bluetooth::l2cap::classic::ChannelData>> -bluetooth::l2cap::classic::internal::DumpsysHelper::DumpActiveDynamicChannels( - flatbuffers::FlatBufferBuilder* fb_builder, - const l2cap::internal::DynamicChannelAllocator& channel_allocator) const { - std::vector<flatbuffers::Offset<bluetooth::l2cap::classic::ChannelData>> channel_offsets; - - for (auto it = channel_allocator.channels_.cbegin(); it != channel_allocator.channels_.cend(); - ++it) { - ChannelDataBuilder builder(*fb_builder); - builder.add_cid(it->first); - channel_offsets.push_back(builder.Finish()); - } - return channel_offsets; -} - -std::vector<flatbuffers::Offset<::bluetooth::l2cap::classic::ChannelData>> -bluetooth::l2cap::classic::internal::DumpsysHelper::DumpActiveFixedChannels( - flatbuffers::FlatBufferBuilder* fb_builder, - const bluetooth::l2cap::internal::FixedChannelAllocator< - bluetooth::l2cap::classic::internal::FixedChannelImpl, - bluetooth::l2cap::classic::internal::Link>& channel_allocator) const { - std::vector<flatbuffers::Offset<bluetooth::l2cap::classic::ChannelData>> channel_offsets; - - for (auto it = channel_allocator.channels_.cbegin(); it != channel_allocator.channels_.cend(); - ++it) { - ChannelDataBuilder builder(*fb_builder); - builder.add_cid(it->first); - channel_offsets.push_back(builder.Finish()); - } - return channel_offsets; -} - -std::vector<flatbuffers::Offset<bluetooth::l2cap::classic::LinkData>> -bluetooth::l2cap::classic::internal::DumpsysHelper::DumpActiveLinks( - flatbuffers::FlatBufferBuilder* fb_builder) const { - const std::unordered_map<hci::Address, Link>* links = &link_manager_.links_; - - std::vector<flatbuffers::Offset<LinkData>> link_offsets; - - for (auto it = links->cbegin(); it != links->cend(); ++it) { - auto link_address = fb_builder->CreateString(it->second.ToString()); - auto dynamic_channel_offsets = - DumpActiveDynamicChannels(fb_builder, it->second.dynamic_channel_allocator_); - auto dynamic_channels = fb_builder->CreateVector(dynamic_channel_offsets); - - auto fixed_channel_offsets = - DumpActiveFixedChannels(fb_builder, it->second.fixed_channel_allocator_); - auto fixed_channels = fb_builder->CreateVector(fixed_channel_offsets); - - LinkDataBuilder builder(*fb_builder); - builder.add_address(link_address); - builder.add_dynamic_channels(dynamic_channels); - builder.add_fixed_channels(fixed_channels); - link_offsets.push_back(builder.Finish()); - } - return link_offsets; -} diff --git a/system/gd/l2cap/classic/internal/dumpsys_helper.h b/system/gd/l2cap/classic/internal/dumpsys_helper.h deleted file mode 100644 index 7fb3377d2e..0000000000 --- a/system/gd/l2cap/classic/internal/dumpsys_helper.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2020 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. - */ - -#pragma once - -#include "l2cap/classic/internal/fixed_channel_impl.h" -#include "l2cap/classic/internal/link.h" -#include "l2cap/classic/internal/link_manager.h" -#include "l2cap/internal/dynamic_channel_allocator.h" -#include "l2cap/internal/fixed_channel_allocator.h" -#include "l2cap_classic_module_generated.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace internal { - -class DumpsysHelper { -public: - DumpsysHelper(const LinkManager& link_manager); - - std::vector<flatbuffers::Offset<ChannelData>> DumpActiveDynamicChannels( - flatbuffers::FlatBufferBuilder* fb_builder, - const l2cap::internal::DynamicChannelAllocator& channel_allocator) const; - std::vector<flatbuffers::Offset<ChannelData>> DumpActiveFixedChannels( - flatbuffers::FlatBufferBuilder* fb_builder, - const l2cap::internal::FixedChannelAllocator<FixedChannelImpl, Link>& channel_allocator) - const; - std::vector<flatbuffers::Offset<LinkData>> DumpActiveLinks( - flatbuffers::FlatBufferBuilder* fb_builder) const; - -private: - const LinkManager& link_manager_; -}; - -} // namespace internal -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/internal/dynamic_channel_service_impl.h b/system/gd/l2cap/classic/internal/dynamic_channel_service_impl.h deleted file mode 100644 index dc2133e446..0000000000 --- a/system/gd/l2cap/classic/internal/dynamic_channel_service_impl.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include "l2cap/classic/dynamic_channel.h" -#include "l2cap/classic/dynamic_channel_configuration_option.h" -#include "l2cap/classic/dynamic_channel_manager.h" -#include "l2cap/classic/dynamic_channel_service.h" -#include "l2cap/classic/security_policy.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace internal { -class DynamicChannelServiceImpl { -public: - virtual ~DynamicChannelServiceImpl() = default; - - struct PendingRegistration { - os::Handler* user_handler_ = nullptr; - classic::SecurityPolicy security_policy_; - DynamicChannelManager::OnRegistrationCompleteCallback on_registration_complete_callback_; - DynamicChannelManager::OnConnectionOpenCallback on_connection_open_callback_; - DynamicChannelConfigurationOption configuration_; - }; - - virtual void NotifyChannelCreation(std::unique_ptr<DynamicChannel> channel) { - on_connection_open_callback_(std::move(channel)); - } - - virtual DynamicChannelConfigurationOption GetConfigOption() const { return config_option_; } - - virtual SecurityPolicy GetSecurityPolicy() const { return security_policy_; } - - friend class DynamicChannelServiceManagerImpl; - -protected: - // protected access for mocking - DynamicChannelServiceImpl( - classic::SecurityPolicy security_policy, - DynamicChannelManager::OnConnectionOpenCallback on_connection_open_callback, - DynamicChannelConfigurationOption config_option) - : security_policy_(security_policy), - on_connection_open_callback_(std::move(on_connection_open_callback)), - config_option_(config_option) {} - -private: - classic::SecurityPolicy security_policy_; - DynamicChannelManager::OnConnectionOpenCallback on_connection_open_callback_; - DynamicChannelConfigurationOption config_option_; -}; - -} // namespace internal -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/internal/dynamic_channel_service_impl_mock.h b/system/gd/l2cap/classic/internal/dynamic_channel_service_impl_mock.h deleted file mode 100644 index 6176ed65c7..0000000000 --- a/system/gd/l2cap/classic/internal/dynamic_channel_service_impl_mock.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2020 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. - */ -#pragma once - -#include <gmock/gmock.h> - -#include "l2cap/classic/internal/dynamic_channel_service_impl.h" - -// Unit test interfaces -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace internal { -namespace testing { - -class MockDynamicChannelServiceImpl : public DynamicChannelServiceImpl { -public: - MockDynamicChannelServiceImpl() : DynamicChannelServiceImpl({}, {}, {}) {} - MOCK_METHOD(SecurityPolicy, GetSecurityPolicy, (), (const, override)); -}; - -} // namespace testing -} // namespace internal -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/internal/dynamic_channel_service_manager_impl.cc b/system/gd/l2cap/classic/internal/dynamic_channel_service_manager_impl.cc deleted file mode 100644 index 1b7ceeca4f..0000000000 --- a/system/gd/l2cap/classic/internal/dynamic_channel_service_manager_impl.cc +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/classic/internal/dynamic_channel_service_manager_impl.h" - -#include <bluetooth/log.h> - -#include "l2cap/classic/internal/dynamic_channel_service_impl.h" -#include "l2cap/psm.h" -#include "os/log.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace internal { - -void DynamicChannelServiceManagerImpl::Register( - Psm psm, DynamicChannelServiceImpl::PendingRegistration pending_registration) { - if (!IsPsmValid(psm)) { - std::unique_ptr<DynamicChannelService> invalid_service(new DynamicChannelService()); - pending_registration.on_registration_complete_callback_( - DynamicChannelManager::RegistrationResult::FAIL_INVALID_SERVICE, - std::move(invalid_service)); - } else if (IsServiceRegistered(psm)) { - std::unique_ptr<DynamicChannelService> invalid_service(new DynamicChannelService()); - pending_registration.on_registration_complete_callback_( - DynamicChannelManager::RegistrationResult::FAIL_DUPLICATE_SERVICE, - std::move(invalid_service)); - } else { - service_map_.try_emplace( - psm, - DynamicChannelServiceImpl(pending_registration.security_policy_, - std::move(pending_registration.on_connection_open_callback_), - pending_registration.configuration_)); - std::unique_ptr<DynamicChannelService> user_service( - new DynamicChannelService(psm, this, l2cap_layer_handler_)); - pending_registration.on_registration_complete_callback_( - DynamicChannelManager::RegistrationResult::SUCCESS, std::move(user_service)); - } -} - -void DynamicChannelServiceManagerImpl::Unregister( - Psm psm, DynamicChannelService::OnUnregisteredCallback callback) { - if (IsServiceRegistered(psm)) { - service_map_.erase(psm); - callback(); - } else { - log::error("service not registered psm:{}", psm); - } -} - -bool DynamicChannelServiceManagerImpl::IsServiceRegistered(Psm psm) const { - return service_map_.find(psm) != service_map_.end(); -} - -DynamicChannelServiceImpl* DynamicChannelServiceManagerImpl::GetService(Psm psm) { - log::assert_that(IsServiceRegistered(psm), "assert failed: IsServiceRegistered(psm)"); - return &service_map_.find(psm)->second; -} - -std::vector<std::pair<Psm, DynamicChannelServiceImpl*>> -DynamicChannelServiceManagerImpl::GetRegisteredServices() { - std::vector<std::pair<Psm, DynamicChannelServiceImpl*>> results; - for (auto& elem : service_map_) { - results.emplace_back(elem.first, &elem.second); - } - return results; -} - -} // namespace internal -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/internal/dynamic_channel_service_manager_impl.h b/system/gd/l2cap/classic/internal/dynamic_channel_service_manager_impl.h deleted file mode 100644 index 97df099e2b..0000000000 --- a/system/gd/l2cap/classic/internal/dynamic_channel_service_manager_impl.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <unordered_map> - -#include "l2cap/classic/dynamic_channel_service.h" -#include "l2cap/classic/internal/dynamic_channel_service_impl.h" -#include "l2cap/classic/security_enforcement_interface.h" -#include "l2cap/psm.h" -#include "os/handler.h" -#include "os/log.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace internal { - -class DynamicChannelServiceManagerImpl { -public: - explicit DynamicChannelServiceManagerImpl(os::Handler* l2cap_layer_handler) - : l2cap_layer_handler_(l2cap_layer_handler) {} - - virtual ~DynamicChannelServiceManagerImpl() = default; - // - // All APIs must be invoked in L2CAP layer handler - // - virtual void Register(Psm psm, - DynamicChannelServiceImpl::PendingRegistration pending_registration); - virtual void Unregister(Psm psm, DynamicChannelService::OnUnregisteredCallback callback); - virtual bool IsServiceRegistered(Psm psm) const; - virtual DynamicChannelServiceImpl* GetService(Psm psm); - - virtual std::vector<std::pair<Psm, DynamicChannelServiceImpl*>> GetRegisteredServices(); - - // Implementation is set by SecurityManager through L2capModule - void SetSecurityEnforcementInterface(SecurityEnforcementInterface* impl) { - security_enforcement_interface_ = impl; - } - - virtual SecurityEnforcementInterface* GetSecurityEnforcementInterface() { - return security_enforcement_interface_; - } - -private: - os::Handler* l2cap_layer_handler_ = nullptr; - std::unordered_map<Psm, DynamicChannelServiceImpl> service_map_; - SecurityEnforcementInterface* security_enforcement_interface_ = nullptr; -}; -} // namespace internal -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/internal/dynamic_channel_service_manager_impl_mock.h b/system/gd/l2cap/classic/internal/dynamic_channel_service_manager_impl_mock.h deleted file mode 100644 index 1990c86e6c..0000000000 --- a/system/gd/l2cap/classic/internal/dynamic_channel_service_manager_impl_mock.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2019 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. - */ -#pragma once - -#include <gmock/gmock.h> - -#include "l2cap/classic/internal/dynamic_channel_service_manager_impl.h" -#include "l2cap/classic/security_enforcement_interface.h" -#include "l2cap/internal/dynamic_channel_impl.h" - -// Unit test interfaces -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace internal { -namespace testing { - -class MockDynamicChannelServiceManagerImpl : public DynamicChannelServiceManagerImpl { -public: - MockDynamicChannelServiceManagerImpl() : DynamicChannelServiceManagerImpl(nullptr) {} - MOCK_METHOD(void, Register, - (Psm psm, DynamicChannelServiceImpl::PendingRegistration pending_registration), - (override)); - MOCK_METHOD(void, Unregister, (Psm psm, DynamicChannelService::OnUnregisteredCallback callback), - (override)); - MOCK_METHOD(bool, IsServiceRegistered, (Psm psm), (const, override)); - MOCK_METHOD(DynamicChannelServiceImpl*, GetService, (Psm psm), (override)); - MOCK_METHOD((std::vector<std::pair<Psm, DynamicChannelServiceImpl*>>), GetRegisteredServices, (), - (override)); - MOCK_METHOD(SecurityEnforcementInterface*, GetSecurityEnforcementInterface, (), (override)); -}; - -} // namespace testing -} // namespace internal -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/internal/dynamic_channel_service_manager_test.cc b/system/gd/l2cap/classic/internal/dynamic_channel_service_manager_test.cc deleted file mode 100644 index bc03b563b2..0000000000 --- a/system/gd/l2cap/classic/internal/dynamic_channel_service_manager_test.cc +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2018 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 <future> - -#include "common/bind.h" -#include "l2cap/cid.h" -#include "l2cap/classic/dynamic_channel_manager.h" -#include "l2cap/classic/dynamic_channel_service.h" -#include "l2cap/classic/internal/dynamic_channel_service_manager_impl.h" -#include "os/handler.h" -#include "os/thread.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace internal { -namespace { - -class L2capDynamicServiceManagerTest : public ::testing::Test { -public: - ~L2capDynamicServiceManagerTest() = default; - - void OnServiceRegistered(bool expect_success, DynamicChannelManager::RegistrationResult result, - std::unique_ptr<DynamicChannelService> user_service) { - EXPECT_EQ(result == DynamicChannelManager::RegistrationResult::SUCCESS, expect_success); - service_registered_ = expect_success; - } - -protected: - void SetUp() override { - thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL); - user_handler_ = new os::Handler(thread_); - l2cap_handler_ = new os::Handler(thread_); - manager_ = new DynamicChannelServiceManagerImpl{l2cap_handler_}; - } - - void TearDown() override { - delete manager_; - l2cap_handler_->Clear(); - delete l2cap_handler_; - user_handler_->Clear(); - delete user_handler_; - delete thread_; - } - - void sync_user_handler() { - std::promise<void> promise; - auto future = promise.get_future(); - user_handler_->CallOn(&promise, &std::promise<void>::set_value); - auto future_status = future.wait_for(std::chrono::seconds(1)); - EXPECT_EQ(future_status, std::future_status::ready); - } - - DynamicChannelServiceManagerImpl* manager_ = nullptr; - os::Thread* thread_ = nullptr; - os::Handler* user_handler_ = nullptr; - os::Handler* l2cap_handler_ = nullptr; - - bool service_registered_ = false; -}; - -TEST_F(L2capDynamicServiceManagerTest, register_and_unregister_classic_dynamic_channel) { - DynamicChannelServiceImpl::PendingRegistration pending_registration{ - .user_handler_ = user_handler_, - .security_policy_ = - SecurityPolicy::_SDP_ONLY_NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK, - .on_registration_complete_callback_ = user_handler_->BindOnceOn( - this, &L2capDynamicServiceManagerTest::OnServiceRegistered, true)}; - Cid cid = kSmpBrCid; - EXPECT_FALSE(manager_->IsServiceRegistered(cid)); - manager_->Register(cid, std::move(pending_registration)); - EXPECT_TRUE(manager_->IsServiceRegistered(cid)); - sync_user_handler(); - EXPECT_TRUE(service_registered_); - manager_->Unregister(cid, user_handler_->BindOnce([] {})); - EXPECT_FALSE(manager_->IsServiceRegistered(cid)); -} - -TEST_F(L2capDynamicServiceManagerTest, register_classic_dynamic_channel_bad_cid) { - DynamicChannelServiceImpl::PendingRegistration pending_registration{ - .security_policy_ = - SecurityPolicy::_SDP_ONLY_NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK, - .on_registration_complete_callback_ = user_handler_->BindOnceOn( - this, &L2capDynamicServiceManagerTest::OnServiceRegistered, false)}; - Cid cid = 0x1000; - EXPECT_FALSE(manager_->IsServiceRegistered(cid)); - manager_->Register(cid, std::move(pending_registration)); - EXPECT_FALSE(manager_->IsServiceRegistered(cid)); - sync_user_handler(); - EXPECT_FALSE(service_registered_); -} - -} // namespace -} // namespace internal -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/internal/fixed_channel_impl.cc b/system/gd/l2cap/classic/internal/fixed_channel_impl.cc deleted file mode 100644 index eaae3cb1cb..0000000000 --- a/system/gd/l2cap/classic/internal/fixed_channel_impl.cc +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/classic/internal/fixed_channel_impl.h" - -#include <bluetooth/log.h> - -#include <unordered_map> - -#include "l2cap/cid.h" -#include "l2cap/classic/internal/link.h" -#include "os/handler.h" -#include "os/log.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace internal { - -FixedChannelImpl::FixedChannelImpl(Cid cid, Link* link, os::Handler* l2cap_handler) - : cid_(cid), device_(link->GetDevice()), link_(link), l2cap_handler_(l2cap_handler) { - log::assert_that(cid_ >= kFirstFixedChannel && cid_ <= kLastFixedChannel, "Invalid cid: {}", - cid_); - log::assert_that(link_ != nullptr, "assert failed: link_ != nullptr"); - log::assert_that(l2cap_handler_ != nullptr, "assert failed: l2cap_handler_ != nullptr"); -} - -void FixedChannelImpl::RegisterOnCloseCallback(os::Handler* user_handler, - FixedChannel::OnCloseCallback on_close_callback) { - log::assert_that(user_handler_ == nullptr, "OnCloseCallback can only be registered once"); - // If channel is already closed, call the callback immediately without saving it - if (closed_) { - user_handler->Post(common::BindOnce(std::move(on_close_callback), close_reason_)); - return; - } - user_handler_ = user_handler; - on_close_callback_ = std::move(on_close_callback); -} - -void FixedChannelImpl::OnClosed(hci::ErrorCode status) { - log::assert_that(!closed_, - "Device {} Cid 0x{:x} closed twice, old status 0x{:x}, new status 0x{:x}", - ADDRESS_TO_LOGGABLE_CSTR(device_), cid_, static_cast<int>(close_reason_), - static_cast<int>(status)); - closed_ = true; - close_reason_ = status; - acquired_ = false; - link_ = nullptr; - l2cap_handler_ = nullptr; - if (user_handler_ == nullptr) { - return; - } - // On close callback can only be called once - user_handler_->Post(common::BindOnce(std::move(on_close_callback_), status)); - user_handler_ = nullptr; - on_close_callback_.Reset(); -} - -void FixedChannelImpl::Acquire() { - log::assert_that(user_handler_ != nullptr, - "Must register OnCloseCallback before calling any methods"); - if (closed_) { - log::warn("{} is already closed", ToRedactedStringForLogging()); - log::assert_that(!acquired_, "assert failed: !acquired_"); - return; - } - if (acquired_) { - log::info("{} was already acquired", ToRedactedStringForLogging()); - return; - } - acquired_ = true; - link_->RefreshRefCount(); -} - -void FixedChannelImpl::Release() { - log::assert_that(user_handler_ != nullptr, - "Must register OnCloseCallback before calling any methods"); - if (closed_) { - log::warn("{} is already closed", ToRedactedStringForLogging()); - log::assert_that(!acquired_, "assert failed: !acquired_"); - return; - } - if (!acquired_) { - log::info("{} was already released", ToRedactedStringForLogging()); - return; - } - acquired_ = false; - link_->RefreshRefCount(); -} - -} // namespace internal -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/internal/fixed_channel_impl.h b/system/gd/l2cap/classic/internal/fixed_channel_impl.h deleted file mode 100644 index 6ce00a48c3..0000000000 --- a/system/gd/l2cap/classic/internal/fixed_channel_impl.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include "common/bidi_queue.h" -#include "common/interfaces/ILoggable.h" -#include "l2cap/cid.h" -#include "l2cap/classic/fixed_channel.h" -#include "l2cap/internal/channel_impl.h" -#include "l2cap/l2cap_packets.h" -#include "os/handler.h" -#include "os/log.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace internal { - -class Link; - -class FixedChannelImpl : public l2cap::internal::ChannelImpl, - public bluetooth::common::IRedactableLoggable { -public: - FixedChannelImpl(Cid cid, Link* link, os::Handler* l2cap_handler); - - FixedChannelImpl(const FixedChannelImpl&) = delete; - FixedChannelImpl& operator=(const FixedChannelImpl&) = delete; - - virtual ~FixedChannelImpl() = default; - - hci::Address GetDevice() const { return device_.GetAddress(); } - - virtual void RegisterOnCloseCallback(os::Handler* user_handler, - FixedChannel::OnCloseCallback on_close_callback); - - virtual void Acquire(); - - virtual void Release(); - - virtual bool IsAcquired() const { return acquired_; } - - virtual void OnClosed(hci::ErrorCode status); - - std::string ToStringForLogging() const override { - std::ostringstream ss; - ss << "Device " << device_.ToStringForLogging() << " Cid 0x" << std::hex << cid_; - return ss.str(); - } - - std::string ToRedactedStringForLogging() const override { - std::ostringstream ss; - ss << "Device " << device_.ToRedactedStringForLogging() << " Cid 0x" << std::hex << cid_; - return ss.str(); - } - - common::BidiQueueEnd<packet::BasePacketBuilder, packet::PacketView<packet::kLittleEndian>>* - GetQueueUpEnd() { - return channel_queue_.GetUpEnd(); - } - - common::BidiQueueEnd<packet::PacketView<packet::kLittleEndian>, packet::BasePacketBuilder>* - GetQueueDownEnd() { - return channel_queue_.GetDownEnd(); - } - - Cid GetCid() const { return cid_; } - - Cid GetRemoteCid() const { return cid_; } - -private: - // Constructor states - // For logging purpose only - const Cid cid_; - // For logging purpose only - const hci::AddressWithType device_; - // Needed to handle Acquire() and Release() - Link* link_; - os::Handler* l2cap_handler_; - - // User supported states - os::Handler* user_handler_ = nullptr; - FixedChannel::OnCloseCallback on_close_callback_{}; - - // Internal states - bool acquired_ = false; - bool closed_ = false; - hci::ErrorCode close_reason_ = hci::ErrorCode::SUCCESS; - static constexpr size_t kChannelQueueSize = 10; - common::BidiQueue<packet::PacketView<packet::kLittleEndian>, packet::BasePacketBuilder> - channel_queue_{kChannelQueueSize}; -}; - -} // namespace internal -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/internal/fixed_channel_impl_mock.h b/system/gd/l2cap/classic/internal/fixed_channel_impl_mock.h deleted file mode 100644 index d5eaee180b..0000000000 --- a/system/gd/l2cap/classic/internal/fixed_channel_impl_mock.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2019 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. - */ -#pragma once - -#include <gmock/gmock.h> - -#include "l2cap/classic/internal/fixed_channel_impl.h" - -// Unit test interfaces -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace internal { -namespace testing { - -class MockFixedChannelImpl : public FixedChannelImpl { -public: - MockFixedChannelImpl(Cid cid, Link* link, os::Handler* l2cap_handler) - : FixedChannelImpl(cid, link, l2cap_handler) {} - MOCK_METHOD(void, RegisterOnCloseCallback, - (os::Handler * user_handler, FixedChannel::OnCloseCallback on_close_callback), - (override)); - MOCK_METHOD(void, Acquire, (), (override)); - MOCK_METHOD(void, Release, (), (override)); - MOCK_METHOD(bool, IsAcquired, (), (override, const)); - MOCK_METHOD(void, OnClosed, (hci::ErrorCode status), (override)); -}; - -} // namespace testing -} // namespace internal -} // namespace classic -} // namespace l2cap -} // namespace bluetooth
\ No newline at end of file diff --git a/system/gd/l2cap/classic/internal/fixed_channel_impl_test.cc b/system/gd/l2cap/classic/internal/fixed_channel_impl_test.cc deleted file mode 100644 index d22ff62d07..0000000000 --- a/system/gd/l2cap/classic/internal/fixed_channel_impl_test.cc +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/classic/internal/fixed_channel_impl.h" - -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include "common/testing/bind_test_util.h" -#include "l2cap/cid.h" -#include "l2cap/classic/internal/link_mock.h" -#include "l2cap/internal/parameter_provider_mock.h" -#include "os/handler.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace internal { - -using l2cap::internal::testing::MockParameterProvider; -using ::testing::_; -using testing::MockLink; -using ::testing::Return; - -class L2capClassicFixedChannelImplTest : public ::testing::Test { -public: - static void SyncHandler(os::Handler* handler) { - std::promise<void> promise; - auto future = promise.get_future(); - handler->Post(common::BindOnce(&std::promise<void>::set_value, common::Unretained(&promise))); - future.wait_for(std::chrono::seconds(1)); - } - -protected: - void SetUp() override { - thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL); - l2cap_handler_ = new os::Handler(thread_); - } - - void TearDown() override { - l2cap_handler_->Clear(); - delete l2cap_handler_; - delete thread_; - } - - os::Thread* thread_ = nullptr; - os::Handler* l2cap_handler_ = nullptr; -}; - -TEST_F(L2capClassicFixedChannelImplTest, get_device) { - MockParameterProvider mock_parameter_provider; - EXPECT_CALL(mock_parameter_provider, GetClassicLinkIdleDisconnectTimeout()) - .WillRepeatedly(Return(std::chrono::seconds(5))); - testing::MockClassicAclConnection* mock_acl_connection = new testing::MockClassicAclConnection(); - EXPECT_CALL(*mock_acl_connection, GetAddress()).Times(1); - EXPECT_CALL(*mock_acl_connection, RegisterCallbacks(_, l2cap_handler_)).Times(1); - MockLink mock_classic_link( - l2cap_handler_, &mock_parameter_provider, - std::unique_ptr<testing::MockClassicAclConnection>(mock_acl_connection), - nullptr /* LinkManager */); - hci::AddressWithType device{hci::Address{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::PUBLIC_IDENTITY_ADDRESS}; - EXPECT_CALL(mock_classic_link, GetDevice()).WillRepeatedly(Return(device)); - FixedChannelImpl fixed_channel_impl(kSmpBrCid, &mock_classic_link, l2cap_handler_); - EXPECT_EQ(device.GetAddress(), fixed_channel_impl.GetDevice()); -} - -TEST_F(L2capClassicFixedChannelImplTest, close_triggers_callback) { - MockParameterProvider mock_parameter_provider; - EXPECT_CALL(mock_parameter_provider, GetClassicLinkIdleDisconnectTimeout()) - .WillRepeatedly(Return(std::chrono::seconds(5))); - testing::MockClassicAclConnection* mock_acl_connection = new testing::MockClassicAclConnection(); - EXPECT_CALL(*mock_acl_connection, GetAddress()).Times(1); - EXPECT_CALL(*mock_acl_connection, RegisterCallbacks(_, l2cap_handler_)).Times(1); - MockLink mock_classic_link( - l2cap_handler_, &mock_parameter_provider, - std::unique_ptr<testing::MockClassicAclConnection>(mock_acl_connection), - nullptr /* LinkManager */); - hci::AddressWithType device{hci::Address{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::PUBLIC_IDENTITY_ADDRESS}; - EXPECT_CALL(mock_classic_link, GetDevice()).WillRepeatedly(Return(device)); - FixedChannelImpl fixed_channel_impl(kSmpBrCid, &mock_classic_link, l2cap_handler_); - - // Register on close callback - auto user_handler = std::make_unique<os::Handler>(thread_); - hci::ErrorCode my_status = hci::ErrorCode::SUCCESS; - fixed_channel_impl.RegisterOnCloseCallback( - user_handler.get(), common::testing::BindLambdaForTesting( - [&](hci::ErrorCode status) { my_status = status; })); - - // Channel closure should trigger such callback - fixed_channel_impl.OnClosed(hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION); - SyncHandler(user_handler.get()); - EXPECT_EQ(hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION, my_status); - - user_handler->Clear(); -} - -TEST_F(L2capClassicFixedChannelImplTest, register_callback_after_close_should_call_immediately) { - MockParameterProvider mock_parameter_provider; - EXPECT_CALL(mock_parameter_provider, GetClassicLinkIdleDisconnectTimeout()) - .WillRepeatedly(Return(std::chrono::seconds(5))); - testing::MockClassicAclConnection* mock_acl_connection = new testing::MockClassicAclConnection(); - EXPECT_CALL(*mock_acl_connection, GetAddress()).Times(1); - EXPECT_CALL(*mock_acl_connection, RegisterCallbacks(_, l2cap_handler_)).Times(1); - MockLink mock_classic_link( - l2cap_handler_, &mock_parameter_provider, - std::unique_ptr<testing::MockClassicAclConnection>(mock_acl_connection), - nullptr /* LinkManager */); - hci::AddressWithType device{hci::Address{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::PUBLIC_IDENTITY_ADDRESS}; - EXPECT_CALL(mock_classic_link, GetDevice()).WillRepeatedly(Return(device)); - FixedChannelImpl fixed_channel_impl(kSmpBrCid, &mock_classic_link, l2cap_handler_); - - // Channel closure should do nothing - fixed_channel_impl.OnClosed(hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION); - - // Register on close callback should trigger callback immediately - auto user_handler = std::make_unique<os::Handler>(thread_); - hci::ErrorCode my_status = hci::ErrorCode::SUCCESS; - fixed_channel_impl.RegisterOnCloseCallback( - user_handler.get(), common::testing::BindLambdaForTesting( - [&](hci::ErrorCode status) { my_status = status; })); - SyncHandler(user_handler.get()); - EXPECT_EQ(hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION, my_status); - - user_handler->Clear(); -} - -TEST_F(L2capClassicFixedChannelImplTest, close_twice_should_fail) { - ::testing::FLAGS_gtest_death_test_style = "threadsafe"; - MockParameterProvider mock_parameter_provider; - EXPECT_CALL(mock_parameter_provider, GetClassicLinkIdleDisconnectTimeout()) - .WillRepeatedly(Return(std::chrono::seconds(5))); - testing::MockClassicAclConnection* mock_acl_connection = new testing::MockClassicAclConnection(); - EXPECT_CALL(*mock_acl_connection, GetAddress()).Times(1); - EXPECT_CALL(*mock_acl_connection, RegisterCallbacks(_, l2cap_handler_)).Times(1); - MockLink mock_classic_link( - l2cap_handler_, &mock_parameter_provider, - std::unique_ptr<testing::MockClassicAclConnection>(mock_acl_connection), - nullptr /* LinkManager */); - hci::AddressWithType device{hci::Address{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::PUBLIC_IDENTITY_ADDRESS}; - EXPECT_CALL(mock_classic_link, GetDevice()).WillRepeatedly(Return(device)); - FixedChannelImpl fixed_channel_impl(kSmpBrCid, &mock_classic_link, l2cap_handler_); - - // Register on close callback - auto user_handler = std::make_unique<os::Handler>(thread_); - hci::ErrorCode my_status = hci::ErrorCode::SUCCESS; - fixed_channel_impl.RegisterOnCloseCallback( - user_handler.get(), common::testing::BindLambdaForTesting( - [&](hci::ErrorCode status) { my_status = status; })); - - // Channel closure should trigger such callback - fixed_channel_impl.OnClosed(hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION); - SyncHandler(user_handler.get()); - EXPECT_EQ(hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION, my_status); - - // 2nd OnClose() callback should fail - EXPECT_DEATH(fixed_channel_impl.OnClosed(hci::ErrorCode::PAGE_TIMEOUT), - ".*assertion \'!closed_\' failed.*"); - - user_handler->Clear(); -} - -TEST_F(L2capClassicFixedChannelImplTest, multiple_registration_should_fail) { - ::testing::FLAGS_gtest_death_test_style = "threadsafe"; - MockParameterProvider mock_parameter_provider; - EXPECT_CALL(mock_parameter_provider, GetClassicLinkIdleDisconnectTimeout()) - .WillRepeatedly(Return(std::chrono::seconds(5))); - testing::MockClassicAclConnection* mock_acl_connection = new testing::MockClassicAclConnection(); - EXPECT_CALL(*mock_acl_connection, GetAddress()).Times(1); - EXPECT_CALL(*mock_acl_connection, RegisterCallbacks(_, l2cap_handler_)).Times(1); - MockLink mock_classic_link( - l2cap_handler_, &mock_parameter_provider, - std::unique_ptr<testing::MockClassicAclConnection>(mock_acl_connection), - nullptr /* LinkManager */); - hci::AddressWithType device{hci::Address{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::PUBLIC_IDENTITY_ADDRESS}; - EXPECT_CALL(mock_classic_link, GetDevice()).WillRepeatedly(Return(device)); - FixedChannelImpl fixed_channel_impl(kSmpBrCid, &mock_classic_link, l2cap_handler_); - - // Register on close callback - auto user_handler = std::make_unique<os::Handler>(thread_); - hci::ErrorCode my_status = hci::ErrorCode::SUCCESS; - fixed_channel_impl.RegisterOnCloseCallback( - user_handler.get(), common::testing::BindLambdaForTesting( - [&](hci::ErrorCode status) { my_status = status; })); - - EXPECT_DEATH(fixed_channel_impl.RegisterOnCloseCallback( - user_handler.get(), common::BindOnce([](hci::ErrorCode status) { FAIL(); })), - ".*OnCloseCallback can only be registered once.*"); - - user_handler->Clear(); -} - -TEST_F(L2capClassicFixedChannelImplTest, call_acquire_before_registration_should_fail) { - ::testing::FLAGS_gtest_death_test_style = "threadsafe"; - MockParameterProvider mock_parameter_provider; - EXPECT_CALL(mock_parameter_provider, GetClassicLinkIdleDisconnectTimeout()) - .WillRepeatedly(Return(std::chrono::seconds(5))); - testing::MockClassicAclConnection* mock_acl_connection = new testing::MockClassicAclConnection(); - EXPECT_CALL(*mock_acl_connection, GetAddress()).Times(1); - EXPECT_CALL(*mock_acl_connection, RegisterCallbacks(_, l2cap_handler_)).Times(1); - MockLink mock_classic_link( - l2cap_handler_, &mock_parameter_provider, - std::unique_ptr<testing::MockClassicAclConnection>(mock_acl_connection), - nullptr /* LinkManager */); - hci::AddressWithType device{hci::Address{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::PUBLIC_IDENTITY_ADDRESS}; - EXPECT_CALL(mock_classic_link, GetDevice()).WillRepeatedly(Return(device)); - FixedChannelImpl fixed_channel_impl(kSmpBrCid, &mock_classic_link, l2cap_handler_); - EXPECT_DEATH(fixed_channel_impl.Acquire(), - ".*Must register OnCloseCallback before calling any methods.*"); -} - -TEST_F(L2capClassicFixedChannelImplTest, call_release_before_registration_should_fail) { - ::testing::FLAGS_gtest_death_test_style = "threadsafe"; - MockParameterProvider mock_parameter_provider; - EXPECT_CALL(mock_parameter_provider, GetClassicLinkIdleDisconnectTimeout()) - .WillRepeatedly(Return(std::chrono::seconds(5))); - testing::MockClassicAclConnection* mock_acl_connection = new testing::MockClassicAclConnection(); - EXPECT_CALL(*mock_acl_connection, GetAddress()).Times(1); - EXPECT_CALL(*mock_acl_connection, RegisterCallbacks(_, l2cap_handler_)).Times(1); - MockLink mock_classic_link( - l2cap_handler_, &mock_parameter_provider, - std::unique_ptr<testing::MockClassicAclConnection>(mock_acl_connection), - nullptr /* LinkManager */); - hci::AddressWithType device{hci::Address{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::PUBLIC_IDENTITY_ADDRESS}; - EXPECT_CALL(mock_classic_link, GetDevice()).WillRepeatedly(Return(device)); - FixedChannelImpl fixed_channel_impl(kSmpBrCid, &mock_classic_link, l2cap_handler_); - EXPECT_DEATH(fixed_channel_impl.Release(), - ".*Must register OnCloseCallback before calling any methods.*"); -} - -TEST_F(L2capClassicFixedChannelImplTest, test_acquire_release_channel) { - MockParameterProvider mock_parameter_provider; - EXPECT_CALL(mock_parameter_provider, GetClassicLinkIdleDisconnectTimeout()) - .WillRepeatedly(Return(std::chrono::seconds(5))); - EXPECT_CALL(mock_parameter_provider, GetClassicLinkIdleDisconnectTimeout()) - .WillRepeatedly(Return(std::chrono::seconds(5))); - testing::MockClassicAclConnection* mock_acl_connection = new testing::MockClassicAclConnection(); - EXPECT_CALL(*mock_acl_connection, GetAddress()).Times(1); - EXPECT_CALL(*mock_acl_connection, RegisterCallbacks(_, l2cap_handler_)).Times(1); - MockLink mock_classic_link( - l2cap_handler_, &mock_parameter_provider, - std::unique_ptr<testing::MockClassicAclConnection>(mock_acl_connection), - nullptr /* LinkManager */); - hci::AddressWithType device{hci::Address{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::PUBLIC_IDENTITY_ADDRESS}; - EXPECT_CALL(mock_classic_link, GetDevice()).WillRepeatedly(Return(device)); - FixedChannelImpl fixed_channel_impl(kSmpBrCid, &mock_classic_link, l2cap_handler_); - - // Register on close callback - auto user_handler = std::make_unique<os::Handler>(thread_); - hci::ErrorCode my_status = hci::ErrorCode::SUCCESS; - fixed_channel_impl.RegisterOnCloseCallback( - user_handler.get(), common::testing::BindLambdaForTesting( - [&my_status](hci::ErrorCode status) { my_status = status; })); - - // Default should be false - EXPECT_FALSE(fixed_channel_impl.IsAcquired()); - - // Should be called 2 times after Acquire() and Release() - EXPECT_CALL(mock_classic_link, RefreshRefCount()).Times(2); - - fixed_channel_impl.Acquire(); - EXPECT_TRUE(fixed_channel_impl.IsAcquired()); - - fixed_channel_impl.Release(); - EXPECT_FALSE(fixed_channel_impl.IsAcquired()); - - user_handler->Clear(); -} - -TEST_F(L2capClassicFixedChannelImplTest, test_acquire_after_close) { - ::testing::FLAGS_gtest_death_test_style = "threadsafe"; - MockParameterProvider mock_parameter_provider; - EXPECT_CALL(mock_parameter_provider, GetClassicLinkIdleDisconnectTimeout()) - .WillRepeatedly(Return(std::chrono::seconds(5))); - testing::MockClassicAclConnection* mock_acl_connection = new testing::MockClassicAclConnection(); - EXPECT_CALL(*mock_acl_connection, GetAddress()).Times(1); - EXPECT_CALL(*mock_acl_connection, RegisterCallbacks(_, l2cap_handler_)).Times(1); - MockLink mock_classic_link( - l2cap_handler_, &mock_parameter_provider, - std::unique_ptr<testing::MockClassicAclConnection>(mock_acl_connection), - nullptr /* LinkManager */); - hci::AddressWithType device{hci::Address{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::PUBLIC_IDENTITY_ADDRESS}; - EXPECT_CALL(mock_classic_link, GetDevice()).WillRepeatedly(Return(device)); - FixedChannelImpl fixed_channel_impl(kSmpBrCid, &mock_classic_link, l2cap_handler_); - - // Register on close callback - auto user_handler = std::make_unique<os::Handler>(thread_); - hci::ErrorCode my_status = hci::ErrorCode::SUCCESS; - std::promise<void> promise; - auto future = promise.get_future(); - fixed_channel_impl.RegisterOnCloseCallback( - user_handler.get(), common::testing::BindLambdaForTesting([&](hci::ErrorCode status) { - my_status = status; - promise.set_value(); - })); - - // Channel closure should trigger such callback - fixed_channel_impl.OnClosed(hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION); - SyncHandler(user_handler.get()); - auto future_status = future.wait_for(std::chrono::seconds(1)); - EXPECT_EQ(future_status, std::future_status::ready); - EXPECT_EQ(hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION, my_status); - - // Release or Acquire after closing should crash - EXPECT_CALL(mock_classic_link, RefreshRefCount()).Times(0); - EXPECT_FALSE(fixed_channel_impl.IsAcquired()); - EXPECT_DEATH(fixed_channel_impl.Acquire(), - ".*Must register OnCloseCallback before calling any methods.*"); - - user_handler->Clear(); -} - -} // namespace internal -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/internal/fixed_channel_service_impl.h b/system/gd/l2cap/classic/internal/fixed_channel_service_impl.h deleted file mode 100644 index 087f800b46..0000000000 --- a/system/gd/l2cap/classic/internal/fixed_channel_service_impl.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include "l2cap/classic/fixed_channel.h" -#include "l2cap/classic/fixed_channel_manager.h" -#include "l2cap/classic/fixed_channel_service.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace internal { - -class FixedChannelServiceImpl { -public: - virtual ~FixedChannelServiceImpl() = default; - - struct PendingRegistration { - os::Handler* user_handler_ = nullptr; - FixedChannelManager::OnRegistrationCompleteCallback on_registration_complete_callback_; - FixedChannelManager::OnConnectionOpenCallback on_connection_open_callback_; - }; - - virtual void NotifyChannelCreation(std::unique_ptr<FixedChannel> channel) { - user_handler_->Post(common::BindOnce(on_connection_open_callback_, std::move(channel))); - } - - friend class FixedChannelServiceManagerImpl; - -protected: - // protected access for mocking - FixedChannelServiceImpl(os::Handler* user_handler, - FixedChannelManager::OnConnectionOpenCallback on_connection_open_callback) - : user_handler_(user_handler), - on_connection_open_callback_(std::move(on_connection_open_callback)) {} - -private: - os::Handler* user_handler_ = nullptr; - FixedChannelManager::OnConnectionOpenCallback on_connection_open_callback_; -}; - -} // namespace internal -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/internal/fixed_channel_service_impl_mock.h b/system/gd/l2cap/classic/internal/fixed_channel_service_impl_mock.h deleted file mode 100644 index 9eebacfb4c..0000000000 --- a/system/gd/l2cap/classic/internal/fixed_channel_service_impl_mock.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2019 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. - */ -#pragma once - -#include <gmock/gmock.h> - -#include "l2cap/classic/internal/fixed_channel_impl.h" -#include "l2cap/classic/internal/fixed_channel_service_manager_impl.h" - -// Unit test interfaces -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace internal { -namespace testing { - -class MockFixedChannelServiceImpl : public FixedChannelServiceImpl { -public: - MockFixedChannelServiceImpl() - : FixedChannelServiceImpl(nullptr, FixedChannelManager::OnConnectionOpenCallback()) {} - MOCK_METHOD(void, NotifyChannelCreation, (std::unique_ptr<FixedChannel> channel), (override)); -}; - -} // namespace testing -} // namespace internal -} // namespace classic -} // namespace l2cap -} // namespace bluetooth
\ No newline at end of file diff --git a/system/gd/l2cap/classic/internal/fixed_channel_service_manager_impl.cc b/system/gd/l2cap/classic/internal/fixed_channel_service_manager_impl.cc deleted file mode 100644 index 169b55b06a..0000000000 --- a/system/gd/l2cap/classic/internal/fixed_channel_service_manager_impl.cc +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/classic/internal/fixed_channel_service_manager_impl.h" - -#include <bluetooth/log.h> - -#include "common/bind.h" -#include "l2cap/cid.h" -#include "l2cap/classic/internal/fixed_channel_service_impl.h" -#include "os/log.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace internal { - -void FixedChannelServiceManagerImpl::Register( - Cid cid, FixedChannelServiceImpl::PendingRegistration pending_registration) { - if (cid < kFirstFixedChannel || cid > kLastFixedChannel || cid == kClassicSignallingCid) { - std::unique_ptr<FixedChannelService> invalid_service(new FixedChannelService()); - pending_registration.user_handler_->Post( - common::BindOnce(std::move(pending_registration.on_registration_complete_callback_), - FixedChannelManager::RegistrationResult::FAIL_INVALID_SERVICE, - std::move(invalid_service))); - } else if (IsServiceRegistered(cid)) { - std::unique_ptr<FixedChannelService> invalid_service(new FixedChannelService()); - pending_registration.user_handler_->Post( - common::BindOnce(std::move(pending_registration.on_registration_complete_callback_), - FixedChannelManager::RegistrationResult::FAIL_DUPLICATE_SERVICE, - std::move(invalid_service))); - } else { - service_map_.try_emplace( - cid, - FixedChannelServiceImpl(pending_registration.user_handler_, - std::move(pending_registration.on_connection_open_callback_))); - std::unique_ptr<FixedChannelService> user_service( - new FixedChannelService(cid, this, l2cap_layer_handler_)); - pending_registration.user_handler_->Post(common::BindOnce( - std::move(pending_registration.on_registration_complete_callback_), - FixedChannelManager::RegistrationResult::SUCCESS, std::move(user_service))); - } -} - -void FixedChannelServiceManagerImpl::Unregister( - Cid cid, FixedChannelService::OnUnregisteredCallback callback, os::Handler* handler) { - if (IsServiceRegistered(cid)) { - service_map_.erase(cid); - handler->Post(std::move(callback)); - } else { - log::error("service not registered cid:{}", cid); - } -} - -bool FixedChannelServiceManagerImpl::IsServiceRegistered(Cid cid) const { - return service_map_.find(cid) != service_map_.end(); -} - -FixedChannelServiceImpl* FixedChannelServiceManagerImpl::GetService(Cid cid) { - log::assert_that(IsServiceRegistered(cid), "assert failed: IsServiceRegistered(cid)"); - return &service_map_.find(cid)->second; -} - -std::vector<std::pair<Cid, FixedChannelServiceImpl*>> -FixedChannelServiceManagerImpl::GetRegisteredServices() { - std::vector<std::pair<Cid, FixedChannelServiceImpl*>> results; - for (auto& elem : service_map_) { - results.emplace_back(elem.first, &elem.second); - } - return results; -} - -namespace { -constexpr uint64_t kSignallingChannelMask = 0x02; -constexpr uint64_t kConnectionlessReceptionMask = 0x04; -constexpr uint64_t kBrEdrSecurityManager = 0x80; -} // namespace - -uint64_t FixedChannelServiceManagerImpl::GetSupportedFixedChannelMask() { - uint64_t result = 0; - result |= kSignallingChannelMask; // Signalling channel is mandatory - for (const auto& elem : service_map_) { - Cid cid = elem.first; - switch (cid) { - case kConnectionlessCid: - result |= kConnectionlessReceptionMask; - continue; - case kSmpBrCid: - result |= kBrEdrSecurityManager; - continue; - default: - log::warn("Unknown fixed channel is registered: 0x{:x}", cid); - continue; - } - } - return result; -} -} // namespace internal -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/internal/fixed_channel_service_manager_impl.h b/system/gd/l2cap/classic/internal/fixed_channel_service_manager_impl.h deleted file mode 100644 index 24edbcf2c1..0000000000 --- a/system/gd/l2cap/classic/internal/fixed_channel_service_manager_impl.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <unordered_map> - -#include "l2cap/cid.h" -#include "l2cap/classic/fixed_channel_service.h" -#include "l2cap/classic/internal/fixed_channel_service_impl.h" -#include "os/handler.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace internal { - -class FixedChannelServiceManagerImpl { -public: - explicit FixedChannelServiceManagerImpl(os::Handler* l2cap_layer_handler) - : l2cap_layer_handler_(l2cap_layer_handler) {} - virtual ~FixedChannelServiceManagerImpl() = default; - - // All APIs must be invoked in L2CAP layer handler - - virtual void Register(Cid cid, FixedChannelServiceImpl::PendingRegistration pending_registration); - virtual void Unregister(Cid cid, FixedChannelService::OnUnregisteredCallback callback, - os::Handler* handler); - virtual bool IsServiceRegistered(Cid cid) const; - virtual FixedChannelServiceImpl* GetService(Cid cid); - virtual std::vector<std::pair<Cid, FixedChannelServiceImpl*>> GetRegisteredServices(); - virtual uint64_t GetSupportedFixedChannelMask(); - -private: - os::Handler* l2cap_layer_handler_ = nullptr; - std::unordered_map<Cid, FixedChannelServiceImpl> service_map_; -}; -} // namespace internal -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/internal/fixed_channel_service_manager_impl_mock.h b/system/gd/l2cap/classic/internal/fixed_channel_service_manager_impl_mock.h deleted file mode 100644 index 49acdf6157..0000000000 --- a/system/gd/l2cap/classic/internal/fixed_channel_service_manager_impl_mock.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2019 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. - */ -#pragma once - -#include <gmock/gmock.h> - -#include "l2cap/classic/internal/fixed_channel_impl.h" -#include "l2cap/classic/internal/fixed_channel_service_manager_impl.h" - -// Unit test interfaces -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace internal { -namespace testing { - -class MockFixedChannelServiceManagerImpl : public FixedChannelServiceManagerImpl { -public: - MockFixedChannelServiceManagerImpl() : FixedChannelServiceManagerImpl(nullptr) {} - MOCK_METHOD(void, Register, - (Cid cid, FixedChannelServiceImpl::PendingRegistration pending_registration), - (override)); - MOCK_METHOD(void, Unregister, - (Cid cid, FixedChannelService::OnUnregisteredCallback callback, os::Handler* handler), - (override)); - MOCK_METHOD(bool, IsServiceRegistered, (Cid cid), (const, override)); - MOCK_METHOD(FixedChannelServiceImpl*, GetService, (Cid cid), (override)); - MOCK_METHOD((std::vector<std::pair<Cid, FixedChannelServiceImpl*>>), GetRegisteredServices, (), - (override)); -}; - -} // namespace testing -} // namespace internal -} // namespace classic -} // namespace l2cap -} // namespace bluetooth
\ No newline at end of file diff --git a/system/gd/l2cap/classic/internal/fixed_channel_service_manager_test.cc b/system/gd/l2cap/classic/internal/fixed_channel_service_manager_test.cc deleted file mode 100644 index ea1dc1227a..0000000000 --- a/system/gd/l2cap/classic/internal/fixed_channel_service_manager_test.cc +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2018 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 <future> - -#include "common/bind.h" -#include "l2cap/cid.h" -#include "l2cap/classic/fixed_channel_manager.h" -#include "l2cap/classic/fixed_channel_service.h" -#include "l2cap/classic/internal/fixed_channel_service_manager_impl.h" -#include "os/handler.h" -#include "os/thread.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace internal { - -class L2capClassicFixedServiceManagerTest : public ::testing::Test { -public: - ~L2capClassicFixedServiceManagerTest() = default; - - void OnServiceRegistered(bool expect_success, FixedChannelManager::RegistrationResult result, - std::unique_ptr<FixedChannelService> user_service) { - EXPECT_EQ(result == FixedChannelManager::RegistrationResult::SUCCESS, expect_success); - service_registered_ = expect_success; - } - -protected: - void SetUp() override { - manager_ = new FixedChannelServiceManagerImpl{nullptr}; - thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL); - user_handler_ = new os::Handler(thread_); - } - - void TearDown() override { - user_handler_->Clear(); - delete user_handler_; - delete thread_; - delete manager_; - } - - void sync_user_handler() { - std::promise<void> promise; - auto future = promise.get_future(); - user_handler_->Post( - common::BindOnce(&std::promise<void>::set_value, common::Unretained(&promise))); - future.wait_for(std::chrono::milliseconds(3)); - } - - FixedChannelServiceManagerImpl* manager_ = nullptr; - os::Thread* thread_ = nullptr; - os::Handler* user_handler_ = nullptr; - - bool service_registered_ = false; -}; - -TEST_F(L2capClassicFixedServiceManagerTest, register_and_unregister_classic_fixed_channel) { - FixedChannelServiceImpl::PendingRegistration pending_registration{ - .user_handler_ = user_handler_, - .on_registration_complete_callback_ = - common::BindOnce(&L2capClassicFixedServiceManagerTest::OnServiceRegistered, - common::Unretained(this), true)}; - Cid cid = kSmpBrCid; - EXPECT_FALSE(manager_->IsServiceRegistered(cid)); - manager_->Register(cid, std::move(pending_registration)); - EXPECT_TRUE(manager_->IsServiceRegistered(cid)); - sync_user_handler(); - EXPECT_TRUE(service_registered_); - manager_->Unregister(cid, common::BindOnce([] {}), user_handler_); - EXPECT_FALSE(manager_->IsServiceRegistered(cid)); -} - -TEST_F(L2capClassicFixedServiceManagerTest, register_classic_fixed_channel_bad_cid) { - FixedChannelServiceImpl::PendingRegistration pending_registration{ - .user_handler_ = user_handler_, - .on_registration_complete_callback_ = - common::BindOnce(&L2capClassicFixedServiceManagerTest::OnServiceRegistered, - common::Unretained(this), false)}; - Cid cid = 0x1000; - EXPECT_FALSE(manager_->IsServiceRegistered(cid)); - manager_->Register(cid, std::move(pending_registration)); - EXPECT_FALSE(manager_->IsServiceRegistered(cid)); - sync_user_handler(); - EXPECT_FALSE(service_registered_); -} - -} // namespace internal -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/internal/link.cc b/system/gd/l2cap/classic/internal/link.cc deleted file mode 100644 index 1171155857..0000000000 --- a/system/gd/l2cap/classic/internal/link.cc +++ /dev/null @@ -1,443 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/classic/internal/link.h" - -#include <bluetooth/log.h> - -#include <chrono> -#include <memory> - -#include "common/bind.h" -#include "hci/acl_manager/classic_acl_connection.h" -#include "l2cap/classic/dynamic_channel_manager.h" -#include "l2cap/classic/internal/fixed_channel_impl.h" -#include "l2cap/classic/internal/link_manager.h" -#include "l2cap/internal/parameter_provider.h" -#include "os/alarm.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace internal { - -using RetransmissionAndFlowControlMode = - DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode; -using ConnectionResult = DynamicChannelManager::ConnectionResult; -using ConnectionResultCode = DynamicChannelManager::ConnectionResultCode; - -Link::Link(os::Handler* l2cap_handler, - std::unique_ptr<hci::acl_manager::ClassicAclConnection> acl_connection, - l2cap::internal::ParameterProvider* parameter_provider, - DynamicChannelServiceManagerImpl* dynamic_service_manager, - FixedChannelServiceManagerImpl* fixed_service_manager, LinkManager* link_manager) - : l2cap_handler_(l2cap_handler), - acl_connection_(std::move(acl_connection)), - data_pipeline_manager_(l2cap_handler, this, acl_connection_->GetAclQueueEnd()), - parameter_provider_(parameter_provider), - dynamic_service_manager_(dynamic_service_manager), - fixed_service_manager_(fixed_service_manager), - link_manager_(link_manager), - signalling_manager_(l2cap_handler_, this, &data_pipeline_manager_, dynamic_service_manager_, - &dynamic_channel_allocator_, fixed_service_manager_), - acl_handle_(acl_connection_->GetHandle()) { - log::assert_that(l2cap_handler_ != nullptr, "assert failed: l2cap_handler_ != nullptr"); - log::assert_that(acl_connection_ != nullptr, "assert failed: acl_connection_ != nullptr"); - log::assert_that(parameter_provider_ != nullptr, "assert failed: parameter_provider_ != nullptr"); - link_idle_disconnect_alarm_.Schedule( - common::BindOnce(&Link::Disconnect, common::Unretained(this)), - parameter_provider_->GetClassicLinkIdleDisconnectTimeout()); - acl_connection_->RegisterCallbacks(this, l2cap_handler_); -} - -void Link::OnAclDisconnected(hci::ErrorCode status) { - signalling_manager_.CancelAlarm(); - fixed_channel_allocator_.OnAclDisconnected(status); - dynamic_channel_allocator_.OnAclDisconnected(status); - ConnectionResult result{ - .connection_result_code = ConnectionResultCode::FAIL_HCI_ERROR, - .hci_error = status, - .l2cap_connection_response_result = ConnectionResponseResult::SUCCESS, - }; - while (!local_cid_to_pending_dynamic_channel_connection_map_.empty()) { - auto entry = local_cid_to_pending_dynamic_channel_connection_map_.begin(); - NotifyChannelFail(entry->first, result); - } -} - -void Link::Disconnect() { - acl_connection_->Disconnect(hci::DisconnectReason::REMOTE_USER_TERMINATED_CONNECTION); -} - -void Link::Encrypt() { - if (encryption_enabled_ == hci::EncryptionEnabled::OFF) { - acl_connection_->SetConnectionEncryption(hci::Enable::ENABLED); - } -} - -void Link::Authenticate() { - if (!IsAuthenticated() && !has_requested_authentication_) { - has_requested_authentication_ = true; - acl_connection_->AuthenticationRequested(); - } -} - -bool Link::IsAuthenticated() const { return encryption_enabled_ != hci::EncryptionEnabled::OFF; } - -void Link::ReadRemoteVersionInformation() { acl_connection_->ReadRemoteVersionInformation(); } - -void Link::ReadRemoteSupportedFeatures() { acl_connection_->ReadRemoteSupportedFeatures(); } - -void Link::ReadRemoteExtendedFeatures(uint8_t page_number) { - acl_connection_->ReadRemoteExtendedFeatures(page_number); -} - -void Link::ReadClockOffset() { acl_connection_->ReadClockOffset(); } - -void Link::AcquireSecurityHold() { - used_by_security_module_ = true; - RefreshRefCount(); -} -void Link::ReleaseSecurityHold() { - used_by_security_module_ = false; - RefreshRefCount(); -} - -std::shared_ptr<FixedChannelImpl> Link::AllocateFixedChannel(Cid cid) { - auto channel = fixed_channel_allocator_.AllocateChannel(cid); - data_pipeline_manager_.AttachChannel(cid, channel, - l2cap::internal::DataPipelineManager::ChannelMode::BASIC); - return channel; -} - -bool Link::IsFixedChannelAllocated(Cid cid) { - return fixed_channel_allocator_.IsChannelAllocated(cid); -} - -Cid Link::ReserveDynamicChannel() { return dynamic_channel_allocator_.ReserveChannel(); } - -void Link::SendConnectionRequest(Psm psm, Cid local_cid) { - signalling_manager_.SendConnectionRequest(psm, local_cid); -} - -void Link::SendConnectionRequest( - Psm psm, Cid local_cid, - PendingDynamicChannelConnection pending_dynamic_channel_connection) { - if (pending_dynamic_channel_connection.configuration_.channel_mode == - RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION && - !remote_extended_feature_received_) { - pending_dynamic_psm_list_.push_back(psm); - pending_dynamic_channel_callback_list_.push_back(std::move(pending_dynamic_channel_connection)); - log::info("Will connect after information response ERTM feature support is received"); - dynamic_channel_allocator_.FreeChannel(local_cid); - return; - } else if (pending_dynamic_channel_connection.configuration_.channel_mode == - RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION && - !GetRemoteSupportsErtm()) { - log::warn("Remote doesn't support ERTM. Dropping connection request"); - ConnectionResult result{ - .connection_result_code = ConnectionResultCode::FAIL_REMOTE_NOT_SUPPORT, - }; - pending_dynamic_channel_connection.on_fail_callback_(result); - dynamic_channel_allocator_.FreeChannel(local_cid); - return; - } else { - local_cid_to_pending_dynamic_channel_connection_map_[local_cid] = - std::move(pending_dynamic_channel_connection); - signalling_manager_.SendConnectionRequest(psm, local_cid); - } -} - -void Link::SetChannelTxPriority(Cid local_cid, bool high_priority) { - data_pipeline_manager_.SetChannelTxPriority(local_cid, high_priority); -} - -void Link::SetPendingDynamicChannels( - std::list<Psm> psm_list, std::list<Link::PendingDynamicChannelConnection> callback_list) { - log::assert_that(psm_list.size() == callback_list.size(), - "assert failed: psm_list.size() == callback_list.size()"); - pending_dynamic_psm_list_ = std::move(psm_list); - pending_dynamic_channel_callback_list_ = std::move(callback_list); -} - -void Link::connect_to_pending_dynamic_channels() { - auto psm = pending_dynamic_psm_list_.begin(); - auto callback = pending_dynamic_channel_callback_list_.begin(); - while (psm != pending_dynamic_psm_list_.end()) { - SendConnectionRequest(*psm, ReserveDynamicChannel(), std::move(*callback)); - psm++; - callback++; - } -} - -void Link::send_pending_configuration_requests() { - for (auto local_cid : pending_outgoing_configuration_request_list_) { - signalling_manager_.SendInitialConfigRequest(local_cid); - } - pending_outgoing_configuration_request_list_.clear(); -} - -void Link::OnOutgoingConnectionRequestFail(Cid local_cid, ConnectionResult result) { - if (local_cid_to_pending_dynamic_channel_connection_map_.find(local_cid) != - local_cid_to_pending_dynamic_channel_connection_map_.end()) { - NotifyChannelFail(local_cid, result); - } - dynamic_channel_allocator_.FreeChannel(local_cid); -} - -void Link::SendInitialConfigRequestOrQueue(Cid local_cid) { - if (remote_extended_feature_received_) { - signalling_manager_.SendInitialConfigRequest(local_cid); - } else { - pending_outgoing_configuration_request_list_.push_back(local_cid); - } -} - -void Link::SendDisconnectionRequest(Cid local_cid, Cid remote_cid) { - signalling_manager_.SendDisconnectionRequest(local_cid, remote_cid); -} - -void Link::SendInformationRequest(InformationRequestInfoType type) { - signalling_manager_.SendInformationRequest(type); -} - -std::shared_ptr<l2cap::internal::DynamicChannelImpl> Link::AllocateDynamicChannel(Psm psm, - Cid remote_cid) { - auto channel = dynamic_channel_allocator_.AllocateChannel(psm, remote_cid); - if (channel != nullptr) { - RefreshRefCount(); - channel->local_initiated_ = false; - } - return channel; -} - -std::shared_ptr<l2cap::internal::DynamicChannelImpl> Link::AllocateReservedDynamicChannel( - Cid reserved_cid, Psm psm, Cid remote_cid) { - auto channel = dynamic_channel_allocator_.AllocateReservedChannel(reserved_cid, psm, remote_cid); - if (channel != nullptr) { - RefreshRefCount(); - } - channel->local_initiated_ = true; - return channel; -} - -classic::DynamicChannelConfigurationOption Link::GetConfigurationForInitialConfiguration(Cid cid) { - log::assert_that( - local_cid_to_pending_dynamic_channel_connection_map_.find(cid) != - local_cid_to_pending_dynamic_channel_connection_map_.end(), - "assert failed: local_cid_to_pending_dynamic_channel_connection_map_.find(cid) != " - "local_cid_to_pending_dynamic_channel_connection_map_.end()"); - return local_cid_to_pending_dynamic_channel_connection_map_[cid].configuration_; -} - -void Link::FreeDynamicChannel(Cid cid) { - if (dynamic_channel_allocator_.FindChannelByCid(cid) == nullptr) { - return; - } - dynamic_channel_allocator_.FreeChannel(cid); - RefreshRefCount(); -} - -void Link::RefreshRefCount() { - int ref_count = 0; - ref_count += fixed_channel_allocator_.GetRefCount(); - ref_count += dynamic_channel_allocator_.NumberOfChannels(); - if (used_by_security_module_) { - ref_count += 1; - } - log::assert_that(ref_count >= 0, "ref_count {} is less than 0", ref_count); - if (ref_count > 0) { - link_idle_disconnect_alarm_.Cancel(); - } else { - link_idle_disconnect_alarm_.Schedule( - common::BindOnce(&Link::Disconnect, common::Unretained(this)), - parameter_provider_->GetClassicLinkIdleDisconnectTimeout()); - } -} - -void Link::NotifyChannelCreation(Cid cid, std::unique_ptr<DynamicChannel> user_channel) { - log::assert_that( - local_cid_to_pending_dynamic_channel_connection_map_.find(cid) != - local_cid_to_pending_dynamic_channel_connection_map_.end(), - "assert failed: local_cid_to_pending_dynamic_channel_connection_map_.find(cid) != " - "local_cid_to_pending_dynamic_channel_connection_map_.end()"); - auto& pending_dynamic_channel_connection = - local_cid_to_pending_dynamic_channel_connection_map_[cid]; - pending_dynamic_channel_connection.on_open_callback_(std::move(user_channel)); - local_cid_to_pending_dynamic_channel_connection_map_.erase(cid); -} - -void Link::NotifyChannelFail(Cid cid, ConnectionResult result) { - log::assert_that( - local_cid_to_pending_dynamic_channel_connection_map_.find(cid) != - local_cid_to_pending_dynamic_channel_connection_map_.end(), - "assert failed: local_cid_to_pending_dynamic_channel_connection_map_.find(cid) != " - "local_cid_to_pending_dynamic_channel_connection_map_.end()"); - auto& pending_dynamic_channel_connection = - local_cid_to_pending_dynamic_channel_connection_map_[cid]; - pending_dynamic_channel_connection.on_fail_callback_(result); - local_cid_to_pending_dynamic_channel_connection_map_.erase(cid); -} - -void Link::SetRemoteConnectionlessMtu(Mtu mtu) { remote_connectionless_mtu_ = mtu; } - -Mtu Link::GetRemoteConnectionlessMtu() const { return remote_connectionless_mtu_; } - -bool Link::GetRemoteSupportsErtm() const { return remote_supports_ertm_; } - -bool Link::GetRemoteSupportsFcs() const { return remote_supports_fcs_; } - -void Link::OnRemoteExtendedFeatureReceived(bool ertm_supported, bool fcs_supported) { - remote_supports_ertm_ = ertm_supported; - remote_supports_fcs_ = fcs_supported; - remote_extended_feature_received_ = true; - connect_to_pending_dynamic_channels(); - send_pending_configuration_requests(); -} - -void Link::OnConnectionPacketTypeChanged(uint16_t packet_type) { - log::info("UNIMPLEMENTED packet_type:{:x}", packet_type); -} - -void Link::OnAuthenticationComplete(hci::ErrorCode hci_status) { - link_manager_->OnAuthenticationComplete(hci_status, GetDevice().GetAddress()); -} - -void Link::OnEncryptionChange(hci::EncryptionEnabled enabled) { - encryption_enabled_ = enabled; - link_manager_->OnEncryptionChange(GetDevice().GetAddress(), enabled); - for (auto& listener : encryption_change_listener_) { - signalling_manager_.on_security_result_for_outgoing( - ClassicSignallingManager::SecurityEnforcementType::ENCRYPTION, listener.psm, - listener.cid, enabled != hci::EncryptionEnabled::OFF); - } -} - -void Link::OnChangeConnectionLinkKeyComplete() { log::info("UNIMPLEMENTED"); } - -void Link::OnReadClockOffsetComplete(uint16_t clock_offset) { - link_manager_->OnReadClockOffset(GetDevice().GetAddress(), clock_offset); -} - -void Link::OnModeChange(hci::ErrorCode status, hci::Mode current_mode, uint16_t interval) { - link_manager_->OnModeChange(status, GetDevice().GetAddress(), current_mode, interval); -} - -void Link::OnSniffSubrating(hci::ErrorCode hci_status, uint16_t maximum_transmit_latency, - uint16_t maximum_receive_latency, uint16_t minimum_remote_timeout, - uint16_t minimum_local_timeout) { - link_manager_->OnSniffSubrating(hci_status, GetDevice().GetAddress(), maximum_transmit_latency, - maximum_receive_latency, minimum_remote_timeout, - minimum_local_timeout); -} - -void Link::OnQosSetupComplete(hci::ServiceType service_type, uint32_t token_rate, - uint32_t peak_bandwidth, uint32_t latency, uint32_t delay_variation) { - log::info( - "UNIMPLEMENTED service_type:{} token_rate:{} peak_bandwidth:{} latency:{} " - "delay_varitation:{}", - hci::ServiceTypeText(service_type), token_rate, peak_bandwidth, latency, delay_variation); -} -void Link::OnFlowSpecificationComplete(hci::FlowDirection flow_direction, - hci::ServiceType service_type, uint32_t token_rate, - uint32_t token_bucket_size, uint32_t peak_bandwidth, - uint32_t access_latency) { - log::info( - "UNIMPLEMENTED flow_direction:{} service_type:{} token_rate:{} token_bucket_size:{} " - "peak_bandwidth:{} access_latency:{}", - hci::FlowDirectionText(flow_direction), hci::ServiceTypeText(service_type), token_rate, - token_bucket_size, peak_bandwidth, access_latency); -} -void Link::OnFlushOccurred() { log::info("UNIMPLEMENTED"); } -void Link::OnRoleDiscoveryComplete(hci::Role current_role) { role_ = current_role; } -void Link::OnReadLinkPolicySettingsComplete(uint16_t link_policy_settings) { - log::info("UNIMPLEMENTED link_policy_settings:0x{:x}", link_policy_settings); -} -void Link::OnReadAutomaticFlushTimeoutComplete(uint16_t flush_timeout) { - log::info("UNIMPLEMENTED flush_timeout:{}", flush_timeout); -} -void Link::OnReadTransmitPowerLevelComplete(uint8_t transmit_power_level) { - log::info("UNIMPLEMENTED transmit_power_level:{}", transmit_power_level); -} -void Link::OnReadLinkSupervisionTimeoutComplete(uint16_t link_supervision_timeout) { - log::info("UNIMPLEMENTED link_supervision_timeout:{}", link_supervision_timeout); -} -void Link::OnReadFailedContactCounterComplete(uint16_t failed_contact_counter) { - log::info("UNIMPLEMENTED failed_contact_counter:{}", failed_contact_counter); -} -void Link::OnReadLinkQualityComplete(uint8_t link_quality) { - log::info("UNIMPLEMENTED link_quality:{}", link_quality); -} -void Link::OnReadAfhChannelMapComplete(hci::AfhMode afh_mode, - std::array<uint8_t, 10> /* afh_channel_map */) { - log::info("UNIMPLEMENTED afh_mode:{}", hci::AfhModeText(afh_mode)); -} -void Link::OnReadRssiComplete(uint8_t rssi) { log::info("UNIMPLEMENTED rssi:{}", rssi); } -void Link::OnReadClockComplete(uint32_t clock, uint16_t accuracy) { - log::info("UNIMPLEMENTED clock:{} accuracy:{}", clock, accuracy); -} -void Link::OnCentralLinkKeyComplete(hci::KeyFlag key_flag) { - log::info("UNIMPLEMENTED key_flag:{}", hci::KeyFlagText(key_flag)); -} -void Link::OnRoleChange(hci::ErrorCode hci_status, hci::Role new_role) { - role_ = new_role; - link_manager_->OnRoleChange(hci_status, GetDevice().GetAddress(), new_role); -} -void Link::OnDisconnection(hci::ErrorCode reason) { - OnAclDisconnected(reason); - link_manager_->OnDisconnect(GetDevice().GetAddress(), reason); -} -void Link::OnReadRemoteVersionInformationComplete(hci::ErrorCode hci_status, uint8_t lmp_version, - uint16_t manufacturer_name, - uint16_t sub_version) { - log::info("UNIMPLEMENTED hci_status:{} lmp_version:{} manufacturer_name:{} sub_version:{}", - ErrorCodeText(hci_status), lmp_version, manufacturer_name, sub_version); - link_manager_->OnReadRemoteVersionInformation(hci_status, GetDevice().GetAddress(), lmp_version, - manufacturer_name, sub_version); -} -void Link::OnReadRemoteSupportedFeaturesComplete(uint64_t features) { - log::info("page_number:{} features:0x{:x}", static_cast<uint8_t>(0), - static_cast<unsigned long>(features)); - link_manager_->OnReadRemoteSupportedFeatures(GetDevice().GetAddress(), features); -} - -void Link::OnReadRemoteExtendedFeaturesComplete(uint8_t page_number, uint8_t max_page_number, - uint64_t features) { - log::info("page_number:{} max_page_number:{} features:0x{:x}", page_number, max_page_number, - static_cast<unsigned long>(features)); - link_manager_->OnReadRemoteExtendedFeatures(GetDevice().GetAddress(), page_number, - max_page_number, features); -} - -void Link::AddEncryptionChangeListener(EncryptionChangeListener listener) { - encryption_change_listener_.push_back(listener); -} - -void Link::OnPendingPacketChange(Cid /* local_cid */, bool has_packet) { - if (has_packet) { - remaining_packets_to_be_sent_++; - } else { - remaining_packets_to_be_sent_--; - } - if (link_manager_ != nullptr) { - link_manager_->OnPendingPacketChange(GetDevice().GetAddress(), remaining_packets_to_be_sent_); - } -} - -} // namespace internal -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/internal/link.h b/system/gd/l2cap/classic/internal/link.h deleted file mode 100644 index 5077eb7b89..0000000000 --- a/system/gd/l2cap/classic/internal/link.h +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <atomic> -#include <memory> -#include <unordered_map> - -#include "common/interfaces/ILoggable.h" -#include "hci/acl_manager/classic_acl_connection.h" -#include "l2cap/classic/dynamic_channel_configuration_option.h" -#include "l2cap/classic/internal/dynamic_channel_service_manager_impl.h" -#include "l2cap/classic/internal/fixed_channel_impl.h" -#include "l2cap/classic/internal/fixed_channel_service_manager_impl.h" -#include "l2cap/classic/security_enforcement_interface.h" -#include "l2cap/internal/data_pipeline_manager.h" -#include "l2cap/internal/dynamic_channel_allocator.h" -#include "l2cap/internal/dynamic_channel_impl.h" -#include "l2cap/internal/fixed_channel_allocator.h" -#include "l2cap/internal/ilink.h" -#include "l2cap/internal/parameter_provider.h" -#include "os/alarm.h" -#include "os/handler.h" -#include "signalling_manager.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace internal { - -class LinkManager; -class DumpsysHelper; - -class Link : public l2cap::internal::ILink, - public hci::acl_manager::ConnectionManagementCallbacks, - public bluetooth::common::IRedactableLoggable { -public: - Link(os::Handler* l2cap_handler, - std::unique_ptr<hci::acl_manager::ClassicAclConnection> acl_connection, - l2cap::internal::ParameterProvider* parameter_provider, - DynamicChannelServiceManagerImpl* dynamic_service_manager, - FixedChannelServiceManagerImpl* fixed_service_manager, LinkManager* link_manager); - - Link(const Link&) = delete; - Link& operator=(const Link&) = delete; - - hci::AddressWithType GetDevice() const override { - return {acl_connection_->GetAddress(), hci::AddressType::PUBLIC_DEVICE_ADDRESS}; - } - - struct PendingDynamicChannelConnection { - os::Handler* handler_; - DynamicChannelManager::OnConnectionOpenCallback on_open_callback_; - DynamicChannelManager::OnConnectionFailureCallback on_fail_callback_; - classic::DynamicChannelConfigurationOption configuration_; - }; - - struct PendingAuthenticateDynamicChannelConnection { - Psm psm_; - Cid cid_; - PendingDynamicChannelConnection pending_dynamic_channel_connection_; - }; - - // ACL methods - - virtual void OnAclDisconnected(hci::ErrorCode status); - - virtual void Disconnect(); - - virtual void Encrypt(); - - virtual void Authenticate(); - - virtual bool IsAuthenticated() const; - - virtual void ReadRemoteVersionInformation(); - - virtual void ReadRemoteSupportedFeatures(); - - virtual void ReadRemoteExtendedFeatures(uint8_t page_number); - - virtual void ReadClockOffset(); - - // Increase the link usage refcount to ensure the link won't be disconnected when SecurityModule - // needs it - virtual void AcquireSecurityHold(); - - // Decrease the link usage refcount when SecurityModule no longer needs it - virtual void ReleaseSecurityHold(); - - // FixedChannel methods - - std::shared_ptr<FixedChannelImpl> AllocateFixedChannel(Cid cid); - - virtual bool IsFixedChannelAllocated(Cid cid); - - // DynamicChannel methods - - virtual Cid ReserveDynamicChannel(); - - virtual void SendConnectionRequest(Psm psm, Cid local_cid); - virtual void SendConnectionRequest( - Psm psm, Cid local_cid, - PendingDynamicChannelConnection pending_dynamic_channel_connection); - void SetChannelTxPriority(Cid local_cid, bool high_priority) override; - - // When a Link is established, LinkManager notifies pending dynamic channels to connect - virtual void SetPendingDynamicChannels( - std::list<Psm> psm_list, std::list<Link::PendingDynamicChannelConnection> callback_list); - - // Invoked by signalling manager to indicate an outgoing connection request failed and link shall - // free resources - virtual void OnOutgoingConnectionRequestFail(Cid local_cid, - DynamicChannelManager::ConnectionResult result); - - virtual void SendInitialConfigRequestOrQueue(Cid local_cid); - - virtual void SendInformationRequest(InformationRequestInfoType type); - - virtual void SendDisconnectionRequest(Cid local_cid, Cid remote_cid) override; - - virtual std::shared_ptr<l2cap::internal::DynamicChannelImpl> AllocateDynamicChannel( - Psm psm, Cid remote_cid); - - virtual std::shared_ptr<l2cap::internal::DynamicChannelImpl> AllocateReservedDynamicChannel( - Cid reserved_cid, Psm psm, Cid remote_cid); - - virtual classic::DynamicChannelConfigurationOption GetConfigurationForInitialConfiguration( - Cid cid); - - virtual void FreeDynamicChannel(Cid cid); - - // Check how many channels are acquired or in use, if zero, start tear down timer, if non-zero, - // cancel tear down timer - virtual void RefreshRefCount(); - - virtual void NotifyChannelCreation(Cid cid, std::unique_ptr<DynamicChannel> channel); - virtual void NotifyChannelFail(Cid cid, DynamicChannelManager::ConnectionResult result); - - // Information received from signaling channel - virtual void SetRemoteConnectionlessMtu(Mtu mtu); - virtual Mtu GetRemoteConnectionlessMtu() const; - virtual bool GetRemoteSupportsErtm() const; - virtual bool GetRemoteSupportsFcs() const; - virtual void OnRemoteExtendedFeatureReceived(bool ertm_supported, bool fcs_supported); - - virtual std::string ToString() const { return GetDevice().ToString(); } - - std::string ToStringForLogging() const override { return GetDevice().ToStringForLogging(); } - - std::string ToRedactedStringForLogging() const override { - return GetDevice().ToRedactedStringForLogging(); - } - - void SendLeCredit(Cid /* local_cid */, uint16_t /* credit */) override {} - - // ConnectionManagementCallbacks - void OnConnectionPacketTypeChanged(uint16_t packet_type) override; - void OnAuthenticationComplete(hci::ErrorCode hci_status) override; - void OnEncryptionChange(hci::EncryptionEnabled enabled) override; - void OnChangeConnectionLinkKeyComplete() override; - void OnReadClockOffsetComplete(uint16_t clock_offset) override; - void OnModeChange(hci::ErrorCode status, hci::Mode current_mode, uint16_t interval) override; - void OnSniffSubrating(hci::ErrorCode hci_status, uint16_t maximum_transmit_latency, - uint16_t maximum_receive_latency, uint16_t minimum_remote_timeout, - uint16_t minimum_local_timeout) override; - void OnQosSetupComplete(hci::ServiceType service_type, uint32_t token_rate, - uint32_t peak_bandwidth, uint32_t latency, - uint32_t delay_variation) override; - void OnFlowSpecificationComplete(hci::FlowDirection flow_direction, hci::ServiceType service_type, - uint32_t token_rate, uint32_t token_bucket_size, - uint32_t peak_bandwidth, uint32_t access_latency) override; - void OnFlushOccurred() override; - void OnRoleDiscoveryComplete(hci::Role current_role) override; - void OnReadLinkPolicySettingsComplete(uint16_t link_policy_settings) override; - void OnReadAutomaticFlushTimeoutComplete(uint16_t flush_timeout) override; - void OnReadTransmitPowerLevelComplete(uint8_t transmit_power_level) override; - void OnReadLinkSupervisionTimeoutComplete(uint16_t link_supervision_timeout) override; - void OnReadFailedContactCounterComplete(uint16_t failed_contact_counter) override; - void OnReadLinkQualityComplete(uint8_t link_quality) override; - void OnReadAfhChannelMapComplete(hci::AfhMode afh_mode, - std::array<uint8_t, 10> afh_channel_map) override; - void OnReadRssiComplete(uint8_t rssi) override; - void OnReadClockComplete(uint32_t clock, uint16_t accuracy) override; - void OnCentralLinkKeyComplete(hci::KeyFlag key_flag) override; - void OnRoleChange(hci::ErrorCode hci_status, hci::Role new_role) override; - void OnDisconnection(hci::ErrorCode reason) override; - void OnReadRemoteVersionInformationComplete(hci::ErrorCode hci_status, uint8_t lmp_version, - uint16_t manufacturer_name, uint16_t sub_version); - void OnReadRemoteSupportedFeaturesComplete(uint64_t features); - void OnReadRemoteExtendedFeaturesComplete(uint8_t page_number, uint8_t max_page_number, - uint64_t features); - - struct EncryptionChangeListener { - Cid cid; - Psm psm; - }; - void AddEncryptionChangeListener(EncryptionChangeListener); - - uint16_t GetAclHandle() const { return acl_handle_; } - - hci::Role GetRole() const { return role_; } - - void OnPendingPacketChange(Cid local_cid, bool has_packet) override; - -private: - friend class DumpsysHelper; - void connect_to_pending_dynamic_channels(); - void send_pending_configuration_requests(); - - os::Handler* l2cap_handler_; - l2cap::internal::FixedChannelAllocator<FixedChannelImpl, Link> fixed_channel_allocator_{ - this, l2cap_handler_}; - l2cap::internal::DynamicChannelAllocator dynamic_channel_allocator_{this, l2cap_handler_}; - std::unique_ptr<hci::acl_manager::ClassicAclConnection> acl_connection_; - l2cap::internal::DataPipelineManager data_pipeline_manager_; - l2cap::internal::ParameterProvider* parameter_provider_; - DynamicChannelServiceManagerImpl* dynamic_service_manager_; - FixedChannelServiceManagerImpl* fixed_service_manager_; - LinkManager* link_manager_; - std::unordered_map<Cid, PendingDynamicChannelConnection> - local_cid_to_pending_dynamic_channel_connection_map_; - os::Alarm link_idle_disconnect_alarm_{l2cap_handler_}; - ClassicSignallingManager signalling_manager_; - uint16_t acl_handle_; - Mtu remote_connectionless_mtu_ = kMinimumClassicMtu; - hci::Role role_ = hci::Role::CENTRAL; - bool remote_extended_feature_received_ = false; - bool remote_supports_ertm_ = false; - bool remote_supports_fcs_ = false; - hci::EncryptionEnabled encryption_enabled_ = hci::EncryptionEnabled::OFF; - std::list<Psm> pending_dynamic_psm_list_; - std::list<Link::PendingDynamicChannelConnection> pending_dynamic_channel_callback_list_; - std::list<uint16_t> pending_outgoing_configuration_request_list_; - bool used_by_security_module_ = false; - bool has_requested_authentication_ = false; - std::list<EncryptionChangeListener> encryption_change_listener_; - std::atomic_int remaining_packets_to_be_sent_ = 0; -}; - -} // namespace internal -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/internal/link_manager.cc b/system/gd/l2cap/classic/internal/link_manager.cc deleted file mode 100644 index 967598eed7..0000000000 --- a/system/gd/l2cap/classic/internal/link_manager.cc +++ /dev/null @@ -1,437 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/classic/internal/link_manager.h" - -#include <bluetooth/log.h> - -#include <memory> -#include <unordered_map> - -#include "hci/acl_manager/classic_acl_connection.h" -#include "hci/address.h" -#include "hci/class_of_device.h" -#include "l2cap/classic/internal/link.h" -#include "l2cap/internal/scheduler_fifo.h" -#include "os/log.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace internal { - -void LinkManager::ConnectFixedChannelServices( - hci::Address device, PendingFixedChannelConnection pending_fixed_channel_connection) { - // Check if there is any service registered - auto fixed_channel_services = fixed_channel_service_manager_->GetRegisteredServices(); - if (fixed_channel_services.empty()) { - // If so, return error - pending_fixed_channel_connection.handler_->Post( - common::BindOnce(std::move(pending_fixed_channel_connection.on_fail_callback_), - FixedChannelManager::ConnectionResult{ - .connection_result_code = FixedChannelManager:: - ConnectionResultCode::FAIL_NO_SERVICE_REGISTERED})); - return; - } - // Otherwise, check if device has an ACL connection - auto* link = GetLink(device); - if (link != nullptr) { - // If device already have an ACL connection - // Check if all registered services have an allocated channel and allocate one if not already - // allocated - int num_new_channels = 0; - for (auto& fixed_channel_service : fixed_channel_services) { - if (link->IsFixedChannelAllocated(fixed_channel_service.first)) { - // This channel is already allocated for this link, do not allocated twice - continue; - } - // Allocate channel for newly registered fixed channels - auto fixed_channel_impl = link->AllocateFixedChannel(fixed_channel_service.first); - fixed_channel_service.second->NotifyChannelCreation( - std::make_unique<FixedChannel>(fixed_channel_impl, l2cap_handler_)); - num_new_channels++; - } - // Declare connection failure if no new channels are created - if (num_new_channels == 0) { - pending_fixed_channel_connection.handler_->Post(common::BindOnce( - std::move(pending_fixed_channel_connection.on_fail_callback_), - FixedChannelManager::ConnectionResult{ - .connection_result_code = FixedChannelManager::ConnectionResultCode:: - FAIL_ALL_SERVICES_HAVE_CHANNEL})); - } - // No need to create ACL connection, return without saving any pending connections - return; - } - // If not, create new ACL connection - // Add request to pending link list first - auto pending_link = pending_links_.find(device); - if (pending_link == pending_links_.end()) { - // Create pending link if not exist - pending_links_.try_emplace(device); - pending_link = pending_links_.find(device); - } - pending_link->second.pending_fixed_channel_connections_.push_back( - std::move(pending_fixed_channel_connection)); - // Then create new ACL connection - acl_manager_->CreateConnection(device); -} - -void LinkManager::ConnectDynamicChannelServices( - hci::Address device, - Link::PendingDynamicChannelConnection pending_dynamic_channel_connection, Psm psm) { - if (!IsPsmValid(psm)) { - return; - } - auto* link = GetLink(device); - if (link == nullptr) { - acl_manager_->CreateConnection(device); - if (pending_dynamic_channels_.find(device) != pending_dynamic_channels_.end()) { - pending_dynamic_channels_[device].push_back(psm); - pending_dynamic_channels_callbacks_[device].push_back( - std::move(pending_dynamic_channel_connection)); - } else { - pending_dynamic_channels_[device] = {psm}; - pending_dynamic_channels_callbacks_[device].push_back( - std::move(pending_dynamic_channel_connection)); - } - return; - } - link->SendConnectionRequest(psm, link->ReserveDynamicChannel(), - std::move(pending_dynamic_channel_connection)); -} - -void LinkManager::InitiateConnectionForSecurity(hci::Address remote) { - auto* link = GetLink(remote); - if (link != nullptr) { - log::error("Link already exists for {}", remote); - } - acl_manager_->CreateConnection(remote); -} - -void LinkManager::RegisterLinkSecurityInterfaceListener(os::Handler* handler, - LinkSecurityInterfaceListener* listener) { - link_security_interface_listener_handler_ = handler; - link_security_interface_listener_ = listener; -} - -LinkSecurityInterfaceListener* LinkManager::GetLinkSecurityInterfaceListener() { - return link_security_interface_listener_; -} - -void LinkManager::RegisterLinkPropertyListener(os::Handler* handler, - LinkPropertyListener* listener) { - link_property_callback_handler_ = handler; - link_property_listener_ = listener; -} - -void LinkManager::OnPendingPacketChange(hci::Address remote, int num_packets) { - if (disconnected_links_.count(remote) != 0 && num_packets == 0) { - links_.erase(remote); - links_with_pending_packets_.erase(remote); - } else if (num_packets != 0) { - links_with_pending_packets_.emplace(remote); - } else { - links_with_pending_packets_.erase(remote); - } -} - -Link* LinkManager::GetLink(const hci::Address device) { - if (links_.find(device) == links_.end()) { - return nullptr; - } - return &links_.find(device)->second; -} - -void LinkManager::handle_link_security_hold(hci::Address remote) { - auto link = GetLink(remote); - if (link == nullptr) { - log::warn("Remote is disconnected"); - return; - } - link->AcquireSecurityHold(); -} - -void LinkManager::handle_link_security_release(hci::Address remote) { - auto link = GetLink(remote); - if (link == nullptr) { - log::warn("Remote is disconnected"); - return; - } - link->ReleaseSecurityHold(); -} - -void LinkManager::handle_link_security_disconnect(hci::Address remote) { - auto link = GetLink(remote); - if (link == nullptr) { - log::warn("Remote is disconnected"); - return; - } - link->Disconnect(); -} - -void LinkManager::handle_link_security_ensure_authenticated(hci::Address remote) { - auto link = GetLink(remote); - if (link == nullptr) { - log::warn("Remote is disconnected"); - return; - } - link->Authenticate(); -} - -void LinkManager::handle_link_security_ensure_encrypted(hci::Address remote) { - auto link = GetLink(remote); - if (link == nullptr) { - log::warn("Remote is disconnected"); - return; - } - link->Encrypt(); -} - -/** - * The implementation for LinkSecurityInterface, which allows the SecurityModule to access some link - * functionalities. Note: All public methods implementing this interface are invoked from external - * context. - */ -class LinkSecurityInterfaceImpl : public LinkSecurityInterface { -public: - LinkSecurityInterfaceImpl(os::Handler* handler, LinkManager* link_manager, Link* link) - : handler_(handler), - link_manager_(link_manager), - remote_(link->GetDevice().GetAddress()), - acl_handle_(link->GetAclHandle()) {} - - hci::Address GetRemoteAddress() override { return remote_; } - - void Hold() override { - handler_->CallOn(link_manager_, &LinkManager::handle_link_security_hold, remote_); - } - - void Release() override { - handler_->CallOn(link_manager_, &LinkManager::handle_link_security_release, remote_); - } - - void Disconnect() override { - handler_->CallOn(link_manager_, &LinkManager::handle_link_security_disconnect, remote_); - } - - void EnsureAuthenticated() override { - handler_->CallOn(link_manager_, &LinkManager::handle_link_security_ensure_authenticated, - remote_); - } - - void EnsureEncrypted() override { - handler_->CallOn(link_manager_, &LinkManager::handle_link_security_ensure_encrypted, remote_); - } - - uint16_t GetAclHandle() override { return acl_handle_; } - - hci::Role GetRole() override { return link_manager_->GetLink(remote_)->GetRole(); } - - os::Handler* handler_; - LinkManager* link_manager_; - hci::Address remote_; - uint16_t acl_handle_; -}; - -void LinkManager::OnConnectSuccess( - std::unique_ptr<hci::acl_manager::ClassicAclConnection> acl_connection) { - // Same link should not be connected twice - hci::Address device = acl_connection->GetAddress(); - log::assert_that(GetLink(device) == nullptr, "{} is connected twice without disconnection", - ADDRESS_TO_LOGGABLE_CSTR(acl_connection->GetAddress())); - links_.try_emplace(device, l2cap_handler_, std::move(acl_connection), parameter_provider_, - dynamic_channel_service_manager_, fixed_channel_service_manager_, this); - auto* link = GetLink(device); - log::assert_that(link != nullptr, "assert failed: link != nullptr"); - link->SendInformationRequest(InformationRequestInfoType::EXTENDED_FEATURES_SUPPORTED); - link->SendInformationRequest(InformationRequestInfoType::FIXED_CHANNELS_SUPPORTED); - link->ReadRemoteVersionInformation(); - link->ReadRemoteSupportedFeatures(); - link->ReadRemoteExtendedFeatures(1); - - // Allocate and distribute channels for all registered fixed channel services - auto fixed_channel_services = fixed_channel_service_manager_->GetRegisteredServices(); - for (auto& fixed_channel_service : fixed_channel_services) { - auto fixed_channel_impl = link->AllocateFixedChannel(fixed_channel_service.first); - fixed_channel_service.second->NotifyChannelCreation( - std::make_unique<FixedChannel>(fixed_channel_impl, l2cap_handler_)); - } - if (pending_dynamic_channels_.find(device) != pending_dynamic_channels_.end()) { - auto psm_list = pending_dynamic_channels_[device]; - auto& callback_list = pending_dynamic_channels_callbacks_[device]; - link->SetPendingDynamicChannels(psm_list, std::move(callback_list)); - pending_dynamic_channels_.erase(device); - pending_dynamic_channels_callbacks_.erase(device); - } - // Notify link property listener - if (link_property_callback_handler_ != nullptr) { - link_property_callback_handler_->CallOn(link_property_listener_, - &LinkPropertyListener::OnLinkConnected, device, - link->GetAclHandle()); - } - - // Notify security manager - if (link_security_interface_listener_handler_ != nullptr) { - link_security_interface_listener_handler_->CallOn( - link_security_interface_listener_, &LinkSecurityInterfaceListener::OnLinkConnected, - std::make_unique<LinkSecurityInterfaceImpl>(l2cap_handler_, this, link)); - } - - // Remove device from pending links list, if any - pending_links_.erase(device); -} - -void LinkManager::OnConnectRequest(hci::Address /* device */, hci::ClassOfDevice /* cod */) { - log::error("Remote connect request unimplemented"); -} - -void LinkManager::OnConnectFail(hci::Address device, hci::ErrorCode reason, bool) { - // Notify all pending links for this device - auto pending_link = pending_links_.find(device); - if (pending_link == pending_links_.end()) { - // There is no pending link, exit - log::info("Connection to {} failed without a pending link; reason: {}", device, - hci::ErrorCodeText(reason)); - if (pending_dynamic_channels_callbacks_.find(device) != - pending_dynamic_channels_callbacks_.end()) { - for (Link::PendingDynamicChannelConnection& callbacks : - pending_dynamic_channels_callbacks_[device]) { - callbacks.on_fail_callback_(DynamicChannelManager::ConnectionResult{ - .hci_error = hci::ErrorCode::CONNECTION_TIMEOUT, - }); - } - pending_dynamic_channels_.erase(device); - pending_dynamic_channels_callbacks_.erase(device); - } - return; - } - for (auto& pending_fixed_channel_connection : - pending_link->second.pending_fixed_channel_connections_) { - pending_fixed_channel_connection.handler_->Post(common::BindOnce( - std::move(pending_fixed_channel_connection.on_fail_callback_), - FixedChannelManager::ConnectionResult{ - .connection_result_code = - FixedChannelManager::ConnectionResultCode::FAIL_HCI_ERROR, - .hci_error = reason})); - } - // Remove entry in pending link list - pending_links_.erase(pending_link); -} - -void LinkManager::OnDisconnect(hci::Address device, hci::ErrorCode status) { - auto* link = GetLink(device); - log::assert_that(link != nullptr, - "Device {} is disconnected with reason 0x{:x}, but not in local database", - ADDRESS_TO_LOGGABLE_CSTR(device), static_cast<uint8_t>(status)); - if (link_security_interface_listener_handler_ != nullptr) { - link_security_interface_listener_handler_->CallOn( - link_security_interface_listener_, &LinkSecurityInterfaceListener::OnLinkDisconnected, - device); - } - if (link_property_callback_handler_ != nullptr) { - link_property_callback_handler_->CallOn(link_property_listener_, - &LinkPropertyListener::OnLinkDisconnected, device); - } - - if (links_with_pending_packets_.count(device) != 0) { - disconnected_links_.emplace(device); - } else { - links_.erase(device); - } -} - -void LinkManager::OnAuthenticationComplete(hci::ErrorCode hci_status, hci::Address device) { - if (link_security_interface_listener_handler_ != nullptr) { - link_security_interface_listener_handler_->CallOn( - link_security_interface_listener_, - &LinkSecurityInterfaceListener::OnAuthenticationComplete, hci_status, device); - } -} - -void LinkManager::OnEncryptionChange(hci::Address device, hci::EncryptionEnabled enabled) { - if (link_security_interface_listener_handler_ != nullptr) { - link_security_interface_listener_handler_->CallOn( - link_security_interface_listener_, &LinkSecurityInterfaceListener::OnEncryptionChange, - device, - enabled == hci::EncryptionEnabled::ON || - enabled == hci::EncryptionEnabled::BR_EDR_AES_CCM); - } -} - -void LinkManager::OnReadRemoteVersionInformation(hci::ErrorCode hci_status, hci::Address device, - uint8_t lmp_version, uint16_t manufacturer_name, - uint16_t sub_version) { - if (link_property_callback_handler_ != nullptr) { - link_property_callback_handler_->CallOn( - link_property_listener_, &LinkPropertyListener::OnReadRemoteVersionInformation, - hci_status, device, lmp_version, manufacturer_name, sub_version); - } -} - -void LinkManager::OnReadRemoteSupportedFeatures(hci::Address device, uint64_t features) { - if (link_property_callback_handler_ != nullptr) { - link_property_callback_handler_->CallOn(link_property_listener_, - &LinkPropertyListener::OnReadRemoteSupportedFeatures, - device, features); - } -} - -void LinkManager::OnReadRemoteExtendedFeatures(hci::Address device, uint8_t page_number, - uint8_t max_page_number, uint64_t features) { - if (link_property_callback_handler_ != nullptr) { - link_property_callback_handler_->CallOn(link_property_listener_, - &LinkPropertyListener::OnReadRemoteExtendedFeatures, - device, page_number, max_page_number, features); - } -} - -void LinkManager::OnRoleChange(hci::ErrorCode hci_status, hci::Address remote, hci::Role role) { - if (link_property_callback_handler_ != nullptr) { - link_property_callback_handler_->CallOn( - link_property_listener_, &LinkPropertyListener::OnRoleChange, hci_status, remote, role); - } -} - -void LinkManager::OnReadClockOffset(hci::Address remote, uint16_t clock_offset) { - if (link_property_callback_handler_ != nullptr) { - link_property_callback_handler_->CallOn(link_property_listener_, - &LinkPropertyListener::OnReadClockOffset, remote, - clock_offset); - } -} - -void LinkManager::OnModeChange(hci::ErrorCode hci_status, hci::Address remote, hci::Mode mode, - uint16_t interval) { - if (link_property_callback_handler_ != nullptr) { - link_property_callback_handler_->CallOn(link_property_listener_, - &LinkPropertyListener::OnModeChange, hci_status, remote, - mode, interval); - } -} - -void LinkManager::OnSniffSubrating(hci::ErrorCode hci_status, hci::Address remote, - uint16_t max_tx_lat, uint16_t max_rx_lat, - uint16_t min_remote_timeout, uint16_t min_local_timeout) { - if (link_property_callback_handler_ != nullptr) { - link_property_callback_handler_->CallOn( - link_property_listener_, &LinkPropertyListener::OnSniffSubrating, hci_status, remote, - max_tx_lat, max_rx_lat, min_remote_timeout, min_local_timeout); - } -} - -} // namespace internal -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/internal/link_manager.h b/system/gd/l2cap/classic/internal/link_manager.h deleted file mode 100644 index 1f719fa57b..0000000000 --- a/system/gd/l2cap/classic/internal/link_manager.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <memory> -#include <unordered_map> -#include <vector> - -#include "hci/acl_manager/classic_acl_connection.h" -#include "hci/address.h" -#include "hci/class_of_device.h" -#include "l2cap/classic/dynamic_channel_manager.h" -#include "l2cap/classic/fixed_channel_manager.h" -#include "l2cap/classic/internal/dynamic_channel_service_manager_impl.h" -#include "l2cap/classic/internal/fixed_channel_service_manager_impl.h" -#include "l2cap/classic/internal/link.h" -#include "l2cap/classic/link_property_listener.h" -#include "l2cap/classic/link_security_interface.h" -#include "l2cap/internal/parameter_provider.h" -#include "l2cap/internal/scheduler.h" -#include "os/handler.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace internal { - -class DumpsysHelper; - -class LinkManager : public hci::acl_manager::ConnectionCallbacks { -public: - LinkManager(os::Handler* l2cap_handler, hci::AclManager* acl_manager, - FixedChannelServiceManagerImpl* fixed_channel_service_manager, - DynamicChannelServiceManagerImpl* dynamic_channel_service_manager, - l2cap::internal::ParameterProvider* parameter_provider) - : l2cap_handler_(l2cap_handler), - acl_manager_(acl_manager), - fixed_channel_service_manager_(fixed_channel_service_manager), - dynamic_channel_service_manager_(dynamic_channel_service_manager), - parameter_provider_(parameter_provider) { - acl_manager_->RegisterCallbacks(this, l2cap_handler_); - } - - LinkManager(const LinkManager&) = delete; - LinkManager& operator=(const LinkManager&) = delete; - - struct PendingFixedChannelConnection { - os::Handler* handler_; - FixedChannelManager::OnConnectionFailureCallback on_fail_callback_; - }; - - struct PendingLink { - std::vector<PendingFixedChannelConnection> pending_fixed_channel_connections_; - }; - - // ACL methods - - Link* GetLink(hci::Address device); - void OnConnectSuccess( - std::unique_ptr<hci::acl_manager::ClassicAclConnection> acl_connection) override; - void OnConnectRequest(hci::Address, hci::ClassOfDevice) override; - void OnConnectFail(hci::Address device, hci::ErrorCode reason, bool locally_initiated) override; - - virtual void OnDisconnect(hci::Address device, hci::ErrorCode status); - void OnAuthenticationComplete(hci::ErrorCode hci_status, hci::Address device); - void OnEncryptionChange(hci::Address device, hci::EncryptionEnabled enabled); - void OnReadRemoteVersionInformation(hci::ErrorCode hci_status, hci::Address device, - uint8_t lmp_version, uint16_t manufacturer_name, - uint16_t sub_version); - void OnReadRemoteSupportedFeatures(hci::Address device, uint64_t features); - void OnReadRemoteExtendedFeatures(hci::Address device, uint8_t page_number, - uint8_t max_page_number, uint64_t features); - void OnRoleChange(hci::ErrorCode hci_status, hci::Address remote, hci::Role role); - void OnReadClockOffset(hci::Address remote, uint16_t clock_offset); - void OnModeChange(hci::ErrorCode hci_status, hci::Address remote, hci::Mode mode, - uint16_t interval); - void OnSniffSubrating(hci::ErrorCode hci_status, hci::Address remote, uint16_t max_tx_lat, - uint16_t max_rx_lat, uint16_t min_remote_timeout, - uint16_t min_local_timeout); - - // FixedChannelManager methods - - void ConnectFixedChannelServices(hci::Address device, - PendingFixedChannelConnection pending_fixed_channel_connection); - - // DynamicChannelManager methods - - void ConnectDynamicChannelServices(hci::Address device, - Link::PendingDynamicChannelConnection pending_connection, - Psm psm); - - // For SecurityModule to initiate an ACL link - void InitiateConnectionForSecurity(hci::Address remote); - - // LinkManager will handle sending OnLinkConnected() callback and construct a - // LinkSecurityInterface proxy. - void RegisterLinkSecurityInterfaceListener(os::Handler* handler, - LinkSecurityInterfaceListener* listener); - - // For the link to get LinkSecurityInterfaceListener - LinkSecurityInterfaceListener* GetLinkSecurityInterfaceListener(); - - // Registerlink callbacks - void RegisterLinkPropertyListener(os::Handler* handler, LinkPropertyListener* listener); - - // Reported by link to indicate how many pending packets are remaining to be set. - // If there is anything outstanding, don't delete link - void OnPendingPacketChange(hci::Address remote, int num_packets); - -private: - // Handles requests from LinkSecurityInterface - friend class LinkSecurityInterfaceImpl; - friend class DumpsysHelper; - void handle_link_security_hold(hci::Address remote); - void handle_link_security_release(hci::Address remote); - void handle_link_security_disconnect(hci::Address remote); - void handle_link_security_ensure_authenticated(hci::Address remote); - void handle_link_security_ensure_encrypted(hci::Address remote); - - // Dependencies - os::Handler* l2cap_handler_; - hci::AclManager* acl_manager_; - FixedChannelServiceManagerImpl* fixed_channel_service_manager_; - DynamicChannelServiceManagerImpl* dynamic_channel_service_manager_; - l2cap::internal::ParameterProvider* parameter_provider_; - - // Internal states - std::unordered_map<hci::Address, PendingLink> pending_links_; - std::unordered_map<hci::Address, Link> links_; - std::unordered_map<hci::Address, std::list<Psm>> pending_dynamic_channels_; - std::unordered_map<hci::Address, std::list<Link::PendingDynamicChannelConnection>> - pending_dynamic_channels_callbacks_; - os::Handler* link_security_interface_listener_handler_ = nullptr; - LinkSecurityInterfaceListener* link_security_interface_listener_ = nullptr; - LinkPropertyListener* link_property_listener_ = nullptr; - os::Handler* link_property_callback_handler_ = nullptr; - std::unordered_set<hci::Address> disconnected_links_; - std::unordered_set<hci::Address> links_with_pending_packets_; -}; - -} // namespace internal -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/internal/link_manager_test.cc b/system/gd/l2cap/classic/internal/link_manager_test.cc deleted file mode 100644 index ad2928ff06..0000000000 --- a/system/gd/l2cap/classic/internal/link_manager_test.cc +++ /dev/null @@ -1,570 +0,0 @@ -/* - * Copyright 2018 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 "l2cap/classic/internal/link_manager.h" - -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include <future> -#include <thread> - -#include "common/bind.h" -#include "common/testing/bind_test_util.h" -#include "dynamic_channel_service_manager_impl_mock.h" -#include "hci/acl_manager_mock.h" -#include "hci/address.h" -#include "l2cap/cid.h" -#include "l2cap/classic/fixed_channel_manager.h" -#include "l2cap/classic/internal/dynamic_channel_service_impl_mock.h" -#include "l2cap/classic/internal/fixed_channel_service_impl_mock.h" -#include "l2cap/classic/internal/fixed_channel_service_manager_impl_mock.h" -#include "l2cap/internal/parameter_provider_mock.h" -#include "os/handler.h" -#include "os/thread.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace internal { -namespace { - -using hci::testing::MockAclManager; -using hci::testing::MockClassicAclConnection; -using l2cap::internal::testing::MockParameterProvider; -using ::testing::_; // Matcher to any value -using ::testing::ByMove; -using ::testing::DoAll; -using testing::MockDynamicChannelServiceImpl; -using testing::MockDynamicChannelServiceManagerImpl; -using testing::MockFixedChannelServiceImpl; -using testing::MockFixedChannelServiceManagerImpl; -using ::testing::Return; -using ::testing::SaveArg; - -constexpr static auto kTestIdleDisconnectTimeoutLong = std::chrono::milliseconds(1000); -constexpr static auto kTestIdleDisconnectTimeoutShort = std::chrono::milliseconds(1000); - -class L2capClassicLinkManagerTest : public ::testing::Test { -public: - static void SyncHandler(os::Handler* handler) { - std::promise<void> promise; - auto future = promise.get_future(); - handler->Post(common::BindOnce(&std::promise<void>::set_value, common::Unretained(&promise))); - future.wait_for(std::chrono::milliseconds(3)); - } - -protected: - void SetUp() override { - thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL); - l2cap_handler_ = new os::Handler(thread_); - mock_parameter_provider_ = new MockParameterProvider; - EXPECT_CALL(*mock_parameter_provider_, GetClassicLinkIdleDisconnectTimeout) - .WillRepeatedly(Return(kTestIdleDisconnectTimeoutLong)); - } - - void TearDown() override { - delete mock_parameter_provider_; - l2cap_handler_->Clear(); - delete l2cap_handler_; - delete thread_; - } - - os::Thread* thread_ = nullptr; - os::Handler* l2cap_handler_ = nullptr; - MockParameterProvider* mock_parameter_provider_ = nullptr; -}; - -TEST_F(L2capClassicLinkManagerTest, connect_fixed_channel_service_without_acl) { - MockFixedChannelServiceManagerImpl mock_classic_fixed_channel_service_manager; - MockDynamicChannelServiceManagerImpl mock_classic_dynamic_channel_service_manager; - SecurityEnforcementRejectAllImpl security_module_impl; - MockDynamicChannelServiceImpl service; - ON_CALL(service, GetSecurityPolicy()) - .WillByDefault( - Return(SecurityPolicy::_SDP_ONLY_NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK)); - - ON_CALL(mock_classic_dynamic_channel_service_manager, GetSecurityEnforcementInterface()) - .WillByDefault(Return(&security_module_impl)); - MockAclManager mock_acl_manager; - hci::Address device{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}; - auto user_handler = std::make_unique<os::Handler>(thread_); - - // Step 1: Verify callback registration with HCI - hci::acl_manager::ConnectionCallbacks* hci_connection_callbacks = nullptr; - os::Handler* hci_callback_handler = nullptr; - EXPECT_CALL(mock_acl_manager, RegisterCallbacks(_, _)) - .WillOnce( - DoAll(SaveArg<0>(&hci_connection_callbacks), SaveArg<1>(&hci_callback_handler))); - ON_CALL(mock_classic_dynamic_channel_service_manager, GetService(_)) - .WillByDefault(Return(&service)); - LinkManager classic_link_manager( - l2cap_handler_, &mock_acl_manager, &mock_classic_fixed_channel_service_manager, - &mock_classic_dynamic_channel_service_manager, mock_parameter_provider_); - EXPECT_EQ(hci_connection_callbacks, &classic_link_manager); - EXPECT_EQ(hci_callback_handler, l2cap_handler_); - - // Register fake services - MockFixedChannelServiceImpl mock_service_1, mock_service_2; - std::vector<std::pair<Cid, FixedChannelServiceImpl*>> results; - results.emplace_back(kSmpBrCid, &mock_service_1); - results.emplace_back(kConnectionlessCid, &mock_service_2); - EXPECT_CALL(mock_classic_fixed_channel_service_manager, GetRegisteredServices()) - .WillRepeatedly(Return(results)); - - // Step 2: Connect to fixed channel without ACL connection should trigger ACL connection process - EXPECT_CALL(mock_acl_manager, CreateConnection(device)).Times(1); - LinkManager::PendingFixedChannelConnection pending_fixed_channel_connection{ - .handler_ = user_handler.get(), - .on_fail_callback_ = - common::BindOnce([](FixedChannelManager::ConnectionResult result) { FAIL(); })}; - classic_link_manager.ConnectFixedChannelServices(device, - std::move(pending_fixed_channel_connection)); - - // Step 3: ACL connection success event should trigger channel creation for all registered - // services - - std::unique_ptr<MockClassicAclConnection> acl_connection = - std::make_unique<MockClassicAclConnection>(); - EXPECT_CALL(*acl_connection, GetAddress()).WillRepeatedly(Return(device)); - EXPECT_CALL(*acl_connection, RegisterCallbacks(_, l2cap_handler_)).Times(1); - std::unique_ptr<FixedChannel> channel_1, channel_2; - std::promise<void> promise_1, promise_2; - auto future_1 = promise_1.get_future(); - auto future_2 = promise_2.get_future(); - EXPECT_CALL(mock_service_1, NotifyChannelCreation(_)) - .WillOnce([&channel_1, &promise_1](std::unique_ptr<FixedChannel> channel) { - channel_1 = std::move(channel); - promise_1.set_value(); - }); - EXPECT_CALL(mock_service_2, NotifyChannelCreation(_)) - .WillOnce([&channel_2, &promise_2](std::unique_ptr<FixedChannel> channel) { - channel_2 = std::move(channel); - promise_2.set_value(); - }); - hci_callback_handler->Post(common::BindOnce( - &hci::acl_manager::ConnectionCallbacks::OnConnectSuccess, - common::Unretained(hci_connection_callbacks), std::move(acl_connection))); - SyncHandler(hci_callback_handler); - auto future_1_status = future_1.wait_for(kTestIdleDisconnectTimeoutShort); - EXPECT_EQ(future_1_status, std::future_status::ready); - EXPECT_NE(channel_1, nullptr); - auto future_2_status = future_2.wait_for(kTestIdleDisconnectTimeoutShort); - EXPECT_EQ(future_2_status, std::future_status::ready); - EXPECT_NE(channel_2, nullptr); - - // Step 4: Calling ConnectServices() to the same device will no trigger another connection attempt - FixedChannelManager::ConnectionResult my_result; - LinkManager::PendingFixedChannelConnection pending_fixed_channel_connection_2{ - .handler_ = user_handler.get(), - .on_fail_callback_ = common::testing::BindLambdaForTesting( - [&my_result](FixedChannelManager::ConnectionResult result) { - my_result = result; - })}; - classic_link_manager.ConnectFixedChannelServices(device, - std::move(pending_fixed_channel_connection_2)); - SyncHandler(user_handler.get()); - EXPECT_EQ(my_result.connection_result_code, - FixedChannelManager::ConnectionResultCode::FAIL_ALL_SERVICES_HAVE_CHANNEL); - - // Step 5: Register new service will cause new channels to be created during ConnectServices() - MockFixedChannelServiceImpl mock_service_3; - results.emplace_back(kSmpBrCid + 1, &mock_service_3); - EXPECT_CALL(mock_classic_fixed_channel_service_manager, GetRegisteredServices()) - .WillRepeatedly(Return(results)); - LinkManager::PendingFixedChannelConnection pending_fixed_channel_connection_3{ - .handler_ = user_handler.get(), - .on_fail_callback_ = - common::BindOnce([](FixedChannelManager::ConnectionResult result) { FAIL(); })}; - std::unique_ptr<FixedChannel> channel_3; - EXPECT_CALL(mock_service_3, NotifyChannelCreation(_)) - .WillOnce([&channel_3](std::unique_ptr<FixedChannel> channel) { - channel_3 = std::move(channel); - }); - classic_link_manager.ConnectFixedChannelServices(device, - std::move(pending_fixed_channel_connection_3)); - EXPECT_NE(channel_3, nullptr); - - user_handler->Clear(); - - classic_link_manager.OnDisconnect(device, hci::ErrorCode::SUCCESS); -} - -TEST_F(L2capClassicLinkManagerTest, connect_fixed_channel_service_without_acl_with_no_service) { - MockFixedChannelServiceManagerImpl mock_classic_fixed_channel_service_manager; - MockAclManager mock_acl_manager; - hci::Address device{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}; - auto user_handler = std::make_unique<os::Handler>(thread_); - - // Step 1: Verify callback registration with HCI - hci::acl_manager::ConnectionCallbacks* hci_connection_callbacks = nullptr; - os::Handler* hci_callback_handler = nullptr; - EXPECT_CALL(mock_acl_manager, RegisterCallbacks(_, _)) - .WillOnce( - DoAll(SaveArg<0>(&hci_connection_callbacks), SaveArg<1>(&hci_callback_handler))); - LinkManager classic_link_manager(l2cap_handler_, &mock_acl_manager, - &mock_classic_fixed_channel_service_manager, nullptr, - mock_parameter_provider_); - EXPECT_EQ(hci_connection_callbacks, &classic_link_manager); - EXPECT_EQ(hci_callback_handler, l2cap_handler_); - - // Make sure no service is registered - std::vector<std::pair<Cid, FixedChannelServiceImpl*>> results; - EXPECT_CALL(mock_classic_fixed_channel_service_manager, GetRegisteredServices()) - .WillRepeatedly(Return(results)); - - // Step 2: Connect to fixed channel without any service registered will result in failure - EXPECT_CALL(mock_acl_manager, CreateConnection(device)).Times(0); - FixedChannelManager::ConnectionResult my_result; - LinkManager::PendingFixedChannelConnection pending_fixed_channel_connection{ - .handler_ = user_handler.get(), - .on_fail_callback_ = common::testing::BindLambdaForTesting( - [&my_result](FixedChannelManager::ConnectionResult result) { - my_result = result; - })}; - classic_link_manager.ConnectFixedChannelServices(device, - std::move(pending_fixed_channel_connection)); - SyncHandler(user_handler.get()); - EXPECT_EQ(my_result.connection_result_code, - FixedChannelManager::ConnectionResultCode::FAIL_NO_SERVICE_REGISTERED); - - user_handler->Clear(); -} - -TEST_F(L2capClassicLinkManagerTest, connect_fixed_channel_service_without_acl_with_hci_failure) { - MockFixedChannelServiceManagerImpl mock_classic_fixed_channel_service_manager; - MockAclManager mock_acl_manager; - hci::Address device{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}; - auto user_handler = std::make_unique<os::Handler>(thread_); - - // Step 1: Verify callback registration with HCI - hci::acl_manager::ConnectionCallbacks* hci_connection_callbacks = nullptr; - os::Handler* hci_callback_handler = nullptr; - EXPECT_CALL(mock_acl_manager, RegisterCallbacks(_, _)) - .WillOnce( - DoAll(SaveArg<0>(&hci_connection_callbacks), SaveArg<1>(&hci_callback_handler))); - LinkManager classic_link_manager(l2cap_handler_, &mock_acl_manager, - &mock_classic_fixed_channel_service_manager, nullptr, - mock_parameter_provider_); - EXPECT_EQ(hci_connection_callbacks, &classic_link_manager); - EXPECT_EQ(hci_callback_handler, l2cap_handler_); - - // Register fake services - MockFixedChannelServiceImpl mock_service_1; - std::vector<std::pair<Cid, FixedChannelServiceImpl*>> results; - results.emplace_back(kSmpBrCid, &mock_service_1); - EXPECT_CALL(mock_classic_fixed_channel_service_manager, GetRegisteredServices()) - .WillRepeatedly(Return(results)); - - // Step 2: Connect to fixed channel without ACL connection should trigger ACL connection process - EXPECT_CALL(mock_acl_manager, CreateConnection(device)).Times(1); - FixedChannelManager::ConnectionResult my_result; - LinkManager::PendingFixedChannelConnection pending_fixed_channel_connection{ - .handler_ = user_handler.get(), - .on_fail_callback_ = common::testing::BindLambdaForTesting( - [&my_result](FixedChannelManager::ConnectionResult result) { - my_result = result; - })}; - classic_link_manager.ConnectFixedChannelServices(device, - std::move(pending_fixed_channel_connection)); - - // Step 3: ACL connection failure event should trigger connection failure callback - EXPECT_CALL(mock_service_1, NotifyChannelCreation(_)).Times(0); - hci_callback_handler->Post(common::BindOnce(&hci::acl_manager::ConnectionCallbacks::OnConnectFail, - common::Unretained(hci_connection_callbacks), device, - hci::ErrorCode::PAGE_TIMEOUT, - true /* locally_initiated */)); - SyncHandler(hci_callback_handler); - SyncHandler(user_handler.get()); - EXPECT_EQ(my_result.connection_result_code, - FixedChannelManager::ConnectionResultCode::FAIL_HCI_ERROR); - EXPECT_EQ(my_result.hci_error, hci::ErrorCode::PAGE_TIMEOUT); - - user_handler->Clear(); -} - -TEST_F(L2capClassicLinkManagerTest, not_acquiring_channels_should_disconnect_acl_after_timeout) { - EXPECT_CALL(*mock_parameter_provider_, GetClassicLinkIdleDisconnectTimeout) - .WillRepeatedly(Return(kTestIdleDisconnectTimeoutShort)); - MockFixedChannelServiceManagerImpl mock_classic_fixed_channel_service_manager; - MockAclManager mock_acl_manager; - hci::Address device{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}; - auto user_handler = std::make_unique<os::Handler>(thread_); - - // Step 1: Verify callback registration with HCI - hci::acl_manager::ConnectionCallbacks* hci_connection_callbacks = nullptr; - os::Handler* hci_callback_handler = nullptr; - EXPECT_CALL(mock_acl_manager, RegisterCallbacks(_, _)) - .WillOnce( - DoAll(SaveArg<0>(&hci_connection_callbacks), SaveArg<1>(&hci_callback_handler))); - LinkManager classic_link_manager(l2cap_handler_, &mock_acl_manager, - &mock_classic_fixed_channel_service_manager, nullptr, - mock_parameter_provider_); - EXPECT_EQ(hci_connection_callbacks, &classic_link_manager); - EXPECT_EQ(hci_callback_handler, l2cap_handler_); - - // Register fake services - MockFixedChannelServiceImpl mock_service_1, mock_service_2; - std::vector<std::pair<Cid, FixedChannelServiceImpl*>> results; - results.emplace_back(kSmpBrCid, &mock_service_1); - results.emplace_back(kConnectionlessCid, &mock_service_2); - EXPECT_CALL(mock_classic_fixed_channel_service_manager, GetRegisteredServices()) - .WillRepeatedly(Return(results)); - - // Step 2: Connect to fixed channel without ACL connection should trigger ACL connection process - EXPECT_CALL(mock_acl_manager, CreateConnection(device)).Times(1); - LinkManager::PendingFixedChannelConnection pending_fixed_channel_connection{ - .handler_ = user_handler.get(), - .on_fail_callback_ = - common::BindOnce([](FixedChannelManager::ConnectionResult result) { FAIL(); })}; - classic_link_manager.ConnectFixedChannelServices(device, - std::move(pending_fixed_channel_connection)); - - // Step 3: ACL connection success event should trigger channel creation for all registered - // services - auto* raw_acl_connection = new MockClassicAclConnection(); - std::unique_ptr<MockClassicAclConnection> acl_connection(raw_acl_connection); - EXPECT_CALL(*acl_connection, GetAddress()).WillRepeatedly(Return(device)); - EXPECT_CALL(*acl_connection, RegisterCallbacks(_, l2cap_handler_)).Times(1); - std::unique_ptr<FixedChannel> channel_1, channel_2; - std::promise<void> promise_1, promise_2; - auto future_1 = promise_1.get_future(); - auto future_2 = promise_2.get_future(); - EXPECT_CALL(mock_service_1, NotifyChannelCreation(_)) - .WillOnce([&channel_1, &promise_1](std::unique_ptr<FixedChannel> channel) { - channel_1 = std::move(channel); - promise_1.set_value(); - }); - EXPECT_CALL(mock_service_2, NotifyChannelCreation(_)) - .WillOnce([&channel_2, &promise_2](std::unique_ptr<FixedChannel> channel) { - channel_2 = std::move(channel); - promise_2.set_value(); - }); - hci_callback_handler->Post(common::BindOnce( - &hci::acl_manager::ConnectionCallbacks::OnConnectSuccess, - common::Unretained(hci_connection_callbacks), std::move(acl_connection))); - SyncHandler(hci_callback_handler); - auto future_1_status = future_1.wait_for(kTestIdleDisconnectTimeoutShort); - EXPECT_EQ(future_1_status, std::future_status::ready); - EXPECT_NE(channel_1, nullptr); - auto future_2_status = future_2.wait_for(kTestIdleDisconnectTimeoutShort); - EXPECT_EQ(future_2_status, std::future_status::ready); - EXPECT_NE(channel_2, nullptr); - hci::ErrorCode status_1 = hci::ErrorCode::SUCCESS; - channel_1->RegisterOnCloseCallback( - user_handler.get(), - common::testing::BindLambdaForTesting([&](hci::ErrorCode status) { status_1 = status; })); - hci::ErrorCode status_2 = hci::ErrorCode::SUCCESS; - channel_2->RegisterOnCloseCallback( - user_handler.get(), - common::testing::BindLambdaForTesting([&](hci::ErrorCode status) { status_2 = status; })); - - // Step 4: Leave channel IDLE long enough, they will disconnect - EXPECT_CALL(*raw_acl_connection, - Disconnect(hci::DisconnectReason::REMOTE_USER_TERMINATED_CONNECTION)) - .Times(1); - std::this_thread::sleep_for(kTestIdleDisconnectTimeoutShort * 1.2); - - user_handler->Clear(); -} - -TEST_F(L2capClassicLinkManagerTest, acquiring_channels_should_not_disconnect_acl_after_timeout) { - EXPECT_CALL(*mock_parameter_provider_, GetClassicLinkIdleDisconnectTimeout) - .WillRepeatedly(Return(kTestIdleDisconnectTimeoutShort)); - MockFixedChannelServiceManagerImpl mock_classic_fixed_channel_service_manager; - MockAclManager mock_acl_manager; - hci::Address device{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}; - auto user_handler = std::make_unique<os::Handler>(thread_); - - // Step 1: Verify callback registration with HCI - hci::acl_manager::ConnectionCallbacks* hci_connection_callbacks = nullptr; - os::Handler* hci_callback_handler = nullptr; - EXPECT_CALL(mock_acl_manager, RegisterCallbacks(_, _)) - .WillOnce( - DoAll(SaveArg<0>(&hci_connection_callbacks), SaveArg<1>(&hci_callback_handler))); - LinkManager classic_link_manager(l2cap_handler_, &mock_acl_manager, - &mock_classic_fixed_channel_service_manager, nullptr, - mock_parameter_provider_); - EXPECT_EQ(hci_connection_callbacks, &classic_link_manager); - EXPECT_EQ(hci_callback_handler, l2cap_handler_); - - // Register fake services - MockFixedChannelServiceImpl mock_service_1, mock_service_2; - std::vector<std::pair<Cid, FixedChannelServiceImpl*>> results; - results.emplace_back(kSmpBrCid, &mock_service_1); - results.emplace_back(kConnectionlessCid, &mock_service_2); - EXPECT_CALL(mock_classic_fixed_channel_service_manager, GetRegisteredServices()) - .WillRepeatedly(Return(results)); - - // Step 2: Connect to fixed channel without ACL connection should trigger ACL connection process - EXPECT_CALL(mock_acl_manager, CreateConnection(device)).Times(1); - LinkManager::PendingFixedChannelConnection pending_fixed_channel_connection{ - .handler_ = user_handler.get(), - .on_fail_callback_ = - common::BindOnce([](FixedChannelManager::ConnectionResult result) { FAIL(); })}; - classic_link_manager.ConnectFixedChannelServices(device, - std::move(pending_fixed_channel_connection)); - - // Step 3: ACL connection success event should trigger channel creation for all registered - // services - auto* raw_acl_connection = new MockClassicAclConnection(); - std::unique_ptr<MockClassicAclConnection> acl_connection(raw_acl_connection); - EXPECT_CALL(*acl_connection, GetAddress()).WillRepeatedly(Return(device)); - EXPECT_CALL(*acl_connection, RegisterCallbacks(_, l2cap_handler_)).Times(1); - std::unique_ptr<FixedChannel> channel_1, channel_2; - std::promise<void> promise_1, promise_2; - auto future_1 = promise_1.get_future(); - auto future_2 = promise_2.get_future(); - EXPECT_CALL(mock_service_1, NotifyChannelCreation(_)) - .WillOnce([&channel_1, &promise_1](std::unique_ptr<FixedChannel> channel) { - channel_1 = std::move(channel); - promise_1.set_value(); - }); - EXPECT_CALL(mock_service_2, NotifyChannelCreation(_)) - .WillOnce([&channel_2, &promise_2](std::unique_ptr<FixedChannel> channel) { - channel_2 = std::move(channel); - promise_2.set_value(); - }); - hci_callback_handler->Post(common::BindOnce( - &hci::acl_manager::ConnectionCallbacks::OnConnectSuccess, - common::Unretained(hci_connection_callbacks), std::move(acl_connection))); - SyncHandler(hci_callback_handler); - auto future_1_status = future_1.wait_for(kTestIdleDisconnectTimeoutShort); - EXPECT_EQ(future_1_status, std::future_status::ready); - EXPECT_NE(channel_1, nullptr); - auto future_2_status = future_2.wait_for(kTestIdleDisconnectTimeoutShort); - EXPECT_EQ(future_2_status, std::future_status::ready); - EXPECT_NE(channel_2, nullptr); - hci::ErrorCode status_1 = hci::ErrorCode::SUCCESS; - channel_1->RegisterOnCloseCallback( - user_handler.get(), - common::testing::BindLambdaForTesting([&](hci::ErrorCode status) { status_1 = status; })); - hci::ErrorCode status_2 = hci::ErrorCode::SUCCESS; - channel_2->RegisterOnCloseCallback( - user_handler.get(), - common::testing::BindLambdaForTesting([&](hci::ErrorCode status) { status_2 = status; })); - - channel_1->Acquire(); - - // Step 4: Leave channel IDLE, it won't disconnect to due acquired channel 1 - EXPECT_CALL(*raw_acl_connection, - Disconnect(hci::DisconnectReason::REMOTE_USER_TERMINATED_CONNECTION)) - .Times(0); - std::this_thread::sleep_for(kTestIdleDisconnectTimeoutShort * 2); - - user_handler->Clear(); -} - -TEST_F(L2capClassicLinkManagerTest, - acquiring_and_releasing_channels_should_eventually_disconnect_acl) { - EXPECT_CALL(*mock_parameter_provider_, GetClassicLinkIdleDisconnectTimeout) - .WillRepeatedly(Return(kTestIdleDisconnectTimeoutShort)); - MockFixedChannelServiceManagerImpl mock_classic_fixed_channel_service_manager; - MockAclManager mock_acl_manager; - hci::Address device{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}; - auto user_handler = std::make_unique<os::Handler>(thread_); - - // Step 1: Verify callback registration with HCI - hci::acl_manager::ConnectionCallbacks* hci_connection_callbacks = nullptr; - os::Handler* hci_callback_handler = nullptr; - EXPECT_CALL(mock_acl_manager, RegisterCallbacks(_, _)) - .WillOnce( - DoAll(SaveArg<0>(&hci_connection_callbacks), SaveArg<1>(&hci_callback_handler))); - LinkManager classic_link_manager(l2cap_handler_, &mock_acl_manager, - &mock_classic_fixed_channel_service_manager, nullptr, - mock_parameter_provider_); - EXPECT_EQ(hci_connection_callbacks, &classic_link_manager); - EXPECT_EQ(hci_callback_handler, l2cap_handler_); - - // Register fake services - MockFixedChannelServiceImpl mock_service_1, mock_service_2; - std::vector<std::pair<Cid, FixedChannelServiceImpl*>> results; - results.emplace_back(kSmpBrCid, &mock_service_1); - results.emplace_back(kConnectionlessCid, &mock_service_2); - EXPECT_CALL(mock_classic_fixed_channel_service_manager, GetRegisteredServices()) - .WillRepeatedly(Return(results)); - - // Step 2: Connect to fixed channel without ACL connection should trigger ACL connection process - EXPECT_CALL(mock_acl_manager, CreateConnection(device)).Times(1); - LinkManager::PendingFixedChannelConnection pending_fixed_channel_connection{ - .handler_ = user_handler.get(), - .on_fail_callback_ = - common::BindOnce([](FixedChannelManager::ConnectionResult result) { FAIL(); })}; - classic_link_manager.ConnectFixedChannelServices(device, - std::move(pending_fixed_channel_connection)); - - // Step 3: ACL connection success event should trigger channel creation for all registered - // services - auto* raw_acl_connection = new MockClassicAclConnection(); - std::unique_ptr<MockClassicAclConnection> acl_connection(raw_acl_connection); - EXPECT_CALL(*acl_connection, GetAddress()).WillRepeatedly(Return(device)); - EXPECT_CALL(*acl_connection, RegisterCallbacks(_, l2cap_handler_)).Times(1); - std::unique_ptr<FixedChannel> channel_1, channel_2; - std::promise<void> promise_1, promise_2; - auto future_1 = promise_1.get_future(); - auto future_2 = promise_2.get_future(); - EXPECT_CALL(mock_service_1, NotifyChannelCreation(_)) - .WillOnce([&channel_1, &promise_1](std::unique_ptr<FixedChannel> channel) { - channel_1 = std::move(channel); - promise_1.set_value(); - }); - EXPECT_CALL(mock_service_2, NotifyChannelCreation(_)) - .WillOnce([&channel_2, &promise_2](std::unique_ptr<FixedChannel> channel) { - channel_2 = std::move(channel); - promise_2.set_value(); - }); - hci_callback_handler->Post(common::BindOnce( - &hci::acl_manager::ConnectionCallbacks::OnConnectSuccess, - common::Unretained(hci_connection_callbacks), std::move(acl_connection))); - SyncHandler(hci_callback_handler); - auto future_1_status = future_1.wait_for(kTestIdleDisconnectTimeoutShort); - EXPECT_EQ(future_1_status, std::future_status::ready); - EXPECT_NE(channel_1, nullptr); - auto future_2_status = future_2.wait_for(kTestIdleDisconnectTimeoutShort); - EXPECT_EQ(future_2_status, std::future_status::ready); - EXPECT_NE(channel_2, nullptr); - hci::ErrorCode status_1 = hci::ErrorCode::SUCCESS; - channel_1->RegisterOnCloseCallback( - user_handler.get(), - common::testing::BindLambdaForTesting([&](hci::ErrorCode status) { status_1 = status; })); - hci::ErrorCode status_2 = hci::ErrorCode::SUCCESS; - channel_2->RegisterOnCloseCallback( - user_handler.get(), - common::testing::BindLambdaForTesting([&](hci::ErrorCode status) { status_2 = status; })); - - channel_1->Acquire(); - - // Step 4: Leave channel IDLE, it won't disconnect to due acquired channel 1 - EXPECT_CALL(*raw_acl_connection, - Disconnect(hci::DisconnectReason::REMOTE_USER_TERMINATED_CONNECTION)) - .Times(0); - std::this_thread::sleep_for(kTestIdleDisconnectTimeoutShort * 2); - - // Step 5: Leave channel IDLE long enough, they will disconnect - channel_1->Release(); - EXPECT_CALL(*raw_acl_connection, - Disconnect(hci::DisconnectReason::REMOTE_USER_TERMINATED_CONNECTION)) - .Times(1); - std::this_thread::sleep_for(kTestIdleDisconnectTimeoutShort * 1.2); - - user_handler->Clear(); -} - -} // namespace -} // namespace internal -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/internal/link_mock.h b/system/gd/l2cap/classic/internal/link_mock.h deleted file mode 100644 index c55649117f..0000000000 --- a/system/gd/l2cap/classic/internal/link_mock.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2019 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. - */ -#pragma once - -#include <gmock/gmock.h> - -#include "hci/acl_manager_mock.h" -#include "hci/address.h" -#include "l2cap/classic/internal/link.h" -#include "l2cap/internal/scheduler_mock.h" - -// Unit test interfaces -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace internal { -namespace testing { - -using hci::testing::MockClassicAclConnection; - -class MockLink : public Link { -public: - explicit MockLink(os::Handler* handler, l2cap::internal::ParameterProvider* parameter_provider) - : Link(handler, std::make_unique<MockClassicAclConnection>(), parameter_provider, nullptr, - nullptr, nullptr) {} - explicit MockLink(os::Handler* handler, l2cap::internal::ParameterProvider* parameter_provider, - std::unique_ptr<hci::acl_manager::ClassicAclConnection> acl_connection, - LinkManager* /* link_manager */) - : Link(handler, std::move(acl_connection), parameter_provider, nullptr, nullptr, nullptr) {} - MOCK_METHOD(hci::AddressWithType, GetDevice, (), (const, override)); - MOCK_METHOD(void, OnAclDisconnected, (hci::ErrorCode status), (override)); - MOCK_METHOD(void, Disconnect, (), (override)); - MOCK_METHOD(std::shared_ptr<l2cap::internal::DynamicChannelImpl>, AllocateDynamicChannel, - (Psm psm, Cid cid), (override)); - - MOCK_METHOD(bool, IsFixedChannelAllocated, (Cid cid), (override)); - MOCK_METHOD(void, RefreshRefCount, (), (override)); -}; - -} // namespace testing -} // namespace internal -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/internal/link_test.cc b/system/gd/l2cap/classic/internal/link_test.cc deleted file mode 100644 index c6a0addccb..0000000000 --- a/system/gd/l2cap/classic/internal/link_test.cc +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2020 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 "l2cap/classic/internal/link.h" - -#include <gmock/gmock-nice-strict.h> -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include "hci/acl_manager_mock.h" -#include "hci/address.h" -#include "l2cap/classic/internal/dynamic_channel_service_impl_mock.h" -#include "l2cap/classic/internal/dynamic_channel_service_manager_impl_mock.h" -#include "l2cap/classic/internal/fixed_channel_service_manager_impl_mock.h" -#include "l2cap/internal/parameter_provider_mock.h" - -using ::testing::NiceMock; - -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace internal { -namespace { - -constexpr Psm kPsm = 123; -constexpr Cid kCid = 456; - -using classic::internal::testing::MockDynamicChannelServiceImpl; -using classic::internal::testing::MockDynamicChannelServiceManagerImpl; -using hci::testing::MockClassicAclConnection; -using l2cap::internal::testing::MockParameterProvider; -using testing::MockFixedChannelServiceManagerImpl; - -class L2capClassicLinkTest : public ::testing::Test { -public: - void OnOpen(std::unique_ptr<DynamicChannel> channel) { on_open_promise_.set_value(); } - - void OnFail(DynamicChannelManager::ConnectionResult result) { on_fail_promise_.set_value(); } - - void OnDequeueCallbackForTest() { - std::unique_ptr<BasePacketBuilder> data = - raw_acl_connection_->acl_queue_.GetDownEnd()->TryDequeue(); - if (data != nullptr) { - dequeue_promise_.set_value(); - } - } - - void EnqueueCallbackForTest() { - raw_acl_connection_->acl_queue_.GetDownEnd()->RegisterDequeue( - handler_, common::Bind(&L2capClassicLinkTest::OnDequeueCallbackForTest, - common::Unretained(this))); - } - - void DequeueCallback() { raw_acl_connection_->acl_queue_.GetDownEnd()->UnregisterDequeue(); } - -protected: - void SetUp() override { - thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL); - handler_ = new os::Handler(thread_); - signalling_handler_ = new os::Handler(thread_); - - raw_acl_connection_ = new NiceMock<MockClassicAclConnection>(); - link_ = new Link(signalling_handler_, - std::unique_ptr<MockClassicAclConnection>(raw_acl_connection_), - &mock_parameter_provider_, &mock_classic_dynamic_channel_service_manager_, - &mock_classic_fixed_channel_service_manager_, nullptr); - } - - void TearDown() override { - delete link_; - - signalling_handler_->Clear(); - delete signalling_handler_; - - handler_->Clear(); - delete handler_; - - delete thread_; - } - - os::Thread* thread_ = nullptr; - os::Handler* handler_ = nullptr; - os::Handler* signalling_handler_ = nullptr; - - MockClassicAclConnection* raw_acl_connection_ = nullptr; - std::unique_ptr<MockClassicAclConnection> acl_connection_; - - NiceMock<MockParameterProvider> mock_parameter_provider_; - MockFixedChannelServiceManagerImpl mock_classic_fixed_channel_service_manager_; - MockDynamicChannelServiceManagerImpl mock_classic_dynamic_channel_service_manager_; - SecurityEnforcementRejectAllImpl security_module_impl_; - - std::promise<void> on_open_promise_; - std::promise<void> on_fail_promise_; - std::promise<void> dequeue_promise_; - - Link* link_; -}; - -TEST_F(L2capClassicLinkTest, pending_channels_get_notified_on_acl_disconnect) { - EnqueueCallbackForTest(); - - Link::PendingDynamicChannelConnection pending_dynamic_channel_connection{ - .on_open_callback_ = handler_->BindOn(this, &L2capClassicLinkTest::OnOpen), - .on_fail_callback_ = handler_->BindOnceOn(this, &L2capClassicLinkTest::OnFail), - .configuration_ = DynamicChannelConfigurationOption(), - }; - auto future = on_fail_promise_.get_future(); - - MockDynamicChannelServiceImpl service; - ON_CALL(service, GetSecurityPolicy()) - .WillByDefault(::testing::Return( - SecurityPolicy::_SDP_ONLY_NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK)); - - EXPECT_CALL(mock_classic_dynamic_channel_service_manager_, GetSecurityEnforcementInterface()) - .WillOnce(::testing::Return(&security_module_impl_)); - EXPECT_CALL(mock_classic_dynamic_channel_service_manager_, GetService(::testing::_)) - .WillRepeatedly(::testing::Return(&service)); - - link_->SendConnectionRequest(kPsm, kCid, std::move(pending_dynamic_channel_connection)); - link_->OnAclDisconnected(hci::ErrorCode::UNKNOWN_HCI_COMMAND); - future.wait(); - - auto dequeue_future = dequeue_promise_.get_future(); - dequeue_future.wait(); - DequeueCallback(); -} - -} // namespace -} // namespace internal -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/internal/signalling_manager.cc b/system/gd/l2cap/classic/internal/signalling_manager.cc deleted file mode 100644 index b26b194472..0000000000 --- a/system/gd/l2cap/classic/internal/signalling_manager.cc +++ /dev/null @@ -1,1046 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/classic/internal/signalling_manager.h" - -#include <bluetooth/log.h> - -#include <chrono> - -#include "common/bind.h" -#include "l2cap/classic/internal/channel_configuration_state.h" -#include "l2cap/classic/internal/link.h" -#include "l2cap/internal/data_pipeline_manager.h" -#include "l2cap/l2cap_packets.h" -#include "os/log.h" -#include "packet/raw_builder.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace internal { -static constexpr auto kTimeout = std::chrono::seconds(3); - -static std::vector<ControlView> GetCommandsFromPacketView(PacketView<kLittleEndian> packet) { - size_t curr = 0; - size_t end = packet.size(); - std::vector<ControlView> result; - while (curr < end) { - auto sub_view = packet.GetLittleEndianSubview(curr, end); - auto control = ControlView::Create(sub_view); - if (!control.IsValid()) { - return {}; - } - result.push_back(control); - curr += 1 + 1 + 2 + control.GetPayload().size(); - } - return result; -} - -ClassicSignallingManager::ClassicSignallingManager( - os::Handler* handler, Link* link, - l2cap::internal::DataPipelineManager* data_pipeline_manager, - DynamicChannelServiceManagerImpl* dynamic_service_manager, - l2cap::internal::DynamicChannelAllocator* channel_allocator, - FixedChannelServiceManagerImpl* fixed_service_manager) - : handler_(handler), - link_(link), - data_pipeline_manager_(data_pipeline_manager), - dynamic_service_manager_(dynamic_service_manager), - channel_allocator_(channel_allocator), - fixed_service_manager_(fixed_service_manager), - alarm_(handler) { - log::assert_that(handler_ != nullptr, "assert failed: handler_ != nullptr"); - log::assert_that(link_ != nullptr, "assert failed: link_ != nullptr"); - signalling_channel_ = link_->AllocateFixedChannel(kClassicSignallingCid); - signalling_channel_->GetQueueUpEnd()->RegisterDequeue( - handler_, - common::Bind(&ClassicSignallingManager::on_incoming_packet, common::Unretained(this))); - enqueue_buffer_ = std::make_unique<os::EnqueueBuffer<packet::BasePacketBuilder>>( - signalling_channel_->GetQueueUpEnd()); -} - -ClassicSignallingManager::~ClassicSignallingManager() { - alarm_.Cancel(); - signalling_channel_->GetQueueUpEnd()->UnregisterDequeue(); - signalling_channel_ = nullptr; - enqueue_buffer_->Clear(); - enqueue_buffer_.reset(); -} - -void ClassicSignallingManager::OnCommandReject(CommandRejectView command_reject_view) { - if (command_just_sent_.signal_id_ != command_reject_view.GetIdentifier()) { - log::warn("Unexpected command reject: no pending request"); - return; - } - if (command_just_sent_.command_code_ == CommandCode::INFORMATION_REQUEST && - command_just_sent_.info_type_ == InformationRequestInfoType::EXTENDED_FEATURES_SUPPORTED) { - link_->OnRemoteExtendedFeatureReceived(false, false); - } - alarm_.Cancel(); - handle_send_next_command(); - - log::info("Command rejected"); -} - -void ClassicSignallingManager::SendConnectionRequest(Psm psm, Cid local_cid) { - dynamic_service_manager_->GetSecurityEnforcementInterface()->Enforce( - link_->GetDevice(), dynamic_service_manager_->GetService(psm)->GetSecurityPolicy(), - handler_->BindOnceOn(this, &ClassicSignallingManager::on_security_result_for_outgoing, - SecurityEnforcementType::LINK_KEY, psm, local_cid)); -} - -void ClassicSignallingManager::on_security_result_for_outgoing(SecurityEnforcementType type, - Psm psm, Cid local_cid, - bool result) { - if (enqueue_buffer_.get() == nullptr) { - log::error("Got security result callback after deletion"); - return; - } - if (!result) { - log::warn("Security requirement can't be satisfied. Dropping connection request"); - DynamicChannelManager::ConnectionResult connection_result{ - .connection_result_code = - DynamicChannelManager::ConnectionResultCode::FAIL_SECURITY_BLOCK, - .hci_error = hci::ErrorCode::SUCCESS, - .l2cap_connection_response_result = ConnectionResponseResult::NO_RESOURCES_AVAILABLE, - }; - link_->OnOutgoingConnectionRequestFail(local_cid, connection_result); - return; - } - if (type == SecurityEnforcementType::LINK_KEY && !link_->IsAuthenticated() && - dynamic_service_manager_->GetService(psm)->GetSecurityPolicy() != - SecurityPolicy::_SDP_ONLY_NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK) { - link_->Encrypt(); - // TODO(b/171253721): If we can receive ENCRYPTION_CHANGE event, we can send command after - // callback is received. - } - - PendingCommand pending_command = { - next_signal_id_, CommandCode::CONNECTION_REQUEST, psm, local_cid, {}, {}, {}}; - next_signal_id_++; - pending_commands_.push(std::move(pending_command)); - if (command_just_sent_.signal_id_ == kInvalidSignalId) { - handle_send_next_command(); - } -} - -void ClassicSignallingManager::send_configuration_request( - Cid remote_cid, std::vector<std::unique_ptr<ConfigurationOption>> config) { - PendingCommand pending_command = { - next_signal_id_, CommandCode::CONFIGURATION_REQUEST, {}, {}, remote_cid, {}, - std::move(config)}; - next_signal_id_++; - pending_commands_.push(std::move(pending_command)); - if (command_just_sent_.signal_id_ == kInvalidSignalId) { - handle_send_next_command(); - } -} - -void ClassicSignallingManager::SendDisconnectionRequest(Cid local_cid, Cid remote_cid) { - PendingCommand pending_command = { - next_signal_id_, CommandCode::DISCONNECTION_REQUEST, {}, local_cid, remote_cid, {}, {}}; - next_signal_id_++; - pending_commands_.push(std::move(pending_command)); - if (command_just_sent_.signal_id_ == kInvalidSignalId) { - handle_send_next_command(); - } -} - -void ClassicSignallingManager::SendInformationRequest(InformationRequestInfoType type) { - PendingCommand pending_command = { - next_signal_id_, CommandCode::INFORMATION_REQUEST, {}, {}, {}, type, {}}; - next_signal_id_++; - pending_commands_.push(std::move(pending_command)); - if (command_just_sent_.signal_id_ == kInvalidSignalId) { - handle_send_next_command(); - } -} - -void ClassicSignallingManager::SendEchoRequest(std::unique_ptr<packet::RawBuilder> /* payload */) { - log::warn("Not supported"); -} - -void ClassicSignallingManager::CancelAlarm() { alarm_.Cancel(); } - -void ClassicSignallingManager::OnConnectionRequest(SignalId signal_id, Psm psm, Cid remote_cid) { - if (!IsPsmValid(psm)) { - log::warn("Invalid psm received from remote psm:{} remote_cid:{}", psm, remote_cid); - send_connection_response(signal_id, remote_cid, kInvalidCid, - ConnectionResponseResult::PSM_NOT_SUPPORTED, - ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE); - return; - } - - if (remote_cid == kInvalidCid) { - log::warn("Invalid remote cid received from remote psm:{} remote_cid:{}", psm, remote_cid); - send_connection_response(signal_id, remote_cid, kInvalidCid, - ConnectionResponseResult::INVALID_CID, - ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE); - return; - } - /* TODO(zachoverflow): add back in with policy - if (channel_allocator_->IsPsmUsed(psm)) { - log::warn("Psm already exists"); - send_connection_response(signal_id, remote_cid, kInvalidCid, - ConnectionResponseResult::PSM_NOT_SUPPORTED, - ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE); - return; - } - */ - - if (!dynamic_service_manager_->IsServiceRegistered(psm)) { - log::info("Service for this psm ({}) is not registered", psm); - send_connection_response(signal_id, remote_cid, kInvalidCid, - ConnectionResponseResult::PSM_NOT_SUPPORTED, - ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE); - return; - } - - dynamic_service_manager_->GetSecurityEnforcementInterface()->Enforce( - link_->GetDevice(), dynamic_service_manager_->GetService(psm)->GetSecurityPolicy(), - handler_->BindOnceOn(this, &ClassicSignallingManager::on_security_result_for_incoming, - psm, remote_cid, signal_id)); -} - -void ClassicSignallingManager::on_security_result_for_incoming(Psm psm, Cid remote_cid, - SignalId signal_id, bool result) { - if (enqueue_buffer_.get() == nullptr) { - log::error("Got security result callback after deletion"); - return; - } - if (!result) { - send_connection_response(signal_id, remote_cid, 0, ConnectionResponseResult::SECURITY_BLOCK, - ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE); - DynamicChannelManager::ConnectionResult connection_result{ - .connection_result_code = - DynamicChannelManager::ConnectionResultCode::FAIL_SECURITY_BLOCK, - .hci_error = hci::ErrorCode::SUCCESS, - .l2cap_connection_response_result = ConnectionResponseResult::NO_RESOURCES_AVAILABLE, - }; - link_->OnOutgoingConnectionRequestFail(0, connection_result); - } - - auto new_channel = link_->AllocateDynamicChannel(psm, remote_cid); - if (new_channel == nullptr) { - log::warn("Can't allocate dynamic channel"); - return; - } - send_connection_response(signal_id, remote_cid, new_channel->GetCid(), - ConnectionResponseResult::SUCCESS, - ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE); - - link_->SendInitialConfigRequestOrQueue(new_channel->GetCid()); -} - -void ClassicSignallingManager::OnConnectionResponse(SignalId signal_id, Cid remote_cid, Cid cid, - ConnectionResponseResult result, - ConnectionResponseStatus /* status */) { - if (command_just_sent_.signal_id_ != signal_id || - command_just_sent_.command_code_ != CommandCode::CONNECTION_REQUEST) { - log::warn("Unexpected response: no pending request. Expected signal id {} type {}, got {}", - command_just_sent_.signal_id_.Value(), - CommandCodeText(command_just_sent_.command_code_).data(), signal_id.Value()); - return; - } - if (command_just_sent_.source_cid_ != cid) { - log::warn("SCID doesn't match: expected {}, received {}", command_just_sent_.source_cid_, cid); - handle_send_next_command(); - return; - } - if (result == ConnectionResponseResult::PENDING) { - alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, - common::Unretained(this)), - kTimeout); - return; - } - - command_just_sent_.signal_id_ = kInvalidSignalId; - alarm_.Cancel(); - if (result != ConnectionResponseResult::SUCCESS) { - DynamicChannelManager::ConnectionResult connection_result{ - .connection_result_code = DynamicChannelManager::ConnectionResultCode::FAIL_L2CAP_ERROR, - .hci_error = hci::ErrorCode::SUCCESS, - .l2cap_connection_response_result = result, - }; - link_->OnOutgoingConnectionRequestFail(cid, connection_result); - handle_send_next_command(); - return; - } - Psm pending_psm = command_just_sent_.psm_; - auto new_channel = link_->AllocateReservedDynamicChannel(cid, pending_psm, remote_cid); - if (new_channel == nullptr) { - log::warn("Can't allocate dynamic channel"); - DynamicChannelManager::ConnectionResult connection_result{ - .connection_result_code = DynamicChannelManager::ConnectionResultCode::FAIL_L2CAP_ERROR, - .hci_error = hci::ErrorCode::SUCCESS, - .l2cap_connection_response_result = ConnectionResponseResult::NO_RESOURCES_AVAILABLE, - }; - link_->OnOutgoingConnectionRequestFail(cid, connection_result); - handle_send_next_command(); - return; - } - - link_->SendInitialConfigRequestOrQueue(cid); -} - -void ClassicSignallingManager::OnConfigurationRequest( - SignalId signal_id, Cid cid, Continuation is_continuation, - std::vector<std::unique_ptr<ConfigurationOption>> options) { - auto channel = channel_allocator_->FindChannelByCid(cid); - if (channel == nullptr) { - log::warn("Configuration request for an unknown channel"); - return; - } - - auto& configuration_state = channel_configuration_[cid]; - std::vector<std::unique_ptr<ConfigurationOption>> rsp_options; - ConfigurationResponseResult result = ConfigurationResponseResult::SUCCESS; - auto remote_rfc_mode = RetransmissionAndFlowControlModeOption::L2CAP_BASIC; - - auto initial_config_option = - dynamic_service_manager_->GetService(channel->GetPsm())->GetConfigOption(); - - for (auto& option : options) { - switch (option->type_) { - case ConfigurationOptionType::MTU: { - auto* config = MtuConfigurationOption::Specialize(option.get()); - if (config->mtu_ < initial_config_option.minimal_remote_mtu) { - log::warn("Configuration request with unacceptable MTU"); - config->mtu_ = initial_config_option.minimal_remote_mtu; - result = ConfigurationResponseResult::UNACCEPTABLE_PARAMETERS; - } - rsp_options.emplace_back(std::make_unique<MtuConfigurationOption>(*config)); - break; - } - case ConfigurationOptionType::FLUSH_TIMEOUT: { - auto* config = FlushTimeoutConfigurationOption::Specialize(option.get()); - rsp_options.emplace_back(std::make_unique<FlushTimeoutConfigurationOption>(*config)); - break; - } - case ConfigurationOptionType::RETRANSMISSION_AND_FLOW_CONTROL: { - auto* config = RetransmissionAndFlowControlConfigurationOption::Specialize(option.get()); - remote_rfc_mode = config->mode_; - if (config->mode_ == RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION) { - if (config->retransmission_time_out_ == 0) { - config->retransmission_time_out_ = 2000; - } - if (config->monitor_time_out_ == 0) { - config->monitor_time_out_ = 12000; - } - } - configuration_state.remote_retransmission_and_flow_control_ = *config; - configuration_state.retransmission_and_flow_control_mode_ = config->mode_; - rsp_options.emplace_back( - std::make_unique<RetransmissionAndFlowControlConfigurationOption>(*config)); - break; - } - case ConfigurationOptionType::FRAME_CHECK_SEQUENCE: { - // We determine whether to use FCS or not when we send config request - break; - } - default: - if (option->is_hint_ != ConfigurationOptionIsHint::OPTION_IS_A_HINT) { - log::warn("Received some unsupported configuration option: {}", - static_cast<int>(option->type_)); - auto response = ConfigurationResponseBuilder::Create( - signal_id.Value(), channel->GetRemoteCid(), is_continuation, - ConfigurationResponseResult::UNKNOWN_OPTIONS, {}); - enqueue_buffer_->Enqueue(std::move(response), handler_); - return; - } - break; - } - } - - if (remote_rfc_mode == RetransmissionAndFlowControlModeOption::L2CAP_BASIC && - initial_config_option.channel_mode == - DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode:: - ENHANCED_RETRANSMISSION) { - log::warn("ERTM mandatory not allow mode configuration, disconnect channel."); - SendDisconnectionRequest(channel->GetCid(), channel->GetRemoteCid()); - return; - } - - if (configuration_state.state_ == ChannelConfigurationState::State::WAIT_CONFIG_REQ) { - std::unique_ptr<DynamicChannel> user_channel = - std::make_unique<DynamicChannel>(channel, handler_); - if (channel->local_initiated_) { - link_->NotifyChannelCreation(cid, std::move(user_channel)); - } else { - dynamic_service_manager_->GetService(channel->GetPsm()) - ->NotifyChannelCreation(std::move(user_channel)); - } - configuration_state.state_ = ChannelConfigurationState::State::CONFIGURED; - data_pipeline_manager_->AttachChannel(cid, channel, - l2cap::internal::DataPipelineManager::ChannelMode::BASIC); - data_pipeline_manager_->UpdateClassicConfiguration(cid, configuration_state); - } else if (configuration_state.state_ == ChannelConfigurationState::State::WAIT_CONFIG_REQ_RSP) { - configuration_state.state_ = ChannelConfigurationState::State::WAIT_CONFIG_RSP; - } - - auto response = - ConfigurationResponseBuilder::Create(signal_id.Value(), channel->GetRemoteCid(), - is_continuation, result, std::move(rsp_options)); - enqueue_buffer_->Enqueue(std::move(response), handler_); -} - -void ClassicSignallingManager::SendInitialConfigRequest(Cid local_cid) { - auto channel = channel_allocator_->FindChannelByCid(local_cid); - auto psm = channel->GetPsm(); - auto& configuration_state = channel_configuration_[local_cid]; - auto* service = dynamic_service_manager_->GetService(psm); - auto initial_config = service->GetConfigOption(); - - auto mtu_configuration = std::make_unique<MtuConfigurationOption>(); - mtu_configuration->mtu_ = initial_config.incoming_mtu; - - auto fcs_option = std::make_unique<FrameCheckSequenceOption>(); - fcs_option->fcs_type_ = FcsType::NO_FCS; - configuration_state.fcs_type_ = FcsType::NO_FCS; - if (link_->GetRemoteSupportsFcs()) { - fcs_option->fcs_type_ = FcsType::DEFAULT; - configuration_state.fcs_type_ = FcsType::DEFAULT; - } - - auto retransmission_flow_control_configuration = - std::make_unique<RetransmissionAndFlowControlConfigurationOption>(); - switch (initial_config.channel_mode) { - case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC: - retransmission_flow_control_configuration->mode_ = - RetransmissionAndFlowControlModeOption::L2CAP_BASIC; - configuration_state.retransmission_and_flow_control_mode_ = - RetransmissionAndFlowControlModeOption::L2CAP_BASIC; - break; - case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode:: - ENHANCED_RETRANSMISSION: - case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode:: - ENHANCED_RETRANSMISSION_OPTIONAL: - retransmission_flow_control_configuration->mode_ = - RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION; - configuration_state.retransmission_and_flow_control_mode_ = - RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION; - // TODO: Decide where to put initial values - retransmission_flow_control_configuration->tx_window_size_ = 10; - retransmission_flow_control_configuration->max_transmit_ = 20; - retransmission_flow_control_configuration->retransmission_time_out_ = 2000; - retransmission_flow_control_configuration->monitor_time_out_ = 12000; - retransmission_flow_control_configuration->maximum_pdu_size_ = 1010; - break; - } - configuration_state.local_retransmission_and_flow_control_ = - *retransmission_flow_control_configuration; - - std::vector<std::unique_ptr<ConfigurationOption>> config; - config.emplace_back(std::move(mtu_configuration)); - if (initial_config.channel_mode != - DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC) { - config.emplace_back(std::move(retransmission_flow_control_configuration)); - config.emplace_back(std::move(fcs_option)); - } - send_configuration_request(channel->GetRemoteCid(), std::move(config)); -} - -void ClassicSignallingManager::negotiate_configuration( - Cid cid, Continuation, std::vector<std::unique_ptr<ConfigurationOption>> options) { - auto channel = channel_allocator_->FindChannelByCid(cid); - auto& configuration_state = channel_configuration_[channel->GetCid()]; - std::vector<std::unique_ptr<ConfigurationOption>> negotiation_config; - bool can_negotiate = false; - for (auto& option : options) { - switch (option->type_) { - case ConfigurationOptionType::MTU: { - // MTU is non-negotiable option. Use default mtu size - auto mtu_configuration = std::make_unique<MtuConfigurationOption>(); - mtu_configuration->mtu_ = kDefaultClassicMtu; - negotiation_config.emplace_back(std::move(mtu_configuration)); - can_negotiate = true; - break; - } - case ConfigurationOptionType::FRAME_CHECK_SEQUENCE: - case ConfigurationOptionType::FLUSH_TIMEOUT: { - // TODO: Handle these two configuration options negotiation. - can_negotiate = true; - break; - } - case ConfigurationOptionType::RETRANSMISSION_AND_FLOW_CONTROL: { - auto* config = RetransmissionAndFlowControlConfigurationOption::Specialize(option.get()); - if (config->mode_ == RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION) { - configuration_state.retransmission_and_flow_control_mode_ = config->mode_; - configuration_state.local_retransmission_and_flow_control_ = *config; - negotiation_config.emplace_back( - std::make_unique<RetransmissionAndFlowControlConfigurationOption>(*config)); - } else if (config->mode_ == RetransmissionAndFlowControlModeOption::L2CAP_BASIC) { - auto initial_config_option = - dynamic_service_manager_->GetService(channel->GetPsm())->GetConfigOption(); - if (initial_config_option.channel_mode == - DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode:: - ENHANCED_RETRANSMISSION) { - // ERTM mandatory is not allow negotiating of retransmission and flow control mode, - // disconnect channel - SendDisconnectionRequest(channel->GetCid(), channel->GetRemoteCid()); - return; - } else if (initial_config_option.channel_mode == - DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode:: - ENHANCED_RETRANSMISSION_OPTIONAL) { - can_negotiate = true; - negotiation_config.emplace_back( - std::make_unique<RetransmissionAndFlowControlConfigurationOption>(*config)); - } - } else { - // Not support other retransmission and flow control mode, disconnect channel. - SendDisconnectionRequest(channel->GetCid(), channel->GetRemoteCid()); - return; - } - break; - } - default: - log::warn("Received some unsupported configuration option: {}", - static_cast<int>(option->type_)); - return; - } - } - if (can_negotiate) { - send_configuration_request(channel->GetRemoteCid(), std::move(negotiation_config)); - } else { - log::info("No suggested parameter received"); - } -} - -void ClassicSignallingManager::OnConfigurationResponse( - SignalId signal_id, Cid cid, Continuation is_continuation, - ConfigurationResponseResult result, - std::vector<std::unique_ptr<ConfigurationOption>> options) { - if (command_just_sent_.signal_id_ != signal_id || - command_just_sent_.command_code_ != CommandCode::CONFIGURATION_REQUEST) { - log::warn("Unexpected response: no pending request. Expected signal id {} type {}, got {}", - command_just_sent_.signal_id_.Value(), - CommandCodeText(command_just_sent_.command_code_).data(), signal_id.Value()); - return; - } - - auto channel = channel_allocator_->FindChannelByCid(cid); - if (channel == nullptr) { - log::warn("Configuration request for an unknown channel"); - handle_send_next_command(); - return; - } - - switch (result) { - default: - case ConfigurationResponseResult::REJECTED: - case ConfigurationResponseResult::UNKNOWN_OPTIONS: - case ConfigurationResponseResult::FLOW_SPEC_REJECTED: - log::warn("Configuration response not SUCCESS: {}", ConfigurationResponseResultText(result)); - alarm_.Cancel(); - handle_send_next_command(); - return; - - case ConfigurationResponseResult::PENDING: - alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, - common::Unretained(this)), - kTimeout); - return; - - case ConfigurationResponseResult::UNACCEPTABLE_PARAMETERS: - log::info("Configuration response with unacceptable parameters"); - alarm_.Cancel(); - negotiate_configuration(cid, is_continuation, std::move(options)); - handle_send_next_command(); - return; - - case ConfigurationResponseResult::SUCCESS: - break; - } - auto& configuration_state = channel_configuration_[channel->GetCid()]; - - for (auto& option : options) { - switch (option->type_) { - case ConfigurationOptionType::MTU: { - // Since they accepted our MTU, no need to read the new value. - break; - } - case ConfigurationOptionType::FLUSH_TIMEOUT: { - break; - } - case ConfigurationOptionType::RETRANSMISSION_AND_FLOW_CONTROL: { - auto config = RetransmissionAndFlowControlConfigurationOption::Specialize(option.get()); - if (configuration_state.retransmission_and_flow_control_mode_ != config->mode_) { - SendDisconnectionRequest(cid, channel->GetRemoteCid()); - alarm_.Cancel(); - handle_send_next_command(); - return; - } - configuration_state.local_retransmission_and_flow_control_ = *config; - break; - } - case ConfigurationOptionType::FRAME_CHECK_SEQUENCE: { - configuration_state.fcs_type_ = - FrameCheckSequenceOption::Specialize(option.get())->fcs_type_; - break; - } - default: - log::warn("Received some unsupported configuration option: {}", - static_cast<int>(option->type_)); - alarm_.Cancel(); - handle_send_next_command(); - return; - } - } - - if (configuration_state.state_ == ChannelConfigurationState::State::WAIT_CONFIG_RSP) { - std::unique_ptr<DynamicChannel> user_channel = - std::make_unique<DynamicChannel>(channel, handler_); - if (channel->local_initiated_) { - link_->NotifyChannelCreation(cid, std::move(user_channel)); - } else { - dynamic_service_manager_->GetService(channel->GetPsm()) - ->NotifyChannelCreation(std::move(user_channel)); - } - configuration_state.state_ = ChannelConfigurationState::State::CONFIGURED; - data_pipeline_manager_->AttachChannel(cid, channel, - l2cap::internal::DataPipelineManager::ChannelMode::BASIC); - data_pipeline_manager_->UpdateClassicConfiguration(cid, configuration_state); - } else if (configuration_state.state_ == ChannelConfigurationState::State::WAIT_CONFIG_REQ_RSP) { - configuration_state.state_ = ChannelConfigurationState::State::WAIT_CONFIG_REQ; - } - - alarm_.Cancel(); - handle_send_next_command(); -} - -void ClassicSignallingManager::OnDisconnectionRequest(SignalId signal_id, Cid cid, Cid remote_cid) { - // TODO: check cid match - auto channel = channel_allocator_->FindChannelByCid(cid); - if (channel == nullptr) { - log::warn("Disconnect request for an unknown channel"); - return; - } - auto builder = DisconnectionResponseBuilder::Create(signal_id.Value(), cid, remote_cid); - enqueue_buffer_->Enqueue(std::move(builder), handler_); - channel->OnClosed(hci::ErrorCode::SUCCESS); - auto& configuration_state = channel_configuration_[channel->GetCid()]; - if (configuration_state.state_ == configuration_state.CONFIGURED) { - data_pipeline_manager_->DetachChannel(cid); - } - link_->FreeDynamicChannel(cid); - channel_configuration_.erase(cid); -} - -void ClassicSignallingManager::OnDisconnectionResponse(SignalId signal_id, Cid /* remote_cid */, - Cid cid) { - if (command_just_sent_.signal_id_ != signal_id || - command_just_sent_.command_code_ != CommandCode::DISCONNECTION_REQUEST) { - log::warn("Unexpected response: no pending request. Expected signal id {} type {}, got {}", - command_just_sent_.signal_id_.Value(), - CommandCodeText(command_just_sent_.command_code_).data(), signal_id.Value()); - return; - } - - alarm_.Cancel(); - - auto channel = channel_allocator_->FindChannelByCid(cid); - if (channel == nullptr) { - log::warn("Disconnect response for an unknown channel"); - handle_send_next_command(); - return; - } - - channel->OnClosed(hci::ErrorCode::SUCCESS); - auto& configuration_state = channel_configuration_[cid]; - if (configuration_state.state_ == configuration_state.CONFIGURED) { - data_pipeline_manager_->DetachChannel(cid); - } - link_->FreeDynamicChannel(cid); - handle_send_next_command(); - channel_configuration_.erase(cid); -} - -void ClassicSignallingManager::OnEchoRequest(SignalId signal_id, - const PacketView<kLittleEndian>& packet) { - std::vector<uint8_t> packet_vector{packet.begin(), packet.end()}; - auto raw_builder = std::make_unique<packet::RawBuilder>(); - raw_builder->AddOctets(packet_vector); - auto builder = EchoResponseBuilder::Create(signal_id.Value(), std::move(raw_builder)); - enqueue_buffer_->Enqueue(std::move(builder), handler_); -} - -void ClassicSignallingManager::OnEchoResponse(SignalId signal_id, - const PacketView<kLittleEndian>& /* packet */) { - if (command_just_sent_.signal_id_ != signal_id || - command_just_sent_.command_code_ != CommandCode::ECHO_REQUEST) { - log::warn("Unexpected response: no pending request. Expected signal id {} type {}, got {}", - command_just_sent_.signal_id_.Value(), - CommandCodeText(command_just_sent_.command_code_).data(), signal_id.Value()); - return; - } - log::info("Echo response received"); - alarm_.Cancel(); - handle_send_next_command(); -} - -void ClassicSignallingManager::OnInformationRequest(SignalId signal_id, - InformationRequestInfoType type) { - switch (type) { - case InformationRequestInfoType::CONNECTIONLESS_MTU: { - auto response = InformationResponseConnectionlessMtuBuilder::Create( - signal_id.Value(), InformationRequestResult::SUCCESS, kDefaultClassicMtu); - enqueue_buffer_->Enqueue(std::move(response), handler_); - break; - } - case InformationRequestInfoType::EXTENDED_FEATURES_SUPPORTED: { - auto response = InformationResponseExtendedFeaturesBuilder::Create( - signal_id.Value(), InformationRequestResult::SUCCESS, 0, 0, 0, 1 /* ERTM */, - 0 /* Streaming mode */, 1 /* FCS */, 0, 1 /* Fixed Channels */, 0, 0, 0 /* COC */); - enqueue_buffer_->Enqueue(std::move(response), handler_); - break; - } - case InformationRequestInfoType::FIXED_CHANNELS_SUPPORTED: { - auto response = InformationResponseFixedChannelsBuilder::Create( - signal_id.Value(), InformationRequestResult::SUCCESS, - fixed_service_manager_->GetSupportedFixedChannelMask()); - enqueue_buffer_->Enqueue(std::move(response), handler_); - break; - } - } -} - -void ClassicSignallingManager::OnInformationResponse(SignalId signal_id, - const InformationResponseView& response) { - if (command_just_sent_.signal_id_ != signal_id || - command_just_sent_.command_code_ != CommandCode::INFORMATION_REQUEST) { - log::warn("Unexpected response: no pending request. Expected signal id {} type {}, got {}", - command_just_sent_.signal_id_.Value(), - CommandCodeText(command_just_sent_.command_code_).data(), signal_id.Value()); - return; - } - - auto type = response.GetInfoType(); - switch (type) { - case InformationRequestInfoType::CONNECTIONLESS_MTU: { - auto view = InformationResponseConnectionlessMtuView::Create(response); - if (!view.IsValid()) { - log::warn("Invalid InformationResponseConnectionlessMtu received"); - return; - } - link_->SetRemoteConnectionlessMtu(view.GetConnectionlessMtu()); - break; - } - case InformationRequestInfoType::EXTENDED_FEATURES_SUPPORTED: { - auto view = InformationResponseExtendedFeaturesView::Create(response); - if (!view.IsValid()) { - log::warn("Invalid InformationResponseExtendedFeatures received"); - return; - } - link_->OnRemoteExtendedFeatureReceived(view.GetEnhancedRetransmissionMode(), - view.GetFcsOption()); - // We don't care about other parameters - break; - } - case InformationRequestInfoType::FIXED_CHANNELS_SUPPORTED: { - auto view = InformationResponseFixedChannelsView::Create(response); - if (!view.IsValid()) { - log::warn("Invalid InformationResponseFixedChannel received"); - return; - } - // We don't use fixed channels (connectionless or BR/EDR security) for now so we don't care - break; - } - } - - alarm_.Cancel(); - handle_send_next_command(); -} - -void ClassicSignallingManager::on_incoming_packet() { - auto packet = signalling_channel_->GetQueueUpEnd()->TryDequeue(); - auto command_list = GetCommandsFromPacketView(*packet); - for (auto& command : command_list) { - handle_one_command(command); - } -} - -void ClassicSignallingManager::handle_one_command(ControlView control_packet_view) { - if (!control_packet_view.IsValid()) { - log::warn("Invalid signalling packet received"); - return; - } - auto code = control_packet_view.GetCode(); - switch (code) { - case CommandCode::COMMAND_REJECT: { - CommandRejectView command_reject_view = CommandRejectView::Create(control_packet_view); - if (!command_reject_view.IsValid()) { - return; - } - OnCommandReject(command_reject_view); - return; - } - case CommandCode::CONNECTION_REQUEST: { - ConnectionRequestView connection_request_view = - ConnectionRequestView::Create(control_packet_view); - if (!connection_request_view.IsValid()) { - return; - } - OnConnectionRequest(control_packet_view.GetIdentifier(), connection_request_view.GetPsm(), - connection_request_view.GetSourceCid()); - return; - } - case CommandCode::CONNECTION_RESPONSE: { - ConnectionResponseView connection_response_view = - ConnectionResponseView::Create(control_packet_view); - if (!connection_response_view.IsValid()) { - return; - } - OnConnectionResponse( - connection_response_view.GetIdentifier(), - connection_response_view.GetDestinationCid(), connection_response_view.GetSourceCid(), - connection_response_view.GetResult(), connection_response_view.GetStatus()); - return; - } - case CommandCode::CONFIGURATION_REQUEST: { - ConfigurationRequestView configuration_request_view = - ConfigurationRequestView::Create(control_packet_view); - if (!configuration_request_view.IsValid()) { - return; - } - OnConfigurationRequest(configuration_request_view.GetIdentifier(), - configuration_request_view.GetDestinationCid(), - configuration_request_view.GetContinuation(), - configuration_request_view.GetConfig()); - return; - } - case CommandCode::CONFIGURATION_RESPONSE: { - ConfigurationResponseView configuration_response_view = - ConfigurationResponseView::Create(control_packet_view); - if (!configuration_response_view.IsValid()) { - return; - } - OnConfigurationResponse(configuration_response_view.GetIdentifier(), - configuration_response_view.GetSourceCid(), - configuration_response_view.GetContinuation(), - configuration_response_view.GetResult(), - configuration_response_view.GetConfig()); - return; - } - case CommandCode::DISCONNECTION_REQUEST: { - DisconnectionRequestView disconnection_request_view = - DisconnectionRequestView::Create(control_packet_view); - if (!disconnection_request_view.IsValid()) { - return; - } - OnDisconnectionRequest(disconnection_request_view.GetIdentifier(), - disconnection_request_view.GetDestinationCid(), - disconnection_request_view.GetSourceCid()); - return; - } - case CommandCode::DISCONNECTION_RESPONSE: { - DisconnectionResponseView disconnection_response_view = - DisconnectionResponseView::Create(control_packet_view); - if (!disconnection_response_view.IsValid()) { - return; - } - OnDisconnectionResponse(disconnection_response_view.GetIdentifier(), - disconnection_response_view.GetDestinationCid(), - disconnection_response_view.GetSourceCid()); - return; - } - case CommandCode::ECHO_REQUEST: { - EchoRequestView echo_request_view = EchoRequestView::Create(control_packet_view); - if (!echo_request_view.IsValid()) { - return; - } - OnEchoRequest(echo_request_view.GetIdentifier(), echo_request_view.GetPayload()); - return; - } - case CommandCode::ECHO_RESPONSE: { - EchoResponseView echo_response_view = EchoResponseView::Create(control_packet_view); - if (!echo_response_view.IsValid()) { - return; - } - OnEchoResponse(echo_response_view.GetIdentifier(), echo_response_view.GetPayload()); - return; - } - case CommandCode::INFORMATION_REQUEST: { - InformationRequestView information_request_view = - InformationRequestView::Create(control_packet_view); - if (!information_request_view.IsValid()) { - return; - } - OnInformationRequest(information_request_view.GetIdentifier(), - information_request_view.GetInfoType()); - return; - } - case CommandCode::INFORMATION_RESPONSE: { - InformationResponseView information_response_view = - InformationResponseView::Create(control_packet_view); - if (!information_response_view.IsValid()) { - return; - } - OnInformationResponse(information_response_view.GetIdentifier(), information_response_view); - return; - } - case CommandCode::CREDIT_BASED_CONNECTION_REQUEST: { - CreditBasedConnectionRequestView request_view = - CreditBasedConnectionRequestView::Create(control_packet_view); - if (!request_view.IsValid()) { - return; - } - return; - } - case CommandCode::CREDIT_BASED_CONNECTION_RESPONSE: { - CreditBasedConnectionResponseView response_view = - CreditBasedConnectionResponseView::Create(control_packet_view); - if (!response_view.IsValid()) { - return; - } - return; - } - case CommandCode::CREDIT_BASED_RECONFIGURE_REQUEST: { - CreditBasedReconfigureRequestView request_view = - CreditBasedReconfigureRequestView::Create(control_packet_view); - if (!request_view.IsValid()) { - return; - } - return; - } - case CommandCode::CREDIT_BASED_RECONFIGURE_RESPONSE: { - CreditBasedReconfigureResponseView response_view = - CreditBasedReconfigureResponseView::Create(control_packet_view); - if (!response_view.IsValid()) { - return; - } - return; - } - case CommandCode::FLOW_CONTROL_CREDIT: { - FlowControlCreditView credit_view = FlowControlCreditView::Create(control_packet_view); - if (!credit_view.IsValid()) { - return; - } - return; - } - default: - log::warn("Unhandled event 0x{:x}", static_cast<int>(code)); - auto builder = CommandRejectNotUnderstoodBuilder::Create(control_packet_view.GetIdentifier()); - enqueue_buffer_->Enqueue(std::move(builder), handler_); - return; - } -} - -void ClassicSignallingManager::send_connection_response(SignalId signal_id, Cid remote_cid, - Cid local_cid, - ConnectionResponseResult result, - ConnectionResponseStatus status) { - auto builder = ConnectionResponseBuilder::Create(signal_id.Value(), local_cid, remote_cid, result, - status); - enqueue_buffer_->Enqueue(std::move(builder), handler_); -} - -void ClassicSignallingManager::on_command_timeout() { - log::warn("Response time out"); - if (command_just_sent_.signal_id_ == kInvalidSignalId) { - log::error("No pending command"); - return; - } - log::warn("Response time out for {}", CommandCodeText(command_just_sent_.command_code_)); - switch (command_just_sent_.command_code_) { - case CommandCode::CONNECTION_REQUEST: { - DynamicChannelManager::ConnectionResult connection_result{ - .connection_result_code = - DynamicChannelManager::ConnectionResultCode::FAIL_L2CAP_ERROR, - .hci_error = hci::ErrorCode::SUCCESS, - .l2cap_connection_response_result = ConnectionResponseResult::NO_RESOURCES_AVAILABLE, - }; - link_->OnOutgoingConnectionRequestFail(command_just_sent_.source_cid_, connection_result); - break; - } - case CommandCode::CONFIGURATION_REQUEST: { - auto channel = - channel_allocator_->FindChannelByRemoteCid(command_just_sent_.destination_cid_); - SendDisconnectionRequest(channel->GetCid(), channel->GetRemoteCid()); - return; - } - case CommandCode::INFORMATION_REQUEST: { - if (command_just_sent_.info_type_ == - InformationRequestInfoType::EXTENDED_FEATURES_SUPPORTED) { - link_->OnRemoteExtendedFeatureReceived(false, false); - } - break; - } - default: - break; - } - handle_send_next_command(); -} - -void ClassicSignallingManager::handle_send_next_command() { - command_just_sent_.signal_id_ = kInvalidSignalId; - if (pending_commands_.empty()) { - return; - } - command_just_sent_ = std::move(pending_commands_.front()); - pending_commands_.pop(); - - auto signal_id = command_just_sent_.signal_id_; - auto psm = command_just_sent_.psm_; - auto source_cid = command_just_sent_.source_cid_; - auto destination_cid = command_just_sent_.destination_cid_; - auto info_type = command_just_sent_.info_type_; - auto config = std::move(command_just_sent_.config_); - switch (command_just_sent_.command_code_) { - case CommandCode::CONNECTION_REQUEST: { - auto builder = ConnectionRequestBuilder::Create(signal_id.Value(), psm, source_cid); - enqueue_buffer_->Enqueue(std::move(builder), handler_); - alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, - common::Unretained(this)), - kTimeout); - break; - } - case CommandCode::CONFIGURATION_REQUEST: { - auto builder = ConfigurationRequestBuilder::Create(signal_id.Value(), destination_cid, - Continuation::END, std::move(config)); - enqueue_buffer_->Enqueue(std::move(builder), handler_); - alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, - common::Unretained(this)), - kTimeout); - break; - } - case CommandCode::DISCONNECTION_REQUEST: { - auto builder = - DisconnectionRequestBuilder::Create(signal_id.Value(), destination_cid, source_cid); - enqueue_buffer_->Enqueue(std::move(builder), handler_); - alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, - common::Unretained(this)), - kTimeout); - break; - } - case CommandCode::INFORMATION_REQUEST: { - auto builder = InformationRequestBuilder::Create(signal_id.Value(), info_type); - enqueue_buffer_->Enqueue(std::move(builder), handler_); - alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, - common::Unretained(this)), - kTimeout); - break; - } - default: - log::warn("Unsupported command code 0x{:x}", - static_cast<int>(command_just_sent_.command_code_)); - } -} - -} // namespace internal -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/internal/signalling_manager.h b/system/gd/l2cap/classic/internal/signalling_manager.h deleted file mode 100644 index aa3f2c77ef..0000000000 --- a/system/gd/l2cap/classic/internal/signalling_manager.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <cstdint> -#include <queue> -#include <vector> - -#include "l2cap/cid.h" -#include "l2cap/classic/internal/channel_configuration_state.h" -#include "l2cap/classic/internal/dynamic_channel_service_manager_impl.h" -#include "l2cap/classic/internal/fixed_channel_impl.h" -#include "l2cap/classic/internal/fixed_channel_service_manager_impl.h" -#include "l2cap/internal/data_pipeline_manager.h" -#include "l2cap/internal/dynamic_channel_allocator.h" -#include "l2cap/l2cap_packets.h" -#include "l2cap/psm.h" -#include "l2cap/signal_id.h" -#include "os/alarm.h" -#include "os/handler.h" -#include "os/queue.h" -#include "packet/raw_builder.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace internal { - -struct PendingCommand { - SignalId signal_id_ = kInvalidSignalId; - CommandCode command_code_; - Psm psm_; - Cid source_cid_; - Cid destination_cid_; - InformationRequestInfoType info_type_; - std::vector<std::unique_ptr<ConfigurationOption>> config_; -}; - -class Link; - -class ClassicSignallingManager { -public: - ClassicSignallingManager( - os::Handler* handler, Link* link, - l2cap::internal::DataPipelineManager* data_pipeline_manager, - classic::internal::DynamicChannelServiceManagerImpl* dynamic_service_manager, - l2cap::internal::DynamicChannelAllocator* channel_allocator, - classic::internal::FixedChannelServiceManagerImpl* fixed_service_manager); - - virtual ~ClassicSignallingManager(); - - void OnCommandReject(CommandRejectView command_reject_view); - - void SendConnectionRequest(Psm psm, Cid local_cid); - - void SendInitialConfigRequest(Cid local_cid); - - void SendDisconnectionRequest(Cid local_cid, Cid remote_cid); - - void SendInformationRequest(InformationRequestInfoType type); - - void SendEchoRequest(std::unique_ptr<packet::RawBuilder> payload); - - void CancelAlarm(); - - void OnConnectionRequest(SignalId signal_id, Psm psm, Cid remote_cid); - - void OnConnectionResponse(SignalId signal_id, Cid remote_cid, Cid cid, - ConnectionResponseResult result, ConnectionResponseStatus status); - - void OnDisconnectionRequest(SignalId signal_id, Cid cid, Cid remote_cid); - - void OnDisconnectionResponse(SignalId signal_id, Cid cid, Cid remote_cid); - - void OnConfigurationRequest(SignalId signal_id, Cid cid, Continuation is_continuation, - std::vector<std::unique_ptr<ConfigurationOption>>); - - void OnConfigurationResponse(SignalId signal_id, Cid cid, Continuation is_continuation, - ConfigurationResponseResult result, - std::vector<std::unique_ptr<ConfigurationOption>>); - - void OnEchoRequest(SignalId signal_id, const PacketView<kLittleEndian>& packet); - - void OnEchoResponse(SignalId signal_id, const PacketView<kLittleEndian>& packet); - - void OnInformationRequest(SignalId signal_id, InformationRequestInfoType type); - - void OnInformationResponse(SignalId signal_id, const InformationResponseView& response); - - enum class SecurityEnforcementType { - LINK_KEY, - ENCRYPTION, - }; - void on_security_result_for_outgoing(SecurityEnforcementType type, Psm psm, Cid local_cid, - bool result); - -private: - void on_incoming_packet(); - void handle_one_command(ControlView control_view); - void send_connection_response(SignalId signal_id, Cid remote_cid, Cid local_cid, - ConnectionResponseResult result, ConnectionResponseStatus status); - void on_command_timeout(); - void handle_send_next_command(); - - void negotiate_configuration(Cid cid, Continuation is_continuation, - std::vector<std::unique_ptr<ConfigurationOption>>); - - void send_configuration_request(Cid remote_cid, - std::vector<std::unique_ptr<ConfigurationOption>> config); - void on_security_result_for_incoming(Psm psm, Cid remote_cid, SignalId signal_id, bool result); - - os::Handler* handler_; - Link* link_; - l2cap::internal::DataPipelineManager* data_pipeline_manager_; - std::shared_ptr<classic::internal::FixedChannelImpl> signalling_channel_; - DynamicChannelServiceManagerImpl* dynamic_service_manager_; - l2cap::internal::DynamicChannelAllocator* channel_allocator_; - FixedChannelServiceManagerImpl* fixed_service_manager_; - std::unique_ptr<os::EnqueueBuffer<packet::BasePacketBuilder>> enqueue_buffer_; - std::queue<PendingCommand> pending_commands_; - PendingCommand command_just_sent_; - os::Alarm alarm_; - SignalId next_signal_id_ = kInitialSignalId; - std::unordered_map<Cid, ChannelConfigurationState> channel_configuration_; -}; - -} // namespace internal -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/internal/signalling_manager_test.cc b/system/gd/l2cap/classic/internal/signalling_manager_test.cc deleted file mode 100644 index f28a2886c8..0000000000 --- a/system/gd/l2cap/classic/internal/signalling_manager_test.cc +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/classic/internal/signalling_manager.h" - -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include "l2cap/classic/internal/dynamic_channel_service_manager_impl_mock.h" -#include "l2cap/classic/internal/fixed_channel_service_manager_impl_mock.h" -#include "l2cap/classic/internal/link_mock.h" -#include "l2cap/internal/parameter_provider_mock.h" - -using ::testing::_; -using ::testing::Return; - -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace internal { -namespace { - -class L2capClassicSignallingManagerTest : public ::testing::Test { -public: - static void SyncHandler(os::Handler* handler) { - std::promise<void> promise; - auto future = promise.get_future(); - handler->Post(common::BindOnce(&std::promise<void>::set_value, common::Unretained(&promise))); - future.wait_for(std::chrono::milliseconds(3)); - } - -protected: - void SetUp() override { - thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL); - l2cap_handler_ = new os::Handler(thread_); - } - - void TearDown() override { - l2cap_handler_->Clear(); - delete l2cap_handler_; - delete thread_; - } - - os::Thread* thread_ = nullptr; - os::Handler* l2cap_handler_ = nullptr; -}; - -TEST_F(L2capClassicSignallingManagerTest, precondition) {} - -} // namespace -} // namespace internal -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/l2cap_classic_module.cc b/system/gd/l2cap/classic/l2cap_classic_module.cc deleted file mode 100644 index afb0f4ef8f..0000000000 --- a/system/gd/l2cap/classic/l2cap_classic_module.cc +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright 2019 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. - */ -#define LOG_TAG "l2cap2" - -#include "l2cap/classic/l2cap_classic_module.h" - -#include <future> -#include <memory> - -#include "dumpsys_data_generated.h" -#include "hci/acl_manager.h" -#include "hci/address.h" -#include "l2cap/classic/internal/dumpsys_helper.h" -#include "l2cap/classic/internal/dynamic_channel_service_manager_impl.h" -#include "l2cap/classic/internal/fixed_channel_service_manager_impl.h" -#include "l2cap/classic/internal/link_manager.h" -#include "l2cap/internal/parameter_provider.h" -#include "l2cap_classic_module_generated.h" -#include "module.h" -#include "os/handler.h" -#include "os/log.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { - -const ModuleFactory L2capClassicModule::Factory = - ModuleFactory([]() { return new L2capClassicModule(); }); - -static SecurityEnforcementRejectAllImpl default_security_module_impl_; - -struct L2capClassicModule::impl { - impl(os::Handler* l2cap_handler, hci::AclManager* acl_manager) - : l2cap_handler_(l2cap_handler), acl_manager_(acl_manager) { - dynamic_channel_service_manager_impl_.SetSecurityEnforcementInterface( - &default_security_module_impl_); - dumpsys_helper_ = std::make_unique<internal::DumpsysHelper>(link_manager_); - } - os::Handler* l2cap_handler_; - hci::AclManager* acl_manager_; - l2cap::internal::ParameterProvider parameter_provider_; - internal::FixedChannelServiceManagerImpl fixed_channel_service_manager_impl_{l2cap_handler_}; - internal::DynamicChannelServiceManagerImpl dynamic_channel_service_manager_impl_{l2cap_handler_}; - internal::LinkManager link_manager_{l2cap_handler_, acl_manager_, - &fixed_channel_service_manager_impl_, - &dynamic_channel_service_manager_impl_, ¶meter_provider_}; - std::unique_ptr<internal::DumpsysHelper> dumpsys_helper_; - - struct SecurityInterfaceImpl : public SecurityInterface { - SecurityInterfaceImpl(impl* module_impl) : module_impl_(module_impl) {} - - void RegisterLinkSecurityInterfaceListener(os::Handler* handler, - LinkSecurityInterfaceListener* listener) { - log::assert_that(!registered_, "assert failed: !registered_"); - module_impl_->link_manager_.RegisterLinkSecurityInterfaceListener(handler, listener); - registered_ = true; - } - - void InitiateConnectionForSecurity(hci::Address remote) override { - log::assert_that(registered_, "assert failed: registered_"); - module_impl_->link_manager_.InitiateConnectionForSecurity(remote); - } - - void Unregister() override { - log::assert_that(registered_, "assert failed: registered_"); - module_impl_->link_manager_.RegisterLinkSecurityInterfaceListener(nullptr, nullptr); - registered_ = false; - } - impl* module_impl_; - bool registered_ = false; - } security_interface_impl_{this}; - - void Dump(std::promise<flatbuffers::Offset<L2capClassicModuleData>> promise, - flatbuffers::FlatBufferBuilder* fb_builder) const; -}; - -L2capClassicModule::L2capClassicModule() {} - -L2capClassicModule::~L2capClassicModule() {} - -void L2capClassicModule::ListDependencies(ModuleList* list) const { list->add<hci::AclManager>(); } - -void L2capClassicModule::Start() { - pimpl_ = std::make_unique<impl>(GetHandler(), GetDependency<hci::AclManager>()); -} - -void L2capClassicModule::Stop() { pimpl_.reset(); } - -std::string L2capClassicModule::ToString() const { return "L2cap Classic Module"; } - -std::unique_ptr<FixedChannelManager> L2capClassicModule::GetFixedChannelManager() { - return std::unique_ptr<FixedChannelManager>( - new FixedChannelManager(&pimpl_->fixed_channel_service_manager_impl_, - &pimpl_->link_manager_, pimpl_->l2cap_handler_)); -} - -std::unique_ptr<DynamicChannelManager> L2capClassicModule::GetDynamicChannelManager() { - return std::unique_ptr<DynamicChannelManager>( - new DynamicChannelManager(&pimpl_->dynamic_channel_service_manager_impl_, - &pimpl_->link_manager_, pimpl_->l2cap_handler_)); -} - -void L2capClassicModule::InjectSecurityEnforcementInterface( - SecurityEnforcementInterface* security_enforcement_interface) { - if (security_enforcement_interface != nullptr) { - pimpl_->dynamic_channel_service_manager_impl_.SetSecurityEnforcementInterface( - security_enforcement_interface); - } else { - pimpl_->dynamic_channel_service_manager_impl_.SetSecurityEnforcementInterface( - &default_security_module_impl_); - } -} - -SecurityInterface* L2capClassicModule::GetSecurityInterface( - os::Handler* handler, LinkSecurityInterfaceListener* listener) { - pimpl_->security_interface_impl_.RegisterLinkSecurityInterfaceListener(handler, listener); - return &pimpl_->security_interface_impl_; -} - -void L2capClassicModule::SetLinkPropertyListener(os::Handler* handler, - LinkPropertyListener* listener) { - pimpl_->link_manager_.RegisterLinkPropertyListener(handler, listener); -} - -void L2capClassicModule::impl::Dump( - std::promise<flatbuffers::Offset<L2capClassicModuleData>> promise, - flatbuffers::FlatBufferBuilder* fb_builder) const { - auto title = fb_builder->CreateString("----- L2cap Classic Dumpsys -----"); - - std::vector<flatbuffers::Offset<bluetooth::l2cap::classic::LinkData>> link_offsets = - dumpsys_helper_->DumpActiveLinks(fb_builder); - - auto active_links = fb_builder->CreateVector(link_offsets); - - L2capClassicModuleDataBuilder builder(*fb_builder); - builder.add_title(title); - builder.add_active_links(active_links); - flatbuffers::Offset<L2capClassicModuleData> dumpsys_data = builder.Finish(); - - promise.set_value(dumpsys_data); -} - -DumpsysDataFinisher L2capClassicModule::GetDumpsysData( - flatbuffers::FlatBufferBuilder* fb_builder) const { - log::assert_that(fb_builder != nullptr, "assert failed: fb_builder != nullptr"); - - std::promise<flatbuffers::Offset<L2capClassicModuleData>> promise; - auto future = promise.get_future(); - pimpl_->Dump(std::move(promise), fb_builder); - - auto dumpsys_data = future.get(); - - return [dumpsys_data](DumpsysDataBuilder* dumpsys_builder) { - dumpsys_builder->add_l2cap_classic_dumpsys_data(dumpsys_data); - }; -} - -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/l2cap_classic_module.fbs b/system/gd/l2cap/classic/l2cap_classic_module.fbs deleted file mode 100644 index f1a102481f..0000000000 --- a/system/gd/l2cap/classic/l2cap_classic_module.fbs +++ /dev/null @@ -1,20 +0,0 @@ -namespace bluetooth.l2cap.classic; - -attribute "privacy"; - -table ChannelData { - cid:int; -} - -table LinkData { - address:string; - dynamic_channels:[ChannelData]; - fixed_channels:[ChannelData]; -} - -table L2capClassicModuleData { - title:string (privacy:"Any"); - active_links:[LinkData] (privacy:"Any"); -} - -root_type L2capClassicModuleData; diff --git a/system/gd/l2cap/classic/l2cap_classic_module.h b/system/gd/l2cap/classic/l2cap_classic_module.h deleted file mode 100644 index 3c21625ca7..0000000000 --- a/system/gd/l2cap/classic/l2cap_classic_module.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2019 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. - */ -#pragma once - -#include <memory> - -#include "l2cap/classic/dynamic_channel_manager.h" -#include "l2cap/classic/fixed_channel_manager.h" -#include "l2cap/classic/link_property_listener.h" -#include "l2cap/classic/link_security_interface.h" -#include "l2cap/classic/security_enforcement_interface.h" -#include "module.h" - -namespace bluetooth { - -namespace security { -class SecurityModule; -} - -namespace l2cap { -namespace classic { - -class L2capClassicModule : public bluetooth::Module { -public: - L2capClassicModule(); - L2capClassicModule(const L2capClassicModule&) = delete; - L2capClassicModule& operator=(const L2capClassicModule&) = delete; - - virtual ~L2capClassicModule(); - - /** - * Get the api to the classic fixed channel l2cap module - */ - virtual std::unique_ptr<FixedChannelManager> GetFixedChannelManager(); - - /** - * Get the api to the classic dynamic channel l2cap module - */ - virtual std::unique_ptr<DynamicChannelManager> GetDynamicChannelManager(); - - static const ModuleFactory Factory; - /** - * Only for the classic security module to inject functionality to enforce security level for a - * connection. When classic security module is stopping, inject nullptr. Note: We expect this only - * to be called during stack startup. This is not synchronized. - */ - virtual void InjectSecurityEnforcementInterface( - SecurityEnforcementInterface* security_enforcement_interface); - - /** - * Get the interface for Security Module to access link function. - * Security Module needs to register the callback for ACL link connected and disconnected. When - * connected, either by incoming or by outgoing connection request, Security Module receives a - * LinkSecurityInterface proxy, which can be used to access some link functionlities. - */ - virtual SecurityInterface* GetSecurityInterface(os::Handler* handler, - LinkSecurityInterfaceListener* listener); - - friend security::SecurityModule; - - /** - * Set the link property listener. - * This is not synchronized. - */ - virtual void SetLinkPropertyListener(os::Handler* handler, LinkPropertyListener* listener); - -protected: - void ListDependencies(ModuleList* list) const override; - - void Start() override; - - void Stop() override; - - std::string ToString() const override; - - DumpsysDataFinisher GetDumpsysData( - flatbuffers::FlatBufferBuilder* builder) const override; // Module - -private: - struct impl; - std::unique_ptr<impl> pimpl_; -}; - -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/l2cap_classic_module_mock.h b/system/gd/l2cap/classic/l2cap_classic_module_mock.h deleted file mode 100644 index d8e894422b..0000000000 --- a/system/gd/l2cap/classic/l2cap_classic_module_mock.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2019 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. - */ -#pragma once - -#include <gmock/gmock.h> - -#include "l2cap/classic/l2cap_classic_module.h" - -// Unit test interfaces -namespace bluetooth { -namespace l2cap { -namespace classic { -namespace testing { - -class MockL2capClassicModule : public L2capClassicModule { -public: - MOCK_METHOD(std::unique_ptr<FixedChannelManager>, GetFixedChannelManager, (), (override)); - MOCK_METHOD(std::unique_ptr<DynamicChannelManager>, GetDynamicChannelManager, (), (override)); -}; - -} // namespace testing -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/link_property_listener.h b/system/gd/l2cap/classic/link_property_listener.h deleted file mode 100644 index cbee2a3ad7..0000000000 --- a/system/gd/l2cap/classic/link_property_listener.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2021 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. - */ - -#pragma once - -#include <memory> - -#include "hci/address.h" -#include "hci/hci_packets.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { - -/** - * This is the listener interface for link property callbacks. - */ -class LinkPropertyListener { -public: - virtual ~LinkPropertyListener() = default; - - /** - * Invoked when an ACL link is connected. - */ - virtual void OnLinkConnected(hci::Address /* remote */, uint16_t /* handle */) {} - - /** - * Invoked when an ACL link is disconnected. - */ - virtual void OnLinkDisconnected(hci::Address /* remote */) {} - - /** - * Invoked when received remote version information for a given link - */ - virtual void OnReadRemoteVersionInformation(hci::ErrorCode /* hci_status */, - hci::Address /* remote */, uint8_t /* lmp_version */, - uint16_t /* manufacturer_name */, - uint16_t /* sub_version */) {} - - /** - * Invoked when received remote features and remote supported features for a - * given link - */ - virtual void OnReadRemoteSupportedFeatures(hci::Address /* remote */, uint64_t /* features */) {} - - /** - * Invoked when received remote features and remote extended features for a - * given link - */ - virtual void OnReadRemoteExtendedFeatures(hci::Address /* remote */, uint8_t /* page_number */, - uint8_t /* max_page_number */, - uint64_t /* features */) {} - - /** - * Invoked when received role change - */ - virtual void OnRoleChange(hci::ErrorCode /* status */, hci::Address /* remote */, - hci::Role /* role */) {} - - /** - * Invoked when received clock offset - */ - virtual void OnReadClockOffset(hci::Address /* remote */, uint16_t /* clock_offset */) {} - - /** - * Invoked when received mode change - */ - virtual void OnModeChange(hci::ErrorCode /* hci_status */, hci::Address /* remote */, - hci::Mode /* mode */, uint16_t /* interval */) {} - - /** - * Invoked when received sniff subrating - */ - virtual void OnSniffSubrating(hci::ErrorCode /* hci_status */, hci::Address /* remote */, - uint16_t /* max_tx_lat */, uint16_t /* max_rx_lat */, - uint16_t /* min_remote_timeout */, - uint16_t /* min_local_timeout */) {} -}; - -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/link_security_interface.h b/system/gd/l2cap/classic/link_security_interface.h deleted file mode 100644 index edb6da2866..0000000000 --- a/system/gd/l2cap/classic/link_security_interface.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2020 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. - */ - -#pragma once - -#include <memory> - -#include "hci/address.h" -#include "hci/hci_packets.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { - -/** - * This is a proxy for Security Module to unregister itself, or to initiate link connection. - */ -class SecurityInterface { -public: - virtual ~SecurityInterface() = default; - - /** - * Page a remote device for ACL connection, when Security Module needs it for pairing. When the - * remote device is connected, Security Module will receive a callback through - * LinkSecurityInterfaceListener. - */ - virtual void InitiateConnectionForSecurity(hci::Address remote) = 0; - - /** - * Unregister the security interface and the LinkSecurityInterfaceListener. - */ - virtual void Unregister() = 0; -}; - -/** - * This is a proxy for Security Module to access some link function. This object is passed to - * Security Module when a link is established. - */ -class LinkSecurityInterface { -public: - virtual ~LinkSecurityInterface() = default; - - virtual hci::Address GetRemoteAddress() = 0; - - /** - * Hold the ACL link connection. Don't disconnect the link until Release() is called. - */ - virtual void Hold() = 0; - - /** - * Release the ACL link connection. This doesn't guarantee link disconnection, if other L2cap - * services are using the link. - */ - virtual void Release() = 0; - - /** - * Force the ACL link to disconnect. - */ - virtual void Disconnect() = 0; - - /** - * Initiate pairing to HCI layer. - */ - virtual void EnsureAuthenticated() = 0; - - /** - * Start encryption on an authenticated link (not necessarily MITM link key). - */ - virtual void EnsureEncrypted() = 0; - - virtual uint16_t GetAclHandle() = 0; - - virtual hci::Role GetRole() { return hci::Role::CENTRAL; } -}; - -class LinkSecurityInterfaceListener { -public: - virtual ~LinkSecurityInterfaceListener() = default; - - /** - * Each time when an ACL link is connected, security manager receives this callback to use - * LinkSecurityInterface functions. - */ - virtual void OnLinkConnected(std::unique_ptr<LinkSecurityInterface>) {} - - /** - * When an ACL link is disconnected, security manager receives this callback. The corresponding - * LinkSecurityInterface is invalidated then. - * @param remote - */ - virtual void OnLinkDisconnected(hci::Address /* remote */) {} - - /** - * Invoked when AuthenticationComplete event is received for a given link - */ - virtual void OnAuthenticationComplete(hci::ErrorCode /* hci_status */, - hci::Address /* remote */) {} - - /** - * Invoked when EncryptionChange event is received for a given link - * @param encrypted - */ - virtual void OnEncryptionChange(hci::Address /* remote */, bool /* encrypted */) {} -}; - -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/security_enforcement_interface.h b/system/gd/l2cap/classic/security_enforcement_interface.h deleted file mode 100644 index ecb2a243ec..0000000000 --- a/system/gd/l2cap/classic/security_enforcement_interface.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2020 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. - */ - -#pragma once - -#include "common/contextual_callback.h" -#include "hci/address_with_type.h" -#include "l2cap/classic/security_policy.h" - -namespace bluetooth { -namespace l2cap { -namespace classic { - -/** - * The interface for Security Module to implement. - */ -class SecurityEnforcementInterface { -public: - virtual ~SecurityEnforcementInterface() = default; - - using ResultCallback = common::ContextualOnceCallback<void(bool)>; - - /** - * Invoked when L2CAP needs to open a channel with given security requirement. When the Security - * Module satisfies the required security level, or cannot satisfy at all, invoke the - * result_callback. - */ - virtual void Enforce(hci::AddressWithType remote, SecurityPolicy policy, - ResultCallback result_callback) = 0; -}; - -/** - * A default implementation which cannot satisfy any security level except - * _SDP_ONLY_NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK. - */ -class SecurityEnforcementRejectAllImpl : public SecurityEnforcementInterface { -public: - void Enforce(hci::AddressWithType /* remote */, SecurityPolicy policy, - ResultCallback result_callback) override { - if (policy == SecurityPolicy::_SDP_ONLY_NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK) { - result_callback(true); - } else { - result_callback(false); - } - } -}; -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/classic/security_policy.h b/system/gd/l2cap/classic/security_policy.h deleted file mode 100644 index dde297f40b..0000000000 --- a/system/gd/l2cap/classic/security_policy.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <cstdint> - -namespace bluetooth { -namespace l2cap { -namespace classic { - -enum class SecurityPolicy { - // Predefined security policies for user to pick - - // Just encryption, but no MITM - ENCRYPTED_TRANSPORT, - - // Implicitly MITM protected - AUTHENTICATED_ENCRYPTED_TRANSPORT, - - // Same as AUTHENTICATED_ENCRYPTED_TRANSPORT - BEST, - - // No security enforced. SDP only. - _SDP_ONLY_NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK, - -}; - -} // namespace classic -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/dynamic_channel.cc b/system/gd/l2cap/dynamic_channel.cc deleted file mode 100644 index 2266857b32..0000000000 --- a/system/gd/l2cap/dynamic_channel.cc +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/dynamic_channel.h" - -#include "common/bind.h" -#include "l2cap/internal/dynamic_channel_impl.h" - -namespace bluetooth { -namespace l2cap { - -hci::AddressWithType DynamicChannel::GetDevice() const { return impl_->GetDevice(); } - -void DynamicChannel::RegisterOnCloseCallback(DynamicChannel::OnCloseCallback on_close_callback) { - l2cap_handler_->CallOn(impl_.get(), &l2cap::internal::DynamicChannelImpl::RegisterOnCloseCallback, - std::move(on_close_callback)); -} - -void DynamicChannel::Close() { - l2cap_handler_->CallOn(impl_.get(), &l2cap::internal::DynamicChannelImpl::Close); -} - -common::BidiQueueEnd<packet::BasePacketBuilder, packet::PacketView<packet::kLittleEndian>>* -DynamicChannel::GetQueueUpEnd() const { - return impl_->GetQueueUpEnd(); -} - -Cid DynamicChannel::HACK_GetRemoteCid() { return impl_->GetRemoteCid(); } - -void DynamicChannel::HACK_SetChannelTxPriority(bool high_priority) { - return impl_->SetChannelTxPriority(high_priority); -} - -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/dynamic_channel.h b/system/gd/l2cap/dynamic_channel.h deleted file mode 100644 index 1af21f1543..0000000000 --- a/system/gd/l2cap/dynamic_channel.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2019 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. - */ -#pragma once - -#include "common/bidi_queue.h" -#include "common/callback.h" -#include "hci/acl_manager.h" -#include "l2cap/cid.h" -#include "os/handler.h" -#include "packet/base_packet_builder.h" -#include "packet/packet_view.h" - -namespace bluetooth { -namespace l2cap { - -namespace internal { -class DynamicChannelImpl; -} // namespace internal - -/** - * L2CAP Dynamic channel object. User needs to call Close() when user no longer wants to use it. - * Otherwise the link won't be disconnected. - */ -class DynamicChannel { -public: - // Should only be constructed by modules that have access to LinkManager - DynamicChannel(std::shared_ptr<l2cap::internal::DynamicChannelImpl> impl, - os::Handler* l2cap_handler) - : impl_(std::move(impl)), l2cap_handler_(l2cap_handler) { - log::assert_that(impl_ != nullptr, "assert failed: impl_ != nullptr"); - log::assert_that(l2cap_handler_ != nullptr, "assert failed: l2cap_handler_ != nullptr"); - } - - hci::AddressWithType GetDevice() const; - - /** - * Register close callback. If close callback is registered, when a channel is closed, the - * channel's resource will only be freed after on_close callback is invoked. Otherwise, if no - * on_close callback is registered, the channel's resource will be freed immediately after - * closing. - * - * @param on_close_callback The callback invoked upon channel closing. - */ - using OnCloseCallback = common::ContextualOnceCallback<void(hci::ErrorCode)>; - void RegisterOnCloseCallback(OnCloseCallback on_close_callback); - - /** - * Indicate that this Dynamic Channel should be closed. OnCloseCallback will be invoked when - * channel close is done. L2cay layer may terminate this ACL connection to free the resource after - * channel is closed. - */ - void Close(); - - /** - * This method will retrieve the data channel queue to send and receive packets. - * - * {@see BidiQueueEnd} - * - * @return The upper end of a bi-directional queue. - */ - common::BidiQueueEnd<packet::BasePacketBuilder, packet::PacketView<packet::kLittleEndian>>* - GetQueueUpEnd() const; - - Cid HACK_GetRemoteCid(); - - /** - * Used by A2dp software encoding to prioritize Tx of this channel - * @param high_priority - */ - void HACK_SetChannelTxPriority(bool high_priority); - -private: - std::shared_ptr<l2cap::internal::DynamicChannelImpl> impl_; - os::Handler* l2cap_handler_; -}; - -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/fcs.cc b/system/gd/l2cap/fcs.cc deleted file mode 100644 index d1b6e1584d..0000000000 --- a/system/gd/l2cap/fcs.cc +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/fcs.h" - -namespace { -// Table for optimizing the CRC calculation, which is a bitwise operation. -static const uint16_t crctab[256] = { - 0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, 0xc601, 0x06c0, 0x0780, - 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440, 0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, - 0xce81, 0x0e40, 0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841, 0xd801, - 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, 0x1e00, 0xdec1, 0xdf81, 0x1f40, - 0xdd01, 0x1dc0, 0x1c80, 0xdc41, 0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, - 0xd641, 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040, 0xf001, 0x30c0, - 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240, 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, - 0x35c0, 0x3480, 0xf441, 0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41, - 0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, 0x2800, 0xe8c1, 0xe981, - 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, 0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, - 0xec81, 0x2c40, 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640, 0x2200, - 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041, 0xa001, 0x60c0, 0x6180, 0xa141, - 0x6300, 0xa3c1, 0xa281, 0x6240, 0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, - 0xa441, 0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, 0xaa01, 0x6ac0, - 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, 0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, - 0x7bc0, 0x7a80, 0xba41, 0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40, - 0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640, 0x7200, 0xb2c1, 0xb381, - 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041, 0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, - 0x5280, 0x9241, 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440, 0x9c01, - 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, 0x5a00, 0x9ac1, 0x9b81, 0x5b40, - 0x9901, 0x59c0, 0x5880, 0x9841, 0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, - 0x4a40, 0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41, 0x4400, 0x84c1, - 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, - 0x81c1, 0x8081, 0x4040, -}; -} // namespace - -namespace bluetooth { -namespace l2cap { - -void Fcs::Initialize() { crc = 0; } - -void Fcs::AddByte(uint8_t byte) { crc = ((crc >> 8) & 0x00ff) ^ crctab[(crc & 0x00ff) ^ byte]; } - -uint16_t Fcs::GetChecksum() const { return crc; } - -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/fcs.h b/system/gd/l2cap/fcs.h deleted file mode 100644 index e1f6c50a85..0000000000 --- a/system/gd/l2cap/fcs.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <cstdint> - -namespace bluetooth { -namespace l2cap { - -// Frame Check Sequence from the L2CAP spec. -class Fcs { -public: - void Initialize(); - - void AddByte(uint8_t byte); - - uint16_t GetChecksum() const; - -private: - uint16_t crc; -}; - -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/fuzz/Android.bp b/system/gd/l2cap/fuzz/Android.bp deleted file mode 100644 index fef71210d6..0000000000 --- a/system/gd/l2cap/fuzz/Android.bp +++ /dev/null @@ -1,44 +0,0 @@ -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "system_bt_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["system_bt_license"], -} - -cc_fuzz { - name: "bluetooth_gd_l2cap_fuzzer", - defaults: ["gd_fuzz_defaults"], - include_dirs: [ - "hardware/interfaces/keymaster/4.0/support/include", - "packages/modules/Bluetooth/system", - "packages/modules/Bluetooth/system/bta/dm", - "packages/modules/Bluetooth/system/bta/include", - "packages/modules/Bluetooth/system/bta/sys", - "packages/modules/Bluetooth/system/btif/co", - "packages/modules/Bluetooth/system/embdrv/sbc/decoder/include", - "packages/modules/Bluetooth/system/embdrv/sbc/encoder/include", - "packages/modules/Bluetooth/system/gd", - "packages/modules/Bluetooth/system/stack/a2dp", - "packages/modules/Bluetooth/system/stack/avdt", - "packages/modules/Bluetooth/system/stack/btm", - "packages/modules/Bluetooth/system/stack/include", - "packages/modules/Bluetooth/system/stack/l2cap", - "packages/modules/Bluetooth/system/udrv/include", - "system/security/keystore/include", - ], - srcs: [ - "channel_fuzz_controller.cc", - "fuzz_l2cap.cc", - ], - static_libs: [ - "bluetooth_flags_c_lib", - "libbte", - ], - fuzz_config: { - cc: ["android-bluetooth-security@google.com"], - componentid: 27441, - }, - cflags: ["-Wno-unused-parameter"], -} diff --git a/system/gd/l2cap/fuzz/channel_fuzz_controller.cc b/system/gd/l2cap/fuzz/channel_fuzz_controller.cc deleted file mode 100644 index cf83082f01..0000000000 --- a/system/gd/l2cap/fuzz/channel_fuzz_controller.cc +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2020 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. - */ -// Authors: corbin.souffrant@leviathansecurity.com -// dylan.katz@leviathansecurity.com - -#include "channel_fuzz_controller.h" - -namespace bluetooth { -using l2cap::classic::internal::FixedChannelImpl; -using l2cap::internal::DynamicChannelImpl; -using os::Handler; - -ChannelFuzzController::ChannelFuzzController(Handler* l2cap_handler, - std::shared_ptr<DynamicChannelImpl> chan) { - EnqueueType* queue = reinterpret_cast<EnqueueType*>(chan->GetQueueUpEnd()); - channelInject_ = std::make_shared<ChannelFuzzQueueType>(queue, l2cap_handler); -} - -ChannelFuzzController::ChannelFuzzController(Handler* l2cap_handler, - std::shared_ptr<FixedChannelImpl> chan) { - EnqueueType* queue = reinterpret_cast<EnqueueType*>(chan->GetQueueUpEnd()); - channelInject_ = std::make_shared<ChannelFuzzQueueType>(queue, l2cap_handler); -} - -void ChannelFuzzController::injectFrame(std::vector<uint8_t> data) { - CONSTRUCT_VALID_UNIQUE_OTHERWISE_BAIL(l2cap::BasicFrameView, packet, data); - channelInject_->Inject(std::move(packet)); -} -} // namespace bluetooth diff --git a/system/gd/l2cap/fuzz/channel_fuzz_controller.h b/system/gd/l2cap/fuzz/channel_fuzz_controller.h deleted file mode 100644 index 7336dc941a..0000000000 --- a/system/gd/l2cap/fuzz/channel_fuzz_controller.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2020 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. - */ -// Authors: corbin.souffrant@leviathansecurity.com -// dylan.katz@leviathansecurity.com - -#pragma once - -#include <vector> - -#include "fuzz/helpers.h" -#include "l2cap/classic/internal/fixed_channel_impl.h" -#include "l2cap/internal/dynamic_channel_impl.h" -#include "l2cap/l2cap_packets.h" -#include "os/fuzz/fuzz_inject_queue.h" -#include "os/handler.h" -#include "packet/packet_view.h" - -namespace bluetooth { - -typedef os::IQueueEnqueue<packet::PacketView<packet::kLittleEndian>> EnqueueType; -typedef os::fuzz::FuzzInjectQueue<packet::PacketView<packet::kLittleEndian>> ChannelFuzzQueueType; - -class ChannelFuzzController { -public: - ChannelFuzzController(os::Handler* l2cap_handler, - std::shared_ptr<l2cap::internal::DynamicChannelImpl> chan); - - ChannelFuzzController(os::Handler* l2cap_handler, - std::shared_ptr<l2cap::classic::internal::FixedChannelImpl> chan); - - void injectPacketData(std::vector<uint8_t> data); - - void injectFrame(std::vector<uint8_t> data); - -private: - std::shared_ptr<ChannelFuzzQueueType> channelInject_; -}; -} // namespace bluetooth diff --git a/system/gd/l2cap/fuzz/fuzz_dynamic_channel_manager.h b/system/gd/l2cap/fuzz/fuzz_dynamic_channel_manager.h deleted file mode 100644 index e8651d3783..0000000000 --- a/system/gd/l2cap/fuzz/fuzz_dynamic_channel_manager.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2020 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. - */ -// Authors: corbin.souffrant@leviathansecurity.com -// dylan.katz@leviathansecurity.com - -#pragma once - -#include "fuzz_dynamic_channel_manager_impl.h" -#include "hci/address.h" -#include "l2cap/classic/dynamic_channel_configuration_option.h" -#include "l2cap/classic/dynamic_channel_manager.h" -#include "l2cap/classic/security_policy.h" -#include "l2cap/psm.h" - -namespace bluetooth { -namespace shim { -namespace { -class FuzzDynamicChannelManager : public l2cap::classic::DynamicChannelManager { -public: - void ConnectChannel( - hci::Address device, - l2cap::classic::DynamicChannelConfigurationOption configuration_option, l2cap::Psm psm, - l2cap::classic::DynamicChannelManager::OnConnectionOpenCallback on_open_callback, - l2cap::classic::DynamicChannelManager::OnConnectionFailureCallback on_fail_callback) - override { - impl_.ConnectChannel(device, configuration_option, psm, std::move(on_open_callback), - std::move(on_fail_callback)); - } - - void RegisterService(l2cap::Psm psm, - l2cap::classic::DynamicChannelConfigurationOption configuration_option, - const l2cap::classic::SecurityPolicy& security_policy, - l2cap::classic::DynamicChannelManager::OnRegistrationCompleteCallback - on_registration_complete, - l2cap::classic::DynamicChannelManager::OnConnectionOpenCallback - on_open_callback) override { - impl_.RegisterService(psm, configuration_option, security_policy, - std::move(on_registration_complete), std::move(on_open_callback)); - } - FuzzDynamicChannelManager(FuzzDynamicChannelManagerImpl& impl) : impl_(impl) {} - FuzzDynamicChannelManagerImpl& impl_; -}; -} // namespace -} // namespace shim -} // namespace bluetooth diff --git a/system/gd/l2cap/fuzz/fuzz_dynamic_channel_manager_impl.h b/system/gd/l2cap/fuzz/fuzz_dynamic_channel_manager_impl.h deleted file mode 100644 index b64606f4f3..0000000000 --- a/system/gd/l2cap/fuzz/fuzz_dynamic_channel_manager_impl.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2020 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. - */ -// Authors: corbin.souffrant@leviathansecurity.com -// dylan.katz@leviathansecurity.com - -#pragma once - -#include <future> -#include <memory> - -#include "hci/address.h" -#include "l2cap/classic/dynamic_channel_configuration_option.h" -#include "l2cap/classic/dynamic_channel_manager.h" -#include "l2cap/classic/security_policy.h" -#include "l2cap/psm.h" - -namespace bluetooth { -namespace shim { -namespace { -class FuzzDynamicChannelManagerImpl { -public: - void ConnectChannel( - hci::Address device, - l2cap::classic::DynamicChannelConfigurationOption configuration_option, l2cap::Psm, - l2cap::classic::DynamicChannelManager::OnConnectionOpenCallback on_open_callback, - l2cap::classic::DynamicChannelManager::OnConnectionFailureCallback on_fail_callback) { - connections_++; - on_open_callback_ = std::move(on_open_callback); - on_fail_callback_ = std::move(on_fail_callback); - - connected_promise_.set_value(); - } - int connections_{0}; - - void RegisterService( - l2cap::Psm, l2cap::classic::DynamicChannelConfigurationOption, - const l2cap::classic::SecurityPolicy&, - l2cap::classic::DynamicChannelManager::OnRegistrationCompleteCallback - on_registration_complete, - l2cap::classic::DynamicChannelManager::OnConnectionOpenCallback on_open_callback) { - services_++; - on_registration_complete_ = std::move(on_registration_complete); - on_open_callback_ = std::move(on_open_callback); - - register_promise_.set_value(); - } - int services_{0}; - - void SetConnectionFuture() { connected_promise_ = std::promise<void>(); } - - void WaitConnectionFuture() { - connected_future_ = connected_promise_.get_future(); - connected_future_.wait(); - } - - void SetRegistrationFuture() { register_promise_ = std::promise<void>(); } - - void WaitRegistrationFuture() { - register_future_ = register_promise_.get_future(); - register_future_.wait(); - } - - void SetConnectionOnFail(l2cap::classic::DynamicChannelManager::ConnectionResult result, - std::promise<void> promise) { - std::move(on_fail_callback_)(result); - promise.set_value(); - } - - void SetConnectionOnOpen(std::unique_ptr<l2cap::DynamicChannel> channel, - std::promise<void> promise) { - std::move(on_open_callback_)(std::move(channel)); - promise.set_value(); - } - - l2cap::classic::DynamicChannelManager::OnRegistrationCompleteCallback on_registration_complete_{}; - l2cap::classic::DynamicChannelManager::OnConnectionOpenCallback on_open_callback_{}; - l2cap::classic::DynamicChannelManager::OnConnectionFailureCallback on_fail_callback_{}; - - FuzzDynamicChannelManagerImpl() = default; - ~FuzzDynamicChannelManagerImpl() = default; - -private: - std::promise<void> connected_promise_; - std::future<void> connected_future_; - - std::promise<void> register_promise_; - std::future<void> register_future_; -}; -} // namespace -} // namespace shim -} // namespace bluetooth diff --git a/system/gd/l2cap/fuzz/fuzz_l2cap.cc b/system/gd/l2cap/fuzz/fuzz_l2cap.cc deleted file mode 100644 index 354e15bfa9..0000000000 --- a/system/gd/l2cap/fuzz/fuzz_l2cap.cc +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2020 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. - */ -// Authors: corbin.souffrant@leviathansecurity.com -// dylan.katz@leviathansecurity.com - -#include <fuzzer/FuzzedDataProvider.h> -#include <hci/address.h> - -#include "channel_fuzz_controller.h" -#include "l2cap/psm.h" -#include "os/log.h" -#include "shim_l2cap.h" - -namespace bluetooth { -using hci::Address; -using hci::AddressType; -using hci::acl_manager::AclConnection; -using hci::acl_manager::ClassicAclConnection; -using l2cap::Cid; -using l2cap::Psm; -using l2cap::classic::internal::Link; - -using shim::ShimL2capFuzz; - -class FakeCommandInterface : public hci::CommandInterface<hci::AclCommandBuilder> { -public: - virtual void EnqueueCommand( - std::unique_ptr<hci::AclCommandBuilder> command, - common::ContextualOnceCallback<void(hci::CommandCompleteView)> on_complete) {} - - virtual void EnqueueCommand( - std::unique_ptr<hci::AclCommandBuilder> command, - common::ContextualOnceCallback<void(hci::CommandStatusView)> on_status) {} -} fake_command_interface; - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - FuzzedDataProvider fdp = FuzzedDataProvider(data, size); - ShimL2capFuzz l2shim(&fdp); - - std::vector<uint8_t> addressVals = fdp.ConsumeBytes<uint8_t>(Address::kLength); - - // Make sure the address is always at least kLength. - while (addressVals.size() < Address::kLength) { - addressVals.push_back(0); - } - Address myAddress; - myAddress.FromOctets(addressVals.data()); - hci::AddressWithType addressWithType = - hci::AddressWithType(myAddress, AddressType::PUBLIC_DEVICE_ADDRESS); - - // Associate a ClassicAclConnection so that we can grab a link. - auto throwaway_queue = std::make_shared<AclConnection::Queue>(10); - l2shim.link_manager->OnConnectSuccess(std::unique_ptr<ClassicAclConnection>( - new ClassicAclConnection(throwaway_queue, &fake_command_interface, 0, myAddress))); - Link* link = l2shim.link_manager->GetLink(myAddress); - - // 0x0001-0x007F Fixed, 0x0080-0x00FF Dynamic - [[maybe_unused]] uint16_t psm = fdp.ConsumeIntegralInRange<uint16_t>(0x0001, 0x007F); - psm = 0x0101u ^ 0x0100u; - uint16_t dynamicPsm = fdp.ConsumeIntegralInRange<uint16_t>(0x0080, 0x00FF); - dynamicPsm = 0x0101u ^ 0x0100u; - - // Open a connection and assign an ID - Cid fixedCid = l2cap::kLeSignallingCid; - - // Fixed channels must be acquired. - auto fixedChannel = link->AllocateFixedChannel(fixedCid); - fixedChannel->RegisterOnCloseCallback(l2shim.handler_.get(), - common::BindOnce([](hci::ErrorCode) {})); - fixedChannel->Acquire(); - ChannelFuzzController fixedChannelController(l2shim.handler_.get(), fixedChannel); - // Generate a valid dynamic channel ID - Cid dynamicCid = fdp.ConsumeIntegralInRange<uint16_t>(l2cap::kFirstDynamicChannel, - l2cap::kLastDynamicChannel); - auto dynamicChannel = link->AllocateDynamicChannel(dynamicPsm, dynamicCid); - ChannelFuzzController dynamicChannelController(l2shim.handler_.get(), dynamicChannel); - - while (fdp.remaining_bytes() > 0) { - // Are we using the dynamic queue? - bool dynamic = fdp.ConsumeBool(); - - // Consume at most UINT16_MAX or remaining_bytes, whatever is smaller. - uint16_t packetSize = static_cast<uint16_t>( - std::min(static_cast<size_t>(fdp.ConsumeIntegral<uint16_t>()), fdp.remaining_bytes())); - std::vector<uint8_t> data = fdp.ConsumeBytes<uint8_t>(packetSize); - if (dynamic) { - dynamicChannelController.injectFrame(data); - } else { - fixedChannelController.injectFrame(data); - } - } - - // Cleanup stuff. - fixedChannel->Release(); - dynamicChannel->Close(); - l2shim.stopRegistry(); - link->OnAclDisconnected(hci::ErrorCode::SUCCESS); - l2shim.link_manager->OnDisconnect(myAddress, hci::ErrorCode::SUCCESS); - return 0; -} -} // namespace bluetooth diff --git a/system/gd/l2cap/fuzz/fuzz_l2cap_classic_module.h b/system/gd/l2cap/fuzz/fuzz_l2cap_classic_module.h deleted file mode 100644 index 4a8df5b54d..0000000000 --- a/system/gd/l2cap/fuzz/fuzz_l2cap_classic_module.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2020 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. - */ -// Authors: corbin.souffrant@leviathansecurity.com -// dylan.katz@leviathansecurity.com - -#pragma once - -#include <fuzzer/FuzzedDataProvider.h> - -#include "fuzz_dynamic_channel_manager.h" -#include "fuzz_dynamic_channel_manager_impl.h" -#include "l2cap/classic/dynamic_channel_manager.h" -#include "l2cap/classic/l2cap_classic_module.h" - -namespace bluetooth { -namespace shim { -namespace { -class FuzzL2capClassicModule : public l2cap::classic::L2capClassicModule { -public: - std::unique_ptr<l2cap::classic::DynamicChannelManager> GetDynamicChannelManager() override { - return std::make_unique<FuzzDynamicChannelManager>(*impl_); - } - - void ListDependencies(ModuleList*) const override {} - void Start() override; - void Stop() override; - - std::unique_ptr<FuzzDynamicChannelManagerImpl> impl_; -}; - -void FuzzL2capClassicModule::Start() { impl_ = std::make_unique<FuzzDynamicChannelManagerImpl>(); } - -void FuzzL2capClassicModule::Stop() { impl_.reset(); } -} // namespace -} // namespace shim -} // namespace bluetooth diff --git a/system/gd/l2cap/fuzz/shim_l2cap.h b/system/gd/l2cap/fuzz/shim_l2cap.h deleted file mode 100644 index 2636fcd007..0000000000 --- a/system/gd/l2cap/fuzz/shim_l2cap.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2020 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. - */ -// Authors: corbin.souffrant@leviathansecurity.com -// dylan.katz@leviathansecurity.com - -#pragma once - -#include <fuzzer/FuzzedDataProvider.h> - -#include <future> -#include <memory> - -#include "fuzz_l2cap_classic_module.h" -#include "hci/fuzz/fuzz_hci_layer.h" -#include "l2cap/classic/internal/dynamic_channel_service_manager_impl.h" -#include "l2cap/classic/internal/fixed_channel_service_manager_impl.h" -#include "l2cap/classic/internal/link_manager.h" -#include "l2cap/classic/l2cap_classic_module.h" -#include "l2cap/internal/parameter_provider.h" -#include "os/handler.h" - -namespace bluetooth { - -namespace shim { -namespace { -class ShimL2capFuzz { -public: - uint16_t CreateConnection(uint16_t psm, hci::Address device_address) { - std::promise<uint16_t> promise; - auto future = promise.get_future(); - - fuzz_l2cap_classic_module_->GetDynamicChannelManager()->ConnectChannel( - device_address, {}, psm, handler_->BindOn(this, &ShimL2capFuzz::OnConnectionComplete), - handler_->BindOnceOn(this, &ShimL2capFuzz::OnConnectionFail)); - - return future.get(); - } - - void OnConnectionComplete(std::unique_ptr<l2cap::classic::DynamicChannel> channel) {} - - void OnConnectionFail(l2cap::classic::DynamicChannelManager::ConnectionResult result) {} - - ShimL2capFuzz(FuzzedDataProvider* fdp) { - hci::fuzz::FuzzHciLayer* fuzzHci = - fake_registry_.Inject<hci::fuzz::FuzzHciLayer>(&hci::HciLayer::Factory); - fuzz_l2cap_classic_module_ = new FuzzL2capClassicModule(); - fake_registry_.InjectTestModule(&l2cap::classic::L2capClassicModule::Factory, - fuzz_l2cap_classic_module_); - fake_registry_.Start<l2cap::classic::L2capClassicModule>(); - - // The autoreply is needed to prevent it from hanging. - fuzzHci->TurnOnAutoReply(fdp); - acl_manager_ = fake_registry_.Start<hci::AclManager>(); - fuzzHci->TurnOffAutoReply(); - - // Create the LinkManager - handler_ = std::unique_ptr<os::Handler>(new os::Handler(&thread_)); - dynamic_channel_impl = - std::unique_ptr<l2cap::classic::internal::DynamicChannelServiceManagerImpl>( - new l2cap::classic::internal::DynamicChannelServiceManagerImpl(handler_.get())); - fixed_channel_impl = std::unique_ptr<l2cap::classic::internal::FixedChannelServiceManagerImpl>( - new l2cap::classic::internal::FixedChannelServiceManagerImpl(handler_.get())); - parameter_provider = std::unique_ptr<l2cap::internal::ParameterProvider>( - new l2cap::internal::ParameterProvider()); - link_manager = std::unique_ptr<l2cap::classic::internal::LinkManager>( - new l2cap::classic::internal::LinkManager( - handler_.get(), acl_manager_, fixed_channel_impl.get(), - dynamic_channel_impl.get(), parameter_provider.get())); - } - - ~ShimL2capFuzz() { handler_->Clear(); } - - void stopRegistry() { fake_registry_.WaitForIdleAndStopAll(); } - - std::promise<void> connection_complete_promise_; - - FuzzL2capClassicModule* fuzz_l2cap_classic_module_{nullptr}; - hci::AclManager* acl_manager_{nullptr}; - - std::unique_ptr<os::Handler> handler_; - std::unique_ptr<l2cap::classic::internal::FixedChannelServiceManagerImpl> fixed_channel_impl; - std::unique_ptr<l2cap::classic::internal::DynamicChannelServiceManagerImpl> dynamic_channel_impl; - std::unique_ptr<l2cap::classic::internal::LinkManager> link_manager; - std::unique_ptr<l2cap::internal::ParameterProvider> parameter_provider; - -private: - FuzzTestModuleRegistry fake_registry_; - os::Thread& thread_ = fake_registry_.GetTestThread(); -}; -} // namespace -} // namespace shim -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/basic_mode_channel_data_controller.cc b/system/gd/l2cap/internal/basic_mode_channel_data_controller.cc deleted file mode 100644 index a8a4b35819..0000000000 --- a/system/gd/l2cap/internal/basic_mode_channel_data_controller.cc +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/internal/basic_mode_channel_data_controller.h" - -#include <bluetooth/log.h> - -#include "l2cap/l2cap_packets.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { - -BasicModeDataController::BasicModeDataController(Cid cid, Cid remote_cid, - UpperQueueDownEnd* channel_queue_end, - os::Handler* handler, Scheduler* scheduler) - : cid_(cid), - remote_cid_(remote_cid), - enqueue_buffer_(channel_queue_end), - handler_(handler), - scheduler_(scheduler) {} - -BasicModeDataController::~BasicModeDataController() { enqueue_buffer_.Clear(); } - -void BasicModeDataController::OnSdu(std::unique_ptr<packet::BasePacketBuilder> sdu) { - auto l2cap_information = BasicFrameBuilder::Create(remote_cid_, std::move(sdu)); - pdu_queue_.emplace(std::move(l2cap_information)); - scheduler_->OnPacketsReady(cid_, 1); -} - -void BasicModeDataController::OnPdu(packet::PacketView<true> pdu) { - auto basic_frame_view = BasicFrameView::Create(pdu); - if (!basic_frame_view.IsValid()) { - log::warn("Received invalid frame"); - return; - } - enqueue_buffer_.Enqueue( - std::make_unique<PacketView<kLittleEndian>>(basic_frame_view.GetPayload()), handler_); -} - -std::unique_ptr<packet::BasePacketBuilder> BasicModeDataController::GetNextPacket() { - auto next = std::move(pdu_queue_.front()); - pdu_queue_.pop(); - return next; -} - -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/basic_mode_channel_data_controller.h b/system/gd/l2cap/internal/basic_mode_channel_data_controller.h deleted file mode 100644 index a8a730654c..0000000000 --- a/system/gd/l2cap/internal/basic_mode_channel_data_controller.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <memory> -#include <unordered_map> -#include <utility> - -#include "common/bidi_queue.h" -#include "l2cap/cid.h" -#include "l2cap/internal/channel_impl.h" -#include "l2cap/internal/data_controller.h" -#include "l2cap/internal/scheduler.h" -#include "l2cap/l2cap_packets.h" -#include "l2cap/mtu.h" -#include "os/handler.h" -#include "os/queue.h" -#include "packet/base_packet_builder.h" -#include "packet/packet_view.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { - -class BasicModeDataController : public DataController { -public: - using UpperEnqueue = packet::PacketView<packet::kLittleEndian>; - using UpperDequeue = packet::BasePacketBuilder; - using UpperQueueDownEnd = common::BidiQueueEnd<UpperEnqueue, UpperDequeue>; - BasicModeDataController(Cid cid, Cid remote_cid, UpperQueueDownEnd* channel_queue_end, - os::Handler* handler, Scheduler* scheduler); - - ~BasicModeDataController(); - - void OnSdu(std::unique_ptr<packet::BasePacketBuilder> sdu) override; - - void OnPdu(packet::PacketView<true> pdu) override; - - std::unique_ptr<packet::BasePacketBuilder> GetNextPacket() override; - - void EnableFcs(bool /* enabled */) override {} - void SetRetransmissionAndFlowControlOptions( - const RetransmissionAndFlowControlConfigurationOption& /* option */) override {} - -private: - Cid cid_; - Cid remote_cid_; - os::EnqueueBuffer<UpperEnqueue> enqueue_buffer_; - os::Handler* handler_; - std::queue<std::unique_ptr<packet::BasePacketBuilder>> pdu_queue_; - Scheduler* scheduler_; -}; - -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/basic_mode_channel_data_controller_test.cc b/system/gd/l2cap/internal/basic_mode_channel_data_controller_test.cc deleted file mode 100644 index cc7082105a..0000000000 --- a/system/gd/l2cap/internal/basic_mode_channel_data_controller_test.cc +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/internal/basic_mode_channel_data_controller.h" - -#include <gtest/gtest.h> - -#include "l2cap/internal/scheduler_mock.h" -#include "packet/raw_builder.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { -namespace { - -std::unique_ptr<packet::BasePacketBuilder> CreateSdu(std::vector<uint8_t> payload) { - auto raw_builder = std::make_unique<packet::RawBuilder>(); - raw_builder->AddOctets(payload); - return raw_builder; -} - -PacketView<kLittleEndian> GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet) { - auto bytes = std::make_shared<std::vector<uint8_t>>(); - BitInserter i(*bytes); - bytes->reserve(packet->size()); - packet->Serialize(i); - return packet::PacketView<packet::kLittleEndian>(bytes); -} - -void sync_handler(os::Handler* handler) { - std::promise<void> promise; - auto future = promise.get_future(); - handler->Post(common::BindOnce(&std::promise<void>::set_value, common::Unretained(&promise))); - auto status = future.wait_for(std::chrono::milliseconds(300)); - EXPECT_EQ(status, std::future_status::ready); -} - -class BasicModeDataControllerTest : public ::testing::Test { -protected: - void SetUp() override { - thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL); - user_handler_ = new os::Handler(thread_); - queue_handler_ = new os::Handler(thread_); - } - - void TearDown() override { - queue_handler_->Clear(); - user_handler_->Clear(); - delete queue_handler_; - delete user_handler_; - delete thread_; - } - - os::Thread* thread_ = nullptr; - os::Handler* user_handler_ = nullptr; - os::Handler* queue_handler_ = nullptr; -}; - -TEST_F(BasicModeDataControllerTest, transmit) { - common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10}; - testing::MockScheduler scheduler; - BasicModeDataController controller{1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler}; - EXPECT_CALL(scheduler, OnPacketsReady(1, 1)); - controller.OnSdu(CreateSdu({'a', 'b', 'c', 'd'})); - auto next_packet = controller.GetNextPacket(); - EXPECT_NE(next_packet, nullptr); - auto view = GetPacketView(std::move(next_packet)); - auto pdu_view = BasicFrameView::Create(view); - EXPECT_TRUE(pdu_view.IsValid()); - auto payload = pdu_view.GetPayload(); - std::string data = std::string(payload.begin(), payload.end()); - EXPECT_EQ(data, "abcd"); -} - -TEST_F(BasicModeDataControllerTest, receive) { - common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10}; - testing::MockScheduler scheduler; - BasicModeDataController controller{1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler}; - auto base_view = GetPacketView(BasicFrameBuilder::Create(1, CreateSdu({'a', 'b', 'c', 'd'}))); - controller.OnPdu(base_view); - sync_handler(queue_handler_); - auto packet_view = channel_queue.GetUpEnd()->TryDequeue(); - EXPECT_NE(packet_view, nullptr); - std::string data = std::string(packet_view->begin(), packet_view->end()); - EXPECT_EQ(data, "abcd"); -} - -} // namespace -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/channel_impl.h b/system/gd/l2cap/internal/channel_impl.h deleted file mode 100644 index 04503b1e1b..0000000000 --- a/system/gd/l2cap/internal/channel_impl.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include "common/bidi_queue.h" -#include "l2cap/cid.h" -#include "l2cap/l2cap_packets.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { -class Sender; - -/** - * Common interface for internal channel implementation - */ -class ChannelImpl { -public: - virtual ~ChannelImpl() = default; - - /** - * Return the queue end for upper layer (L2CAP user) - */ - virtual common::BidiQueueEnd<packet::BasePacketBuilder, - packet::PacketView<packet::kLittleEndian>>* - GetQueueUpEnd() = 0; - - /** - * Return the queue end for lower layer (sender and receiver) - */ - virtual common::BidiQueueEnd<packet::PacketView<packet::kLittleEndian>, - packet::BasePacketBuilder>* - GetQueueDownEnd() = 0; - - virtual Cid GetCid() const = 0; - - virtual Cid GetRemoteCid() const = 0; -}; - -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/channel_impl_mock.h b/system/gd/l2cap/internal/channel_impl_mock.h deleted file mode 100644 index 67e66ad1ab..0000000000 --- a/system/gd/l2cap/internal/channel_impl_mock.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <gmock/gmock.h> - -#include "l2cap/internal/channel_impl.h" - -// Unit test interfaces -namespace bluetooth { -namespace l2cap { -namespace internal { -namespace testing { - -class MockChannelImpl : public ChannelImpl { -public: - MOCK_METHOD((common::BidiQueueEnd<packet::BasePacketBuilder, - packet::PacketView<packet::kLittleEndian>>*), - GetQueueUpEnd, (), (override)); - MOCK_METHOD((common::BidiQueueEnd<packet::PacketView<packet::kLittleEndian>, - packet::BasePacketBuilder>*), - GetQueueDownEnd, (), (override)); - MOCK_METHOD(Cid, GetCid, (), (const, override)); - MOCK_METHOD(Cid, GetRemoteCid, (), (const, override)); -}; - -} // namespace testing -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/data_controller.h b/system/gd/l2cap/internal/data_controller.h deleted file mode 100644 index 8efb57cc16..0000000000 --- a/system/gd/l2cap/internal/data_controller.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <memory> - -#include "l2cap/l2cap_packets.h" -#include "packet/base_packet_builder.h" -#include "packet/packet_view.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { - -class DataController { -public: - virtual ~DataController() = default; - - // SDU -> PDUs and notify Scheduler - virtual void OnSdu(std::unique_ptr<packet::BasePacketBuilder> sdu) = 0; - - // PDUs -> SDU and enqueue to channel queue end - virtual void OnPdu(packet::PacketView<true> pdu) = 0; - - // Used by Scheduler to get next PDU - virtual std::unique_ptr<packet::BasePacketBuilder> GetNextPacket() = 0; - - // Set FCS mode. This only applies to some modes (ERTM). - virtual void EnableFcs(bool enabled) = 0; - - // Set retransmission and flow control. Ignore the mode option because each DataController only - // handles one mode. This only applies to some modes (ERTM). - virtual void SetRetransmissionAndFlowControlOptions( - const RetransmissionAndFlowControlConfigurationOption& option) = 0; -}; - -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/data_controller_mock.h b/system/gd/l2cap/internal/data_controller_mock.h deleted file mode 100644 index 92876d8d16..0000000000 --- a/system/gd/l2cap/internal/data_controller_mock.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <gmock/gmock.h> - -#include "l2cap/internal/data_controller.h" - -// Unit test interfaces -namespace bluetooth { -namespace l2cap { -namespace internal { -namespace testing { - -class MockDataController : public DataController { -public: - MOCK_METHOD(void, OnSdu, (std::unique_ptr<packet::BasePacketBuilder>), (override)); - MOCK_METHOD(void, OnPdu, (packet::PacketView<true>), (override)); - MOCK_METHOD(std::unique_ptr<packet::BasePacketBuilder>, GetNextPacket, (), (override)); - MOCK_METHOD(void, EnableFcs, (bool), (override)); - MOCK_METHOD(void, SetRetransmissionAndFlowControlOptions, - (const RetransmissionAndFlowControlConfigurationOption&), (override)); -}; - -} // namespace testing -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/data_pipeline_manager.cc b/system/gd/l2cap/internal/data_pipeline_manager.cc deleted file mode 100644 index e2ce918beb..0000000000 --- a/system/gd/l2cap/internal/data_pipeline_manager.cc +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/internal/data_pipeline_manager.h" - -#include <unordered_map> - -#include "l2cap/cid.h" -#include "l2cap/internal/channel_impl.h" -#include "l2cap/internal/data_controller.h" -#include "l2cap/internal/sender.h" -#include "os/log.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { - -void DataPipelineManager::AttachChannel(Cid cid, std::shared_ptr<ChannelImpl> channel, - ChannelMode mode) { - log::assert_that(sender_map_.find(cid) == sender_map_.end(), - "assert failed: sender_map_.find(cid) == sender_map_.end()"); - sender_map_.emplace(std::piecewise_construct, std::forward_as_tuple(cid), - std::forward_as_tuple(handler_, link_, scheduler_.get(), channel, mode)); -} - -void DataPipelineManager::DetachChannel(Cid cid) { - log::assert_that(sender_map_.find(cid) != sender_map_.end(), - "assert failed: sender_map_.find(cid) != sender_map_.end()"); - sender_map_.erase(cid); - scheduler_->RemoveChannel(cid); - scheduler_->SetChannelTxPriority(cid, false); -} - -DataController* DataPipelineManager::GetDataController(Cid cid) { - if (sender_map_.find(cid) == sender_map_.end()) { - return nullptr; - }; - return sender_map_.find(cid)->second.GetDataController(); -} - -void DataPipelineManager::OnPacketSent(Cid cid) { - log::assert_that(sender_map_.find(cid) != sender_map_.end(), - "assert failed: sender_map_.find(cid) != sender_map_.end()"); - sender_map_.find(cid)->second.OnPacketSent(); -} - -void DataPipelineManager::UpdateClassicConfiguration( - Cid cid, classic::internal::ChannelConfigurationState config) { - log::assert_that(sender_map_.find(cid) != sender_map_.end(), - "assert failed: sender_map_.find(cid) != sender_map_.end()"); - sender_map_.find(cid)->second.UpdateClassicConfiguration(config); -} - -void DataPipelineManager::SetChannelTxPriority(Cid cid, bool high_priority) { - log::assert_that(sender_map_.find(cid) != sender_map_.end(), - "assert failed: sender_map_.find(cid) != sender_map_.end()"); - scheduler_->SetChannelTxPriority(cid, high_priority); -} - -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/data_pipeline_manager.h b/system/gd/l2cap/internal/data_pipeline_manager.h deleted file mode 100644 index 4f9a27311d..0000000000 --- a/system/gd/l2cap/internal/data_pipeline_manager.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <string> -#include <unordered_map> - -#include "common/bidi_queue.h" -#include "common/bind.h" -#include "data_controller.h" -#include "l2cap/cid.h" -#include "l2cap/classic/internal/channel_configuration_state.h" -#include "l2cap/internal/channel_impl.h" -#include "l2cap/internal/receiver.h" -#include "l2cap/internal/scheduler.h" -#include "l2cap/internal/scheduler_fifo.h" -#include "l2cap/l2cap_packets.h" -#include "l2cap/mtu.h" -#include "os/handler.h" -#include "os/log.h" -#include "os/queue.h" -#include "packet/base_packet_builder.h" -#include "packet/packet_view.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { -class ILink; - -/** - * Manages data pipeline from channel queue end to link queue end, per link. - * Contains a Scheduler and Receiver per link. - * Contains a Sender and its corresponding DataController per attached channel. - */ -class DataPipelineManager { -public: - using UpperEnqueue = packet::PacketView<packet::kLittleEndian>; - using UpperDequeue = packet::BasePacketBuilder; - using UpperQueueDownEnd = common::BidiQueueEnd<UpperEnqueue, UpperDequeue>; - using LowerEnqueue = UpperDequeue; - using LowerDequeue = UpperEnqueue; - using LowerQueueUpEnd = common::BidiQueueEnd<LowerEnqueue, LowerDequeue>; - - DataPipelineManager(os::Handler* handler, ILink* link, LowerQueueUpEnd* link_queue_up_end) - : handler_(handler), - link_(link), - scheduler_(std::make_unique<Fifo>(this, link_queue_up_end, handler)), - receiver_(link_queue_up_end, handler, this) {} - - using ChannelMode = Sender::ChannelMode; - - virtual void AttachChannel(Cid cid, std::shared_ptr<ChannelImpl> channel, ChannelMode mode); - virtual void DetachChannel(Cid cid); - virtual DataController* GetDataController(Cid cid); - virtual void OnPacketSent(Cid cid); - virtual void UpdateClassicConfiguration(Cid cid, - classic::internal::ChannelConfigurationState config); - virtual void SetChannelTxPriority(Cid cid, bool high_priority); - virtual ~DataPipelineManager() = default; - -private: - os::Handler* handler_; - ILink* link_; - std::unordered_map<Cid, Sender> sender_map_; - std::unique_ptr<Scheduler> scheduler_; - Receiver receiver_; -}; -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/data_pipeline_manager_mock.h b/system/gd/l2cap/internal/data_pipeline_manager_mock.h deleted file mode 100644 index 900f0d49c6..0000000000 --- a/system/gd/l2cap/internal/data_pipeline_manager_mock.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <gmock/gmock.h> - -#include "l2cap/internal/channel_impl.h" -#include "l2cap/internal/data_controller.h" -#include "l2cap/internal/data_pipeline_manager.h" - -// Unit test interfaces -namespace bluetooth { -namespace l2cap { -namespace internal { -namespace testing { - -class MockDataPipelineManager : public DataPipelineManager { -public: - MockDataPipelineManager(os::Handler* handler, LowerQueueUpEnd* link_queue_up_end) - : DataPipelineManager(handler, nullptr, link_queue_up_end) {} - MOCK_METHOD(void, AttachChannel, (Cid, std::shared_ptr<ChannelImpl>, ChannelMode), (override)); - MOCK_METHOD(void, DetachChannel, (Cid), (override)); - MOCK_METHOD(DataController*, GetDataController, (Cid), (override)); - MOCK_METHOD(void, OnPacketSent, (Cid), (override)); -}; - -} // namespace testing -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/dynamic_channel_allocator.cc b/system/gd/l2cap/internal/dynamic_channel_allocator.cc deleted file mode 100644 index bb59311e77..0000000000 --- a/system/gd/l2cap/internal/dynamic_channel_allocator.cc +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/internal/dynamic_channel_allocator.h" - -#include <bluetooth/log.h> - -#include <unordered_map> - -#include "l2cap/cid.h" -#include "l2cap/classic/internal/link.h" -#include "l2cap/classic/security_policy.h" -#include "l2cap/internal/dynamic_channel_impl.h" -#include "os/log.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { - -std::shared_ptr<DynamicChannelImpl> DynamicChannelAllocator::AllocateChannel(Psm psm, - Cid remote_cid) { - if (used_remote_cid_.find(remote_cid) != used_remote_cid_.end()) { - log::info("Remote cid 0x{:x} is used", remote_cid); - return nullptr; - } - Cid cid = kFirstDynamicChannel; - for (; cid <= kLastDynamicChannel; cid++) { - if (used_cid_.find(cid) == used_cid_.end()) { - break; - } - } - if (cid > kLastDynamicChannel) { - log::warn("All cid are used"); - return nullptr; - } - auto elem = channels_.try_emplace( - cid, std::make_shared<DynamicChannelImpl>(psm, cid, remote_cid, link_, l2cap_handler_)); - log::assert_that(elem.second, "Failed to create channel for psm 0x{:x} device {}", psm, - ADDRESS_TO_LOGGABLE_CSTR(link_->GetDevice())); - log::assert_that(elem.first->second != nullptr, "assert failed: elem.first->second != nullptr"); - used_remote_cid_.insert(remote_cid); - used_cid_.insert(cid); - return elem.first->second; -} - -std::shared_ptr<DynamicChannelImpl> DynamicChannelAllocator::AllocateReservedChannel( - Cid reserved_cid, Psm psm, Cid remote_cid) { - if (used_remote_cid_.find(remote_cid) != used_remote_cid_.end()) { - log::info("Remote cid 0x{:x} is used", remote_cid); - return nullptr; - } - auto elem = channels_.try_emplace( - reserved_cid, std::make_shared<DynamicChannelImpl>(psm, reserved_cid, remote_cid, link_, - l2cap_handler_)); - log::assert_that(elem.second, "Failed to create channel for psm 0x{:x} device {}", psm, - ADDRESS_TO_LOGGABLE_CSTR(link_->GetDevice())); - log::assert_that(elem.first->second != nullptr, "assert failed: elem.first->second != nullptr"); - used_remote_cid_.insert(remote_cid); - return elem.first->second; -} - -Cid DynamicChannelAllocator::ReserveChannel() { - Cid cid = kFirstDynamicChannel; - for (; cid <= kLastDynamicChannel; cid++) { - if (used_cid_.find(cid) == used_cid_.end()) { - break; - } - } - if (cid > kLastDynamicChannel) { - log::warn("All cid are used"); - return kInvalidCid; - } - used_cid_.insert(cid); - return cid; -} - -void DynamicChannelAllocator::FreeChannel(Cid cid) { - used_cid_.erase(cid); - auto channel = FindChannelByCid(cid); - if (channel == nullptr) { - log::info("Channel is not in use: cid {}, device {}", cid, link_->GetDevice()); - return; - } - used_remote_cid_.erase(channel->GetRemoteCid()); - channels_.erase(cid); -} - -bool DynamicChannelAllocator::IsPsmUsed(Psm psm) const { - for (const auto& channel : channels_) { - if (channel.second->GetPsm() == psm) { - return true; - } - } - return false; -} - -std::shared_ptr<DynamicChannelImpl> DynamicChannelAllocator::FindChannelByCid(Cid cid) { - if (channels_.find(cid) == channels_.end()) { - log::warn("Can't find cid {}", cid); - return nullptr; - } - return channels_.find(cid)->second; -} - -std::shared_ptr<DynamicChannelImpl> DynamicChannelAllocator::FindChannelByRemoteCid( - Cid remote_cid) { - for (auto& channel : channels_) { - if (channel.second->GetRemoteCid() == remote_cid) { - return channel.second; - } - } - return nullptr; -} - -size_t DynamicChannelAllocator::NumberOfChannels() const { return channels_.size(); } - -void DynamicChannelAllocator::OnAclDisconnected(hci::ErrorCode reason) { - for (auto& elem : channels_) { - elem.second->OnClosed(reason); - } -} - -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/dynamic_channel_allocator.h b/system/gd/l2cap/internal/dynamic_channel_allocator.h deleted file mode 100644 index 9f760ebfe3..0000000000 --- a/system/gd/l2cap/internal/dynamic_channel_allocator.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <unordered_map> -#include <unordered_set> - -#include "hci/acl_manager.h" -#include "l2cap/cid.h" -#include "l2cap/classic/security_policy.h" -#include "l2cap/internal/ilink.h" -#include "l2cap/psm.h" -#include "os/handler.h" -#include "os/log.h" - -namespace bluetooth { -namespace l2cap { - -namespace classic { -namespace internal { -class DumpsysHelper; -} // namespace internal -} // namespace classic - -namespace internal { - -class DynamicChannelImpl; - -// Helper class for keeping channels in a Link. It allocates and frees Channel object, and supports -// querying whether a channel is in use -class DynamicChannelAllocator { -public: - DynamicChannelAllocator(l2cap::internal::ILink* link, os::Handler* l2cap_handler) - : link_(link), l2cap_handler_(l2cap_handler) { - log::assert_that(link_ != nullptr, "assert failed: link_ != nullptr"); - log::assert_that(l2cap_handler_ != nullptr, "assert failed: l2cap_handler_ != nullptr"); - } - - // Allocates a channel. If psm is used, OR the remote cid already exists, return nullptr. - // NOTE: The returned DynamicChannelImpl object is still owned by the channel allocator, NOT the - // client. - std::shared_ptr<DynamicChannelImpl> AllocateChannel(Psm psm, Cid remote_cid); - - std::shared_ptr<DynamicChannelImpl> AllocateReservedChannel(Cid reserved_cid, Psm psm, - Cid remote_cid); - - // Gives an unused Cid to be used for opening a channel. If a channel is used, call - // AllocateReservedChannel. If no longer needed, use FreeChannel. - Cid ReserveChannel(); - - // Frees a channel (existing or reserved) - void FreeChannel(Cid cid); - - bool IsPsmUsed(Psm psm) const; - - std::shared_ptr<DynamicChannelImpl> FindChannelByCid(Cid cid); - std::shared_ptr<DynamicChannelImpl> FindChannelByRemoteCid(Cid cid); - - // Returns number of open, but not reserved channels - size_t NumberOfChannels() const; - - void OnAclDisconnected(hci::ErrorCode hci_status); - -private: - friend class bluetooth::l2cap::classic::internal::DumpsysHelper; - l2cap::internal::ILink* link_; - os::Handler* l2cap_handler_; - std::unordered_set<Cid> used_cid_; - std::unordered_map<Cid, std::shared_ptr<DynamicChannelImpl>> channels_; - std::unordered_set<Cid> used_remote_cid_; -}; - -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/dynamic_channel_allocator_fuzz_test.cc b/system/gd/l2cap/internal/dynamic_channel_allocator_fuzz_test.cc deleted file mode 100644 index 2c1f50f22f..0000000000 --- a/system/gd/l2cap/internal/dynamic_channel_allocator_fuzz_test.cc +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2019 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 <gmock/gmock.h> - -#include "l2cap/classic/internal/link_mock.h" -#include "l2cap/internal/dynamic_channel_allocator.h" -#include "l2cap/internal/parameter_provider_mock.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { - -using classic::internal::testing::MockLink; -using hci::testing::MockClassicAclConnection; -using l2cap::internal::testing::MockParameterProvider; -using l2cap::internal::testing::MockScheduler; -using ::testing::NiceMock; -using ::testing::Return; - -const hci::AddressWithType device{{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::PUBLIC_IDENTITY_ADDRESS}; - -class L2capClassicDynamicChannelAllocatorFuzzTest { -public: - void RunTests(const uint8_t* data, size_t size) { - SetUp(); - TestPrecondition(data, size); - TearDown(); - } - -private: - void SetUp() { - thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL); - handler_ = new os::Handler(thread_); - mock_parameter_provider_ = new NiceMock<MockParameterProvider>(); - mock_classic_link_ = - new NiceMock<MockLink>(handler_, mock_parameter_provider_, - std::make_unique<NiceMock<MockClassicAclConnection>>(), nullptr); - EXPECT_CALL(*mock_classic_link_, GetDevice()).WillRepeatedly(Return(device)); - channel_allocator_ = std::make_unique<DynamicChannelAllocator>(mock_classic_link_, handler_); - } - - void TearDown() { - channel_allocator_.reset(); - delete mock_classic_link_; - delete mock_parameter_provider_; - handler_->Clear(); - delete handler_; - delete thread_; - } - - void TestPrecondition(const uint8_t* data, size_t size) { - if (size != 2) { - return; - } - Psm psm = *reinterpret_cast<const Psm*>(data); - EXPECT_FALSE(channel_allocator_->IsPsmUsed(psm)); - } - - os::Thread* thread_{nullptr}; - os::Handler* handler_{nullptr}; - NiceMock<MockParameterProvider>* mock_parameter_provider_{nullptr}; - NiceMock<MockLink>* mock_classic_link_{nullptr}; - std::unique_ptr<DynamicChannelAllocator> channel_allocator_; -}; - -} // namespace internal -} // namespace l2cap -} // namespace bluetooth - -void RunL2capClassicDynamicChannelAllocatorFuzzTest(const uint8_t* data, size_t size) { - bluetooth::l2cap::internal::L2capClassicDynamicChannelAllocatorFuzzTest test; - test.RunTests(data, size); -} diff --git a/system/gd/l2cap/internal/dynamic_channel_allocator_test.cc b/system/gd/l2cap/internal/dynamic_channel_allocator_test.cc deleted file mode 100644 index 5cfebf666b..0000000000 --- a/system/gd/l2cap/internal/dynamic_channel_allocator_test.cc +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/internal/dynamic_channel_allocator.h" - -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include "l2cap/classic/internal/link_mock.h" -#include "l2cap/internal/parameter_provider_mock.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { - -using classic::internal::testing::MockLink; -using l2cap::internal::testing::MockParameterProvider; -using ::testing::Return; - -const hci::AddressWithType device{{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::PUBLIC_IDENTITY_ADDRESS}; - -class L2capClassicDynamicChannelAllocatorTest : public ::testing::Test { -protected: - void SetUp() override { - thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL); - handler_ = new os::Handler(thread_); - mock_parameter_provider_ = new MockParameterProvider(); - mock_classic_link_ = new MockLink(handler_, mock_parameter_provider_); - EXPECT_CALL(*mock_classic_link_, GetDevice()).WillRepeatedly(Return(device)); - channel_allocator_ = std::make_unique<DynamicChannelAllocator>(mock_classic_link_, handler_); - } - - void TearDown() override { - channel_allocator_.reset(); - delete mock_classic_link_; - delete mock_parameter_provider_; - handler_->Clear(); - delete handler_; - delete thread_; - } - - os::Thread* thread_{nullptr}; - os::Handler* handler_{nullptr}; - MockParameterProvider* mock_parameter_provider_{nullptr}; - MockLink* mock_classic_link_{nullptr}; - std::unique_ptr<DynamicChannelAllocator> channel_allocator_; -}; - -TEST_F(L2capClassicDynamicChannelAllocatorTest, precondition) { - Psm psm = 0x03; - EXPECT_FALSE(channel_allocator_->IsPsmUsed(psm)); -} - -TEST_F(L2capClassicDynamicChannelAllocatorTest, allocate_and_free_channel) { - Psm psm = 0x03; - Cid remote_cid = kFirstDynamicChannel; - auto channel = channel_allocator_->AllocateChannel(psm, remote_cid); - Cid local_cid = channel->GetCid(); - EXPECT_TRUE(channel_allocator_->IsPsmUsed(psm)); - EXPECT_EQ(channel, channel_allocator_->FindChannelByCid(local_cid)); - ASSERT_NO_FATAL_FAILURE(channel_allocator_->FreeChannel(local_cid)); - EXPECT_FALSE(channel_allocator_->IsPsmUsed(psm)); -} - -TEST_F(L2capClassicDynamicChannelAllocatorTest, reserve_channel) { - Psm psm = 0x03; - Cid remote_cid = kFirstDynamicChannel; - Cid reserved = channel_allocator_->ReserveChannel(); - auto channel = channel_allocator_->AllocateReservedChannel(reserved, psm, remote_cid); - Cid local_cid = channel->GetCid(); - EXPECT_EQ(local_cid, reserved); - EXPECT_TRUE(channel_allocator_->IsPsmUsed(psm)); - EXPECT_EQ(channel, channel_allocator_->FindChannelByCid(local_cid)); - ASSERT_NO_FATAL_FAILURE(channel_allocator_->FreeChannel(local_cid)); - EXPECT_FALSE(channel_allocator_->IsPsmUsed(psm)); -} - -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/dynamic_channel_impl.cc b/system/gd/l2cap/internal/dynamic_channel_impl.cc deleted file mode 100644 index ff47c283c7..0000000000 --- a/system/gd/l2cap/internal/dynamic_channel_impl.cc +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/internal/dynamic_channel_impl.h" - -#include <bluetooth/log.h> - -#include <unordered_map> - -#include "l2cap/cid.h" -#include "l2cap/classic/internal/link.h" -#include "l2cap/classic/security_policy.h" -#include "l2cap/internal/sender.h" -#include "l2cap/psm.h" -#include "os/handler.h" -#include "os/log.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { - -DynamicChannelImpl::DynamicChannelImpl(Psm psm, Cid cid, Cid remote_cid, - l2cap::internal::ILink* link, os::Handler* l2cap_handler) - : psm_(psm), - cid_(cid), - remote_cid_(remote_cid), - link_(link), - l2cap_handler_(l2cap_handler), - device_(link->GetDevice()) { - log::assert_that(cid_ > 0, "assert failed: cid_ > 0"); - log::assert_that(remote_cid_ > 0, "assert failed: remote_cid_ > 0"); - log::assert_that(link_ != nullptr, "assert failed: link_ != nullptr"); - log::assert_that(l2cap_handler_ != nullptr, "assert failed: l2cap_handler_ != nullptr"); -} - -hci::AddressWithType DynamicChannelImpl::GetDevice() const { return device_; } - -void DynamicChannelImpl::RegisterOnCloseCallback( - DynamicChannel::OnCloseCallback on_close_callback) { - log::assert_that(!on_close_callback_, "OnCloseCallback can only be registered once"); - // If channel is already closed, call the callback immediately without saving it - if (closed_) { - on_close_callback(close_reason_); - return; - } - on_close_callback_ = std::move(on_close_callback); -} - -void DynamicChannelImpl::Close() { - if (link_ == nullptr) { - log::error("Channel is already closed"); - return; - } - link_->SendDisconnectionRequest(cid_, remote_cid_); -} - -void DynamicChannelImpl::OnClosed(hci::ErrorCode status) { - log::assert_that(!closed_, - "Device {} Cid 0x{:x} closed twice, old status 0x{:x}, new status 0x{:x}", - ADDRESS_TO_LOGGABLE_CSTR(device_), cid_, static_cast<int>(close_reason_), - static_cast<int>(status)); - closed_ = true; - close_reason_ = status; - link_ = nullptr; - l2cap_handler_ = nullptr; - on_close_callback_(close_reason_); - on_close_callback_ = {}; -} - -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/dynamic_channel_impl.h b/system/gd/l2cap/internal/dynamic_channel_impl.h deleted file mode 100644 index c2eccfba6f..0000000000 --- a/system/gd/l2cap/internal/dynamic_channel_impl.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include "common/bidi_queue.h" -#include "hci/address.h" -#include "l2cap/cid.h" -#include "l2cap/dynamic_channel.h" -#include "l2cap/internal/channel_impl.h" -#include "l2cap/internal/ilink.h" -#include "l2cap/l2cap_packets.h" -#include "l2cap/mtu.h" -#include "l2cap/psm.h" -#include "os/handler.h" -#include "os/log.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { - -class DynamicChannelImpl : public l2cap::internal::ChannelImpl { -public: - DynamicChannelImpl(Psm psm, Cid cid, Cid remote_cid, l2cap::internal::ILink* link, - os::Handler* l2cap_handler); - - DynamicChannelImpl(const DynamicChannelImpl&) = delete; - DynamicChannelImpl& operator=(const DynamicChannelImpl&) = delete; - - virtual ~DynamicChannelImpl() = default; - - hci::AddressWithType GetDevice() const; - - virtual void RegisterOnCloseCallback(DynamicChannel::OnCloseCallback on_close_callback); - - virtual void Close(); - virtual void OnClosed(hci::ErrorCode status); - - common::BidiQueueEnd<packet::BasePacketBuilder, packet::PacketView<packet::kLittleEndian>>* - GetQueueUpEnd() { - return channel_queue_.GetUpEnd(); - } - - common::BidiQueueEnd<packet::PacketView<packet::kLittleEndian>, packet::BasePacketBuilder>* - GetQueueDownEnd() { - return channel_queue_.GetDownEnd(); - } - - virtual Cid GetCid() const { return cid_; } - - virtual Cid GetRemoteCid() const { return remote_cid_; } - - virtual Psm GetPsm() const { return psm_; } - - virtual void SetChannelTxPriority(bool high_priority) { - link_->SetChannelTxPriority(cid_, high_priority); - } - - // TODO(cmanton) Do something a little bit better than this - bool local_initiated_{false}; - -private: - const Psm psm_; - const Cid cid_; - const Cid remote_cid_; - l2cap::internal::ILink* link_; - os::Handler* l2cap_handler_; - const hci::AddressWithType device_; - - // User supported states - DynamicChannel::OnCloseCallback on_close_callback_{}; - - // Internal states - bool closed_ = false; - hci::ErrorCode close_reason_ = hci::ErrorCode::SUCCESS; - static constexpr size_t kChannelQueueSize = 5; - common::BidiQueue<packet::PacketView<packet::kLittleEndian>, packet::BasePacketBuilder> - channel_queue_{kChannelQueueSize}; -}; - -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/dynamic_channel_impl_test.cc b/system/gd/l2cap/internal/dynamic_channel_impl_test.cc deleted file mode 100644 index e356a587c8..0000000000 --- a/system/gd/l2cap/internal/dynamic_channel_impl_test.cc +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/internal/dynamic_channel_impl.h" - -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include "common/testing/bind_test_util.h" -#include "l2cap/cid.h" -#include "l2cap/classic/internal/link_mock.h" -#include "l2cap/internal/parameter_provider_mock.h" -#include "os/handler.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { - -using classic::internal::testing::MockLink; -using l2cap::internal::testing::MockParameterProvider; -using ::testing::Return; - -class L2capClassicDynamicChannelImplTest : public ::testing::Test { -public: - static void SyncHandler(os::Handler* handler) { - std::promise<void> promise; - auto future = promise.get_future(); - handler->Post(common::BindOnce(&std::promise<void>::set_value, common::Unretained(&promise))); - future.wait_for(std::chrono::milliseconds(3)); - } - -protected: - void SetUp() override { - thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL); - l2cap_handler_ = new os::Handler(thread_); - } - - void TearDown() override { - l2cap_handler_->Clear(); - delete l2cap_handler_; - delete thread_; - } - - os::Thread* thread_ = nullptr; - os::Handler* l2cap_handler_ = nullptr; -}; - -class StatusCapture { -public: - hci::ErrorCode value = hci::ErrorCode::SUCCESS; - void capture(hci::ErrorCode status) { value = status; } -}; - -TEST_F(L2capClassicDynamicChannelImplTest, get_device) { - MockParameterProvider mock_parameter_provider; - MockLink mock_classic_link(l2cap_handler_, &mock_parameter_provider); - const hci::AddressWithType device{{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::PUBLIC_IDENTITY_ADDRESS}; - EXPECT_CALL(mock_classic_link, GetDevice()).WillRepeatedly(Return(device)); - DynamicChannelImpl dynamic_channel_impl(0x01, kFirstDynamicChannel, kFirstDynamicChannel, - &mock_classic_link, l2cap_handler_); - EXPECT_EQ(device, dynamic_channel_impl.GetDevice()); -} - -TEST_F(L2capClassicDynamicChannelImplTest, close_triggers_callback) { - MockParameterProvider mock_parameter_provider; - MockLink mock_classic_link(l2cap_handler_, &mock_parameter_provider); - const hci::AddressWithType device{{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::PUBLIC_IDENTITY_ADDRESS}; - EXPECT_CALL(mock_classic_link, GetDevice()).WillRepeatedly(Return(device)); - DynamicChannelImpl dynamic_channel_impl(0x01, kFirstDynamicChannel, kFirstDynamicChannel, - &mock_classic_link, l2cap_handler_); - - // Register on close callback - auto user_handler = std::make_unique<os::Handler>(thread_); - StatusCapture* my_status = new StatusCapture(); - dynamic_channel_impl.RegisterOnCloseCallback( - user_handler->BindOnceOn(my_status, &StatusCapture::capture)); - - // Channel closure should trigger such callback - dynamic_channel_impl.OnClosed(hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION); - SyncHandler(user_handler.get()); - EXPECT_EQ(hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION, my_status->value); - - user_handler->Clear(); - delete my_status; -} - -TEST_F(L2capClassicDynamicChannelImplTest, register_callback_after_close_should_call_immediately) { - MockParameterProvider mock_parameter_provider; - MockLink mock_classic_link(l2cap_handler_, &mock_parameter_provider); - const hci::AddressWithType device{{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::PUBLIC_IDENTITY_ADDRESS}; - EXPECT_CALL(mock_classic_link, GetDevice()).WillRepeatedly(Return(device)); - DynamicChannelImpl dynamic_channel_impl(0x01, kFirstDynamicChannel, kFirstDynamicChannel, - &mock_classic_link, l2cap_handler_); - - // Channel closure should do nothing - dynamic_channel_impl.OnClosed(hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION); - - // Register on close callback should trigger callback immediately - auto user_handler = std::make_unique<os::Handler>(thread_); - StatusCapture* my_status = new StatusCapture(); - dynamic_channel_impl.RegisterOnCloseCallback( - user_handler->BindOnceOn(my_status, &StatusCapture::capture)); - - SyncHandler(user_handler.get()); - EXPECT_EQ(hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION, my_status->value); - - user_handler->Clear(); - delete my_status; -} - -TEST_F(L2capClassicDynamicChannelImplTest, close_twice_should_fail) { - MockParameterProvider mock_parameter_provider; - MockLink mock_classic_link(l2cap_handler_, &mock_parameter_provider); - const hci::AddressWithType device{{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::PUBLIC_IDENTITY_ADDRESS}; - EXPECT_CALL(mock_classic_link, GetDevice()).WillRepeatedly(Return(device)); - DynamicChannelImpl dynamic_channel_impl(0x01, kFirstDynamicChannel, kFirstDynamicChannel, - &mock_classic_link, l2cap_handler_); - - // Register on close callback - auto user_handler = std::make_unique<os::Handler>(thread_); - StatusCapture* my_status = new StatusCapture(); - dynamic_channel_impl.RegisterOnCloseCallback( - user_handler->BindOnceOn(my_status, &StatusCapture::capture)); - - // Channel closure should trigger such callback - dynamic_channel_impl.OnClosed(hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION); - SyncHandler(user_handler.get()); - EXPECT_EQ(hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION, my_status->value); - - // 2nd OnClose() callback should fail - EXPECT_DEATH(dynamic_channel_impl.OnClosed(hci::ErrorCode::PAGE_TIMEOUT), ".*OnClosed.*"); - - user_handler->Clear(); - delete my_status; -} - -TEST_F(L2capClassicDynamicChannelImplTest, multiple_registeration_should_fail) { - MockParameterProvider mock_parameter_provider; - MockLink mock_classic_link(l2cap_handler_, &mock_parameter_provider); - const hci::AddressWithType device{{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::PUBLIC_IDENTITY_ADDRESS}; - EXPECT_CALL(mock_classic_link, GetDevice()).WillRepeatedly(Return(device)); - DynamicChannelImpl dynamic_channel_impl(0x01, kFirstDynamicChannel, kFirstDynamicChannel, - &mock_classic_link, l2cap_handler_); - - // Register on close callback - auto user_handler = std::make_unique<os::Handler>(thread_); - StatusCapture* my_status = new StatusCapture(); - dynamic_channel_impl.RegisterOnCloseCallback( - user_handler->BindOnceOn(my_status, &StatusCapture::capture)); - - EXPECT_DEATH(dynamic_channel_impl.RegisterOnCloseCallback( - user_handler->BindOnce([](hci::ErrorCode status) { FAIL(); })), - ".*RegisterOnCloseCallback.*"); - - user_handler->Clear(); - delete my_status; -} - -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.cc b/system/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.cc deleted file mode 100644 index 201ab32f5c..0000000000 --- a/system/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.cc +++ /dev/null @@ -1,1067 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/internal/enhanced_retransmission_mode_channel_data_controller.h" - -#include <bluetooth/log.h> - -#include <map> -#include <queue> -#include <vector> - -#include "common/bind.h" -#include "l2cap/internal/ilink.h" -#include "os/alarm.h" -#include "packet/fragmenting_inserter.h" -#include "packet/raw_builder.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { -ErtmController::ErtmController(ILink* link, Cid cid, Cid remote_cid, - UpperQueueDownEnd* channel_queue_end, os::Handler* handler, - Scheduler* scheduler) - : link_(link), - cid_(cid), - remote_cid_(remote_cid), - enqueue_buffer_(channel_queue_end), - handler_(handler), - scheduler_(scheduler), - pimpl_(std::make_unique<impl>(this, handler)) {} - -ErtmController::~ErtmController() { enqueue_buffer_.Clear(); } - -struct ErtmController::impl { - impl(ErtmController* controller, os::Handler* handler) - : controller_(controller), - handler_(handler), - retrans_timer_(handler), - monitor_timer_(handler) {} - - ErtmController* controller_; - os::Handler* handler_; - - // We don't support extended window - static constexpr uint8_t kMaxTxWin = 64; - - // We don't support sending SREJ - static constexpr bool kSendSrej = false; - - // States (@see 8.6.5.2): Transmitter state and receiver state - - enum class TxState { - XMIT, - WAIT_F, - }; - TxState tx_state_ = TxState::XMIT; - - enum class RxState { - RECV, - REJ_SENT, - SREJ_SENT, - }; - RxState rx_state_ = RxState::RECV; - - // Variables and Timers (@see 8.6.5.3) - - uint8_t tx_seq_ = 0; - uint8_t next_tx_seq_ = 0; - uint8_t expected_ack_seq_ = 0; - uint8_t req_seq_ = 0; - uint8_t expected_tx_seq_ = 0; - uint8_t buffer_seq_ = 0; - - bool remote_busy_ = false; - bool local_busy_ = false; - int unacked_frames_ = 0; - // TODO: Instead of having a map, we may consider about a better data structure - // Map from TxSeq to (SAR, SDU size for START packet, information payload) - std::map<uint8_t, - std::tuple<SegmentationAndReassembly, uint16_t, std::shared_ptr<packet::RawBuilder>>> - unacked_list_; - // Stores (SAR, SDU size for START packet, information payload) - std::queue<std::tuple<SegmentationAndReassembly, uint16_t, std::unique_ptr<packet::RawBuilder>>> - pending_frames_; - int retry_count_ = 0; - std::map<uint8_t /* tx_seq, */, int /* count */> retry_i_frames_; - bool rnr_sent_ = false; - bool rej_actioned_ = false; - bool srej_actioned_ = false; - uint16_t srej_save_req_seq_ = 0; - bool send_rej_ = false; - int buffer_seq_srej_ = 0; - int frames_sent_ = 0; - os::Alarm retrans_timer_; - os::Alarm monitor_timer_; - - // Events (@see 8.6.5.4) - - void data_request(SegmentationAndReassembly sar, std::unique_ptr<packet::RawBuilder> pdu, - uint16_t sdu_size = 0) { - // Note: sdu_size only applies to START packet - if (tx_state_ == TxState::XMIT && !remote_busy() && rem_window_not_full()) { - send_data(sar, sdu_size, std::move(pdu)); - } else if (tx_state_ == TxState::XMIT && (remote_busy() || rem_window_full())) { - pend_data(sar, sdu_size, std::move(pdu)); - } else if (tx_state_ == TxState::WAIT_F) { - pend_data(sar, sdu_size, std::move(pdu)); - } - } - - void local_busy_detected() { local_busy_ = true; } - - void local_busy_clear() { - if (tx_state_ == TxState::XMIT && rnr_sent()) { - local_busy_ = false; - rnr_sent_ = false; - send_rr(Poll::POLL); - retry_count_ = 1; - stop_retrans_timer(); - start_monitor_timer(); - } else if (tx_state_ == TxState::XMIT) { - local_busy_ = false; - rnr_sent_ = false; - } - } - - void recv_req_seq_and_f_bit(uint8_t req_seq, Final f) { - if (tx_state_ == TxState::XMIT) { - process_req_seq(req_seq); - } else if (f == Final::POLL_RESPONSE) { - process_req_seq(req_seq); - stop_monitor_timer(); - if (unacked_frames_ > 0) { - start_retrans_timer(); - } - tx_state_ = TxState::XMIT; - } else { - process_req_seq(req_seq); - } - } - - void recv_f_bit(Final f) { - if (tx_state_ == TxState::WAIT_F && f == Final::POLL_RESPONSE) { - stop_monitor_timer(); - if (unacked_frames_ > 0) { - start_retrans_timer(); - } - tx_state_ = TxState::XMIT; - } - } - - void retrans_timer_expires() { - if (tx_state_ == TxState::XMIT) { - send_rr_or_rnr(Poll::POLL); - // send rr or rnr(p=1) - retry_count_ = 1; - start_monitor_timer(); - tx_state_ = TxState::WAIT_F; - } - } - - void monitor_timer_expires() { - if (tx_state_ == TxState::WAIT_F && retry_count_less_than_max_transmit()) { - retry_count_++; - send_rr_or_rnr(Poll::POLL); - start_monitor_timer(); - } else if (tx_state_ == TxState::WAIT_F) { - log::info("Close channel because max transmit reached"); - CloseChannel(); - } - } - - void recv_i_frame(Final f, uint8_t tx_seq, uint8_t req_seq, SegmentationAndReassembly sar, - uint16_t sdu_size, const packet::PacketView<true>& payload) { - if (rx_state_ == RxState::RECV) { - if (f == Final::NOT_SET && with_expected_tx_seq(tx_seq) && with_valid_req_seq(req_seq) && - with_valid_f_bit(f) && !local_busy()) { - increment_expected_tx_seq(); - pass_to_tx(req_seq, f); - data_indication(sar, sdu_size, payload); - send_ack(Final::NOT_SET); - } else if (f == Final::POLL_RESPONSE && with_expected_tx_seq(tx_seq) && - with_valid_req_seq(req_seq) && with_valid_f_bit(f) && !local_busy()) { - increment_expected_tx_seq(); - pass_to_tx(req_seq, f); - data_indication(sar, sdu_size, payload); - if (!rej_actioned_) { - retransmit_i_frames(req_seq); - send_pending_i_frames(); - } else { - rej_actioned_ = false; - } - send_ack(Final::NOT_SET); - } else if (with_duplicate_tx_seq(tx_seq) && with_valid_req_seq(req_seq) && - with_valid_f_bit(f) && !local_busy()) { - pass_to_tx(req_seq, f); - } else if (with_unexpected_tx_seq(tx_seq) && with_valid_req_seq(req_seq) && - with_valid_f_bit(f) && !local_busy()) { - if constexpr (kSendSrej) { - // We don't support sending SREJ - } else { - pass_to_tx(req_seq, f); - send_rej(); - rx_state_ = RxState::REJ_SENT; - } - } else if (with_expected_tx_seq(tx_seq) && with_valid_req_seq(req_seq) && - with_valid_f_bit(f) && local_busy()) { - pass_to_tx(req_seq, f); - store_or_ignore(); - } else if (with_valid_req_seq(req_seq) && not_with_expected_tx_seq(tx_seq) && - with_valid_f_bit(f) && local_busy()) { - pass_to_tx(req_seq, f); - } else if ((with_invalid_tx_seq(tx_seq) && controller_->local_tx_window_ > kMaxTxWin / 2) || - with_invalid_req_seq(req_seq)) { - CloseChannel(); - } else if (with_invalid_tx_seq(tx_seq) && controller_->local_tx_window_ <= kMaxTxWin / 2) { - // We decided to ignore - } - } else if (rx_state_ == RxState::REJ_SENT) { - if (f == Final::NOT_SET && with_expected_tx_seq(tx_seq) && with_valid_req_seq(req_seq) && - with_valid_f_bit(f)) { - increment_expected_tx_seq(); - pass_to_tx(req_seq, f); - data_indication(sar, sdu_size, payload); - send_ack(Final::NOT_SET); - rx_state_ = RxState::RECV; - } else if (f == Final::POLL_RESPONSE && with_expected_tx_seq(tx_seq) && - with_valid_req_seq(req_seq) && with_valid_f_bit(f)) { - increment_expected_tx_seq(); - pass_to_tx(req_seq, f); - data_indication(sar, sdu_size, payload); - if (!rej_actioned_) { - retransmit_i_frames(req_seq); - send_pending_i_frames(); - } else { - rej_actioned_ = false; - } - send_ack(Final::NOT_SET); - rx_state_ = RxState::RECV; - } else if (with_unexpected_tx_seq(tx_seq) && with_valid_req_seq(req_seq) && - with_valid_f_bit(f)) { - pass_to_tx(req_seq, f); - } - } else if (rx_state_ == RxState::SREJ_SENT) { - // SREJ NOT SUPPORTED - } - } - - void recv_rr(uint8_t req_seq, Poll p = Poll::NOT_SET, Final f = Final::NOT_SET) { - if (rx_state_ == RxState::RECV) { - if (p == Poll::NOT_SET && f == Final::NOT_SET && with_valid_req_seq(req_seq) && - with_valid_f_bit(f)) { - pass_to_tx(req_seq, f); - if (remote_busy() && unacked_frames_ > 0) { - start_retrans_timer(); - } - remote_busy_ = false; - send_pending_i_frames(); - } else if (f == Final::POLL_RESPONSE && with_valid_req_seq(req_seq) && with_valid_f_bit(f)) { - remote_busy_ = false; - pass_to_tx(req_seq, f); - if (!rej_actioned_) { - retransmit_i_frames(req_seq, p); - } else { - rej_actioned_ = false; - } - send_pending_i_frames(); - } else if (p == Poll::POLL && with_valid_req_seq(req_seq) && with_valid_f_bit(f)) { - pass_to_tx(req_seq, f); - send_i_or_rr_or_rnr(Final::POLL_RESPONSE); - } else if (with_invalid_req_seq(req_seq)) { - CloseChannel(); - } - } else if (rx_state_ == RxState::REJ_SENT) { - if (f == Final::POLL_RESPONSE && with_valid_req_seq(req_seq) && with_valid_f_bit(f)) { - remote_busy_ = false; - pass_to_tx(req_seq, f); - if (!rej_actioned_) { - retransmit_i_frames(req_seq, p); - } else { - rej_actioned_ = false; - } - send_pending_i_frames(); - } else if (p == Poll::NOT_SET && f == Final::NOT_SET && with_valid_req_seq(req_seq) && - with_valid_f_bit(f)) { - pass_to_tx(req_seq, f); - if (remote_busy() && unacked_frames_ > 0) { - start_retrans_timer(); - } - remote_busy_ = false; - send_ack(Final::NOT_SET); - } else if (p == Poll::POLL && with_valid_req_seq(req_seq) && with_valid_f_bit(f)) { - pass_to_tx(req_seq, f); - if (remote_busy() && unacked_frames_ > 0) { - start_retrans_timer(); - } - remote_busy_ = false; - send_rr(Final::POLL_RESPONSE); - } else if (with_invalid_req_seq(req_seq)) { - CloseChannel(); - } - } else if (rx_state_ == RxState::SREJ_SENT) { - // SREJ NOT SUPPORTED - } - } - - void recv_rej(uint8_t req_seq, Poll p = Poll::NOT_SET, Final f = Final::NOT_SET) { - if (rx_state_ == RxState::RECV) { - if (f == Final::NOT_SET && with_valid_req_seq_retrans(req_seq) && - retry_i_frames_less_than_max_transmit(req_seq) && with_valid_f_bit(f)) { - remote_busy_ = false; - pass_to_tx(req_seq, f); - retransmit_i_frames(req_seq, p); - send_pending_i_frames(); - if (p_bit_outstanding()) { - rej_actioned_ = true; - } - } else if (f == Final::POLL_RESPONSE && with_valid_req_seq_retrans(req_seq) && - retry_i_frames_less_than_max_transmit(req_seq) && with_valid_f_bit(f)) { - remote_busy_ = false; - pass_to_tx(req_seq, f); - if (!rej_actioned_) { - retransmit_i_frames(req_seq, p); - } else { - rej_actioned_ = false; - } - send_pending_i_frames(); - } else if (with_valid_req_seq_retrans(req_seq) && - !retry_i_frames_less_than_max_transmit(req_seq)) { - CloseChannel(); - } else if (with_invalid_req_seq_retrans(req_seq)) { - CloseChannel(); - } - } else if (rx_state_ == RxState::REJ_SENT) { - if (f == Final::NOT_SET && with_valid_req_seq_retrans(req_seq) && - retry_i_frames_less_than_max_transmit(req_seq) && with_valid_f_bit(f)) { - remote_busy_ = false; - pass_to_tx(req_seq, f); - retransmit_i_frames(req_seq, p); - send_pending_i_frames(); - if (p_bit_outstanding()) { - rej_actioned_ = true; - } - } else if (f == Final::POLL_RESPONSE && with_valid_req_seq_retrans(req_seq) && - retry_i_frames_less_than_max_transmit(req_seq) && with_valid_f_bit(f)) { - remote_busy_ = false; - pass_to_tx(req_seq, f); - if (!rej_actioned_) { - retransmit_i_frames(req_seq, p); - } else { - rej_actioned_ = false; - } - send_pending_i_frames(); - } else if (with_valid_req_seq_retrans(req_seq) && - !retry_i_frames_less_than_max_transmit(req_seq)) { - CloseChannel(); - } else if (with_invalid_req_seq_retrans(req_seq)) { - CloseChannel(); - } - } else if (rx_state_ == RxState::SREJ_SENT) { - // SREJ NOT SUPPORTED - } - } - - void recv_rnr(uint8_t req_seq, Poll p = Poll::NOT_SET, Final f = Final::NOT_SET) { - if (rx_state_ == RxState::RECV) { - if (p == Poll::NOT_SET && with_valid_req_seq(req_seq) && with_valid_f_bit(f)) { - remote_busy_ = true; - pass_to_tx(req_seq, f); - stop_retrans_timer(); - } else if (p == Poll::POLL && with_valid_req_seq(req_seq) && with_valid_f_bit(f)) { - remote_busy_ = true; - pass_to_tx(req_seq, f); - stop_retrans_timer(); - send_rr_or_rnr(Poll::NOT_SET, Final::POLL_RESPONSE); - } else if (with_invalid_req_seq_retrans(req_seq)) { - CloseChannel(); - } - } else if (rx_state_ == RxState::REJ_SENT) { - if (p == Poll::NOT_SET && with_valid_req_seq(req_seq) && with_valid_f_bit(f)) { - remote_busy_ = true; - pass_to_tx(req_seq, f); - send_rr(Final::POLL_RESPONSE); - } else if (p == Poll::POLL && with_valid_req_seq(req_seq) && with_valid_f_bit(f)) { - remote_busy_ = true; - pass_to_tx(req_seq, f); - send_rr(Final::NOT_SET); - } else if (with_invalid_req_seq_retrans(req_seq)) { - CloseChannel(); - } - } else if (rx_state_ == RxState::SREJ_SENT) { - // SREJ NOT SUPPORTED - } - } - - void recv_srej(uint8_t req_seq, Poll p = Poll::NOT_SET, Final f = Final::NOT_SET) { - if (rx_state_ == RxState::RECV) { - if (p == Poll::NOT_SET && f == Final::NOT_SET && with_valid_req_seq_retrans(req_seq) && - retry_i_frames_less_than_max_transmit(req_seq) && with_valid_f_bit(f)) { - remote_busy_ = false; - pass_to_tx_f_bit(f); - retransmit_requested_i_frame(req_seq, p); - if (p_bit_outstanding()) { - srej_actioned_ = true; - srej_save_req_seq_ = req_seq; - } - } else if (f == Final::POLL_RESPONSE && with_valid_req_seq_retrans(req_seq) && - retry_i_frames_less_than_max_transmit(req_seq) && with_valid_f_bit(f)) { - remote_busy_ = false; - pass_to_tx_f_bit(f); - if (srej_actioned_ && srej_save_req_seq_ == req_seq) { - srej_actioned_ = false; - } else { - retransmit_requested_i_frame(req_seq, p); - } - } else if (p == Poll::POLL && with_valid_req_seq_retrans(req_seq) && - retry_i_frames_less_than_max_transmit(req_seq) && with_valid_f_bit(f)) { - remote_busy_ = false; - pass_to_tx(req_seq, f); - retransmit_requested_i_frame(req_seq, p); - send_pending_i_frames(); - if (p_bit_outstanding()) { - srej_actioned_ = true; - srej_save_req_seq_ = req_seq; - } - } else if (with_valid_req_seq_retrans(req_seq) && - !retry_i_frames_less_than_max_transmit(req_seq)) { - CloseChannel(); - } else if (with_invalid_req_seq_retrans(req_seq)) { - CloseChannel(); - } - } else if (rx_state_ == RxState::REJ_SENT) { - if (p == Poll::NOT_SET && f == Final::NOT_SET && with_valid_req_seq_retrans(req_seq) && - retry_i_frames_less_than_max_transmit(req_seq) && with_valid_f_bit(f)) { - remote_busy_ = false; - pass_to_tx_f_bit(f); - retransmit_requested_i_frame(req_seq, p); - if (p_bit_outstanding()) { - srej_actioned_ = true; - srej_save_req_seq_ = req_seq; - } - } else if (f == Final::POLL_RESPONSE && with_valid_req_seq_retrans(req_seq) && - retry_i_frames_less_than_max_transmit(req_seq) && with_valid_f_bit(f)) { - remote_busy_ = false; - pass_to_tx_f_bit(f); - if (srej_actioned_ && srej_save_req_seq_ == req_seq) { - srej_actioned_ = false; - } else { - retransmit_requested_i_frame(req_seq, p); - } - } else if (p == Poll::POLL && with_valid_req_seq_retrans(req_seq) && - retry_i_frames_less_than_max_transmit(req_seq) && with_valid_f_bit(f)) { - remote_busy_ = false; - pass_to_tx(req_seq, f); - retransmit_requested_i_frame(req_seq, p); - send_pending_i_frames(); - if (p_bit_outstanding()) { - srej_actioned_ = true; - srej_save_req_seq_ = req_seq; - } - } else if (with_valid_req_seq_retrans(req_seq) && - !retry_i_frames_less_than_max_transmit(req_seq)) { - CloseChannel(); - } else if (with_invalid_req_seq_retrans(req_seq)) { - CloseChannel(); - } - } else if (rx_state_ == RxState::SREJ_SENT) { - // SREJ NOT SUPPORTED - } - } - - // Conditions (@see 8.6.5.5) - bool remote_busy() { return remote_busy_; } - - bool local_busy() { return local_busy_; } - - bool rem_window_not_full() { return unacked_frames_ < controller_->remote_tx_window_; } - - bool rem_window_full() { return unacked_frames_ == controller_->remote_tx_window_; } - - bool rnr_sent() { return rnr_sent_; } - - bool retry_i_frames_less_than_max_transmit(uint8_t req_seq) { - return retry_i_frames_[req_seq] < controller_->local_max_transmit_; - } - - bool retry_count_less_than_max_transmit() { - return retry_count_ < controller_->local_max_transmit_; - } - - // Compares two sequence numbers (tx_seq or rx_seq) - bool sequence_less_than(uint8_t x, uint8_t y) { - // Assuming the maximum overflow of sequence number is the same as local_tx_window_ (10 by - // default). - return x < y || kMaxTxWin - (x - y) < controller_->local_tx_window_; - } - - // Compares two sequence numbers (tx_seq or rx_seq) - bool sequence_less_than_or_equal(uint8_t x, uint8_t y) { - // Assuming the maximum overflow of sequence number is the same as local_tx_window_ (10 by - // default). - return x <= y || kMaxTxWin - (x - y) <= controller_->local_tx_window_; - } - - bool with_expected_tx_seq(uint8_t tx_seq) { return tx_seq == expected_tx_seq_; } - - bool with_valid_req_seq(uint8_t req_seq) { - return sequence_less_than_or_equal(expected_ack_seq_, req_seq) && - sequence_less_than_or_equal(req_seq, next_tx_seq_); - } - - bool with_valid_req_seq_retrans(uint8_t req_seq) { - return sequence_less_than_or_equal(expected_ack_seq_, req_seq) && - sequence_less_than_or_equal(req_seq, next_tx_seq_); - } - - bool with_valid_f_bit(Final f) { return f == Final::NOT_SET ^ tx_state_ == TxState::WAIT_F; } - - bool with_unexpected_tx_seq(uint8_t tx_seq) { - return sequence_less_than(expected_tx_seq_, tx_seq) && - sequence_less_than_or_equal(tx_seq, expected_tx_seq_ + controller_->local_tx_window_); - } - - bool with_duplicate_tx_seq(uint8_t tx_seq) { - return sequence_less_than(tx_seq, expected_tx_seq_) && - sequence_less_than_or_equal(expected_tx_seq_ - controller_->local_tx_window_, tx_seq); - } - - bool with_invalid_tx_seq(uint8_t tx_seq) { - return sequence_less_than(tx_seq, expected_tx_seq_ - controller_->local_tx_window_) || - sequence_less_than(expected_tx_seq_ + controller_->local_tx_window_, tx_seq); - } - - bool with_invalid_req_seq(uint8_t req_seq) { - return sequence_less_than(req_seq, expected_ack_seq_) || - sequence_less_than(next_tx_seq_, req_seq); - } - - bool with_invalid_req_seq_retrans(uint8_t req_seq) { - return sequence_less_than(req_seq, expected_ack_seq_) || - sequence_less_than(next_tx_seq_, req_seq); - } - - bool not_with_expected_tx_seq(uint8_t tx_seq) { - return !with_invalid_tx_seq(tx_seq) && !with_expected_tx_seq(tx_seq); - } - - bool with_expected_tx_seq_srej() { - // We don't support sending SREJ - return false; - } - - bool send_req_is_true() { - // We don't support sending SREJ - return false; - } - - bool srej_list_is_one() { - // We don't support sending SREJ - return false; - } - - bool with_unexpected_tx_seq_srej() { - // We don't support sending SREJ - return false; - } - - bool with_duplicate_tx_seq_srej() { - // We don't support sending SREJ - return false; - } - - // Actions (@see 8.6.5.6) - - void _send_i_frame(SegmentationAndReassembly sar, std::unique_ptr<CopyablePacketBuilder> segment, - uint8_t req_seq, uint8_t tx_seq, uint16_t sdu_size = 0, - Final f = Final::NOT_SET) { - std::unique_ptr<packet::BasePacketBuilder> builder; - if (sar == SegmentationAndReassembly::START) { - if (controller_->fcs_enabled_) { - builder = EnhancedInformationStartFrameWithFcsBuilder::Create( - controller_->remote_cid_, tx_seq, f, req_seq, sdu_size, std::move(segment)); - } else { - builder = EnhancedInformationStartFrameBuilder::Create( - controller_->remote_cid_, tx_seq, f, req_seq, sdu_size, std::move(segment)); - } - } else { - if (controller_->fcs_enabled_) { - builder = EnhancedInformationFrameWithFcsBuilder::Create( - controller_->remote_cid_, tx_seq, f, req_seq, sar, std::move(segment)); - } else { - builder = EnhancedInformationFrameBuilder::Create(controller_->remote_cid_, tx_seq, f, - req_seq, sar, std::move(segment)); - } - } - controller_->send_pdu(std::move(builder)); - } - - void send_data(SegmentationAndReassembly sar, uint16_t sdu_size, - std::unique_ptr<packet::RawBuilder> segment, Final f = Final::NOT_SET) { - std::shared_ptr<packet::RawBuilder> shared_segment(segment.release()); - unacked_list_.emplace(std::piecewise_construct, std::forward_as_tuple(next_tx_seq_), - std::forward_as_tuple(sar, sdu_size, shared_segment)); - - std::unique_ptr<CopyablePacketBuilder> copyable_packet_builder = - std::make_unique<CopyablePacketBuilder>( - std::get<2>(unacked_list_.find(next_tx_seq_)->second)); - _send_i_frame(sar, std::move(copyable_packet_builder), buffer_seq_, next_tx_seq_, sdu_size, f); - unacked_frames_++; - frames_sent_++; - retry_i_frames_[next_tx_seq_] = 1; - next_tx_seq_ = (next_tx_seq_ + 1) % kMaxTxWin; - start_retrans_timer(); - } - - void pend_data(SegmentationAndReassembly sar, uint16_t sdu_size, - std::unique_ptr<packet::RawBuilder> data) { - pending_frames_.emplace(std::make_tuple(sar, sdu_size, std::move(data))); - } - - void process_req_seq(uint8_t req_seq) { - for (int i = expected_ack_seq_; i < req_seq; i++) { - unacked_list_.erase(i); - retry_i_frames_[i] = 0; - } - unacked_frames_ -= ((req_seq - expected_ack_seq_) + kMaxTxWin) % kMaxTxWin; - expected_ack_seq_ = req_seq; - if (unacked_frames_ == 0) { - stop_retrans_timer(); - } - } - - void _send_s_frame(SupervisoryFunction s, uint8_t req_seq, Poll p, Final f) { - std::unique_ptr<packet::BasePacketBuilder> builder; - if (controller_->fcs_enabled_) { - builder = EnhancedSupervisoryFrameWithFcsBuilder::Create(controller_->remote_cid_, s, p, f, - req_seq); - } else { - builder = EnhancedSupervisoryFrameBuilder::Create(controller_->remote_cid_, s, p, f, req_seq); - } - controller_->send_pdu(std::move(builder)); - } - - void send_rr(Poll p) { - _send_s_frame(SupervisoryFunction::RECEIVER_READY, expected_tx_seq_, p, Final::NOT_SET); - } - - void send_rr(Final f) { - _send_s_frame(SupervisoryFunction::RECEIVER_READY, expected_tx_seq_, Poll::NOT_SET, f); - } - - void send_rnr(Poll p) { - _send_s_frame(SupervisoryFunction::RECEIVER_NOT_READY, expected_tx_seq_, p, Final::NOT_SET); - } - - void send_rnr(Final f) { - _send_s_frame(SupervisoryFunction::RECEIVER_NOT_READY, expected_tx_seq_, Poll::NOT_SET, f); - rnr_sent_ = true; - } - - void send_rej(Poll p = Poll::NOT_SET, Final f = Final::NOT_SET) { - _send_s_frame(SupervisoryFunction::REJECT, expected_tx_seq_, p, f); - } - - void send_rr_or_rnr(Poll p = Poll::NOT_SET, Final f = Final::NOT_SET) { - if (local_busy()) { - _send_s_frame(SupervisoryFunction::RECEIVER_NOT_READY, buffer_seq_, p, f); - } else { - _send_s_frame(SupervisoryFunction::RECEIVER_READY, buffer_seq_, p, f); - } - } - - void send_i_or_rr_or_rnr(Final f = Final::POLL_RESPONSE) { - auto frames_sent = 0; - if (local_busy()) { - send_rnr(Final::POLL_RESPONSE); - } - if (remote_busy() && unacked_frames_ > 0) { - start_retrans_timer(); - } - remote_busy_ = false; - send_pending_i_frames(f); // TODO: Only first has f = 1, other f = 0. Also increase frames_sent - if (!local_busy() && frames_sent == 0) { - send_rr(Final::POLL_RESPONSE); - } - } - - void send_srej() { - // Sending SREJ is not supported - } - - void start_retrans_timer() { - retrans_timer_.Schedule( - common::BindOnce(&impl::retrans_timer_expires, common::Unretained(this)), - std::chrono::milliseconds(controller_->local_retransmit_timeout_ms_)); - } - - void start_monitor_timer() { - monitor_timer_.Schedule( - common::BindOnce(&impl::monitor_timer_expires, common::Unretained(this)), - std::chrono::milliseconds(controller_->local_monitor_timeout_ms_)); - } - - void pass_to_tx(uint8_t req_seq, Final f) { recv_req_seq_and_f_bit(req_seq, f); } - - void pass_to_tx_f_bit(Final f) { recv_f_bit(f); } - - void data_indication(SegmentationAndReassembly sar, uint16_t sdu_size, - const packet::PacketView<true>& segment) { - controller_->stage_for_reassembly(sar, sdu_size, segment); - buffer_seq_ = (buffer_seq_ + 1) % kMaxTxWin; - } - - void increment_expected_tx_seq() { expected_tx_seq_ = (expected_tx_seq_ + 1) % kMaxTxWin; } - - void stop_retrans_timer() { retrans_timer_.Cancel(); } - - void stop_monitor_timer() { monitor_timer_.Cancel(); } - - void send_ack(Final f = Final::NOT_SET) { - if (local_busy()) { - send_rnr(f); - } else if (!remote_busy() && !pending_frames_.empty() && rem_window_not_full()) { - send_pending_i_frames(f); - } else { - send_rr(f); - } - } - - void init_srej() { - // We don't support sending SREJ - } - - void save_i_frame_srej() { - // We don't support sending SREJ - } - - void store_or_ignore() { - // We choose to ignore. - } - - bool p_bit_outstanding() { return tx_state_ == TxState::WAIT_F; } - - void retransmit_i_frames(uint8_t req_seq, Poll p = Poll::NOT_SET) { - uint8_t i = req_seq; - Final f = (p == Poll::NOT_SET ? Final::NOT_SET : Final::POLL_RESPONSE); - while (unacked_list_.find(i) != unacked_list_.end()) { - if (retry_i_frames_[i] == controller_->local_max_transmit_) { - CloseChannel(); - return; - } - std::unique_ptr<CopyablePacketBuilder> copyable_packet_builder = - std::make_unique<CopyablePacketBuilder>(std::get<2>(unacked_list_.find(i)->second)); - _send_i_frame(std::get<0>(unacked_list_.find(i)->second), std::move(copyable_packet_builder), - buffer_seq_, i, std::get<1>(unacked_list_.find(i)->second), f); - retry_i_frames_[i]++; - frames_sent_++; - f = Final::NOT_SET; - i++; - } - if (i != req_seq) { - start_retrans_timer(); - } - } - - void retransmit_requested_i_frame(uint8_t req_seq, Poll p) { - Final f = p == Poll::POLL ? Final::POLL_RESPONSE : Final::NOT_SET; - if (unacked_list_.find(req_seq) == unacked_list_.end()) { - log::error("Received invalid SREJ"); - return; - } - std::unique_ptr<CopyablePacketBuilder> copyable_packet_builder = - std::make_unique<CopyablePacketBuilder>( - std::get<2>(unacked_list_.find(req_seq)->second)); - _send_i_frame(std::get<0>(unacked_list_.find(req_seq)->second), - std::move(copyable_packet_builder), buffer_seq_, req_seq, - std::get<1>(unacked_list_.find(req_seq)->second), f); - retry_i_frames_[req_seq]++; - start_retrans_timer(); - } - - void send_pending_i_frames(Final f = Final::NOT_SET) { - if (p_bit_outstanding()) { - return; - } - while (rem_window_not_full() && !pending_frames_.empty()) { - auto& frame = pending_frames_.front(); - send_data(std::get<0>(frame), std::get<1>(frame), std::move(std::get<2>(frame)), f); - pending_frames_.pop(); - f = Final::NOT_SET; - } - } - - void CloseChannel() { controller_->close_channel(); } - - void pop_srej_list() { - // We don't support sending SREJ - } - - void data_indication_srej() { - // We don't support sending SREJ - } -}; - -// Segmentation is handled here -void ErtmController::OnSdu(std::unique_ptr<packet::BasePacketBuilder> sdu) { - auto sdu_size = sdu->size(); - std::vector<std::unique_ptr<packet::RawBuilder>> segments; - auto size_each_packet = (remote_mps_ - 4 /* basic L2CAP header */ - 2 /* SDU length */ - - 2 /* Enhanced control */ - (fcs_enabled_ ? 2 : 0)); - packet::FragmentingInserter fragmenting_inserter(size_each_packet, - std::back_insert_iterator(segments)); - sdu->Serialize(fragmenting_inserter); - fragmenting_inserter.finalize(); - if (segments.size() == 1) { - pimpl_->data_request(SegmentationAndReassembly::UNSEGMENTED, std::move(segments[0])); - return; - } - pimpl_->data_request(SegmentationAndReassembly::START, std::move(segments[0]), sdu_size); - for (size_t i = 1; i < segments.size() - 1; i++) { - pimpl_->data_request(SegmentationAndReassembly::CONTINUATION, std::move(segments[i])); - } - pimpl_->data_request(SegmentationAndReassembly::END, std::move(segments.back())); -} - -void ErtmController::OnPdu(packet::PacketView<true> pdu) { - if (fcs_enabled_) { - on_pdu_fcs(pdu); - } else { - on_pdu_no_fcs(pdu); - } -} - -void ErtmController::on_pdu_no_fcs(const packet::PacketView<true>& pdu) { - auto basic_frame_view = BasicFrameView::Create(pdu); - if (!basic_frame_view.IsValid()) { - return; - } - auto standard_frame_view = StandardFrameView::Create(basic_frame_view); - if (!standard_frame_view.IsValid()) { - log::warn("Received invalid frame"); - return; - } - auto type = standard_frame_view.GetFrameType(); - if (type == FrameType::I_FRAME) { - auto i_frame_view = EnhancedInformationFrameView::Create(standard_frame_view); - if (!i_frame_view.IsValid()) { - log::warn("Received invalid frame"); - return; - } - Final f = i_frame_view.GetF(); - uint8_t tx_seq = i_frame_view.GetTxSeq(); - uint8_t req_seq = i_frame_view.GetReqSeq(); - auto sar = i_frame_view.GetSar(); - if (sar == SegmentationAndReassembly::START) { - auto i_frame_start_view = EnhancedInformationStartFrameView::Create(i_frame_view); - if (!i_frame_start_view.IsValid()) { - log::warn("Received invalid I-Frame START"); - return; - } - pimpl_->recv_i_frame(f, tx_seq, req_seq, sar, i_frame_start_view.GetL2capSduLength(), - i_frame_start_view.GetPayload()); - } else { - pimpl_->recv_i_frame(f, tx_seq, req_seq, sar, 0, i_frame_view.GetPayload()); - } - } else if (type == FrameType::S_FRAME) { - auto s_frame_view = EnhancedSupervisoryFrameView::Create(standard_frame_view); - if (!s_frame_view.IsValid()) { - log::warn("Received invalid frame"); - return; - } - auto req_seq = s_frame_view.GetReqSeq(); - auto f = s_frame_view.GetF(); - auto p = s_frame_view.GetP(); - switch (s_frame_view.GetS()) { - case SupervisoryFunction::RECEIVER_READY: - pimpl_->recv_rr(req_seq, p, f); - break; - case SupervisoryFunction::RECEIVER_NOT_READY: - pimpl_->recv_rnr(req_seq, p, f); - break; - case SupervisoryFunction::REJECT: - pimpl_->recv_rej(req_seq, p, f); - break; - case SupervisoryFunction::SELECT_REJECT: - pimpl_->recv_srej(req_seq, p, f); - break; - } - } else { - log::warn("Received invalid frame"); - } -} - -void ErtmController::on_pdu_fcs(const packet::PacketView<true>& pdu) { - auto basic_frame_view = BasicFrameWithFcsView::Create(pdu); - if (!basic_frame_view.IsValid()) { - return; - } - auto standard_frame_view = StandardFrameWithFcsView::Create(basic_frame_view); - if (!standard_frame_view.IsValid()) { - log::warn("Received invalid frame"); - return; - } - auto type = standard_frame_view.GetFrameType(); - if (type == FrameType::I_FRAME) { - auto i_frame_view = EnhancedInformationFrameWithFcsView::Create(standard_frame_view); - if (!i_frame_view.IsValid()) { - log::warn("Received invalid frame"); - return; - } - Final f = i_frame_view.GetF(); - uint8_t tx_seq = i_frame_view.GetTxSeq(); - uint8_t req_seq = i_frame_view.GetReqSeq(); - auto sar = i_frame_view.GetSar(); - if (sar == SegmentationAndReassembly::START) { - auto i_frame_start_view = EnhancedInformationStartFrameWithFcsView::Create(i_frame_view); - if (!i_frame_start_view.IsValid()) { - log::warn("Received invalid I-Frame START"); - return; - } - pimpl_->recv_i_frame(f, tx_seq, req_seq, sar, i_frame_start_view.GetL2capSduLength(), - i_frame_start_view.GetPayload()); - } else { - pimpl_->recv_i_frame(f, tx_seq, req_seq, sar, 0, i_frame_view.GetPayload()); - } - } else if (type == FrameType::S_FRAME) { - auto s_frame_view = EnhancedSupervisoryFrameWithFcsView::Create(standard_frame_view); - if (!s_frame_view.IsValid()) { - log::warn("Received invalid frame"); - return; - } - auto req_seq = s_frame_view.GetReqSeq(); - auto f = s_frame_view.GetF(); - auto p = s_frame_view.GetP(); - switch (s_frame_view.GetS()) { - case SupervisoryFunction::RECEIVER_READY: - pimpl_->recv_rr(req_seq, p, f); - break; - case SupervisoryFunction::RECEIVER_NOT_READY: - pimpl_->recv_rnr(req_seq, p, f); - break; - case SupervisoryFunction::REJECT: - pimpl_->recv_rej(req_seq, p, f); - break; - case SupervisoryFunction::SELECT_REJECT: - pimpl_->recv_srej(req_seq, p, f); - break; - } - } else { - log::warn("Received invalid frame"); - } -} - -std::unique_ptr<packet::BasePacketBuilder> ErtmController::GetNextPacket() { - auto next = std::move(pdu_queue_.front()); - pdu_queue_.pop(); - return next; -} - -void ErtmController::stage_for_reassembly(SegmentationAndReassembly sar, uint16_t sdu_size, - const packet::PacketView<kLittleEndian>& payload) { - // If EnqueueBuffer has more than 1 packets, we claim LocalBusy, until queue is empty - constexpr size_t kEnqueueBufferBusyThreshold = 3; - switch (sar) { - case SegmentationAndReassembly::UNSEGMENTED: - if (sar_state_ != SegmentationAndReassembly::END) { - log::warn("Received invalid SAR"); - close_channel(); - return; - } - // TODO: Enforce MTU - enqueue_buffer_.Enqueue(std::make_unique<packet::PacketView<kLittleEndian>>(payload), - handler_); - if (enqueue_buffer_.Size() == kEnqueueBufferBusyThreshold) { - pimpl_->local_busy_detected(); - enqueue_buffer_.NotifyOnEmpty( - common::BindOnce(&impl::local_busy_clear, common::Unretained(pimpl_.get()))); - } - break; - case SegmentationAndReassembly::START: - if (sar_state_ != SegmentationAndReassembly::END) { - log::warn("Received invalid SAR"); - close_channel(); - return; - } - // TODO: Enforce MTU - sar_state_ = SegmentationAndReassembly::START; - reassembly_stage_ = payload; - remaining_sdu_continuation_packet_size_ = sdu_size - payload.size(); - break; - case SegmentationAndReassembly::CONTINUATION: - if (sar_state_ == SegmentationAndReassembly::END) { - log::warn("Received invalid SAR"); - close_channel(); - return; - } - reassembly_stage_.AppendPacketView(payload); - remaining_sdu_continuation_packet_size_ -= payload.size(); - break; - case SegmentationAndReassembly::END: - if (sar_state_ == SegmentationAndReassembly::END) { - log::warn("Received invalid SAR"); - close_channel(); - return; - } - sar_state_ = SegmentationAndReassembly::END; - remaining_sdu_continuation_packet_size_ -= payload.size(); - if (remaining_sdu_continuation_packet_size_ != 0) { - log::warn("Received invalid END I-Frame"); - reassembly_stage_ = PacketViewForReassembly( - PacketView<kLittleEndian>(std::make_shared<std::vector<uint8_t>>())); - remaining_sdu_continuation_packet_size_ = 0; - close_channel(); - return; - } - reassembly_stage_.AppendPacketView(payload); - enqueue_buffer_.Enqueue( - std::make_unique<packet::PacketView<kLittleEndian>>(reassembly_stage_), handler_); - if (enqueue_buffer_.Size() == kEnqueueBufferBusyThreshold) { - pimpl_->local_busy_detected(); - enqueue_buffer_.NotifyOnEmpty( - common::BindOnce(&impl::local_busy_clear, common::Unretained(pimpl_.get()))); - } - break; - } -} - -void ErtmController::EnableFcs(bool enabled) { fcs_enabled_ = enabled; } - -void ErtmController::send_pdu(std::unique_ptr<packet::BasePacketBuilder> pdu) { - pdu_queue_.emplace(std::move(pdu)); - scheduler_->OnPacketsReady(cid_, 1); -} - -void ErtmController::SetRetransmissionAndFlowControlOptions( - const RetransmissionAndFlowControlConfigurationOption& option) { - remote_tx_window_ = option.tx_window_size_; - local_max_transmit_ = option.max_transmit_; - local_retransmit_timeout_ms_ = option.retransmission_time_out_; - local_monitor_timeout_ms_ = option.monitor_time_out_; - remote_mps_ = option.maximum_pdu_size_; -} - -void ErtmController::close_channel() { link_->SendDisconnectionRequest(cid_, remote_cid_); } - -size_t ErtmController::CopyablePacketBuilder::size() const { return builder_->size(); } - -void ErtmController::CopyablePacketBuilder::Serialize(BitInserter& it) const { - builder_->Serialize(it); -} - -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.h b/system/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.h deleted file mode 100644 index 4d9be3b213..0000000000 --- a/system/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <memory> -#include <unordered_map> -#include <utility> - -#include "common/bidi_queue.h" -#include "l2cap/cid.h" -#include "l2cap/internal/channel_impl.h" -#include "l2cap/internal/data_controller.h" -#include "l2cap/internal/scheduler.h" -#include "l2cap/l2cap_packets.h" -#include "l2cap/mtu.h" -#include "os/handler.h" -#include "os/queue.h" -#include "packet/base_packet_builder.h" -#include "packet/packet_view.h" -#include "packet/raw_builder.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { -class ILink; - -class ErtmController : public DataController { -public: - using UpperEnqueue = packet::PacketView<packet::kLittleEndian>; - using UpperDequeue = packet::BasePacketBuilder; - using UpperQueueDownEnd = common::BidiQueueEnd<UpperEnqueue, UpperDequeue>; - ErtmController(ILink* link, Cid cid, Cid remote_cid, UpperQueueDownEnd* channel_queue_end, - os::Handler* handler, Scheduler* scheduler); - ~ErtmController(); - // Segmentation is handled here - void OnSdu(std::unique_ptr<packet::BasePacketBuilder> sdu) override; - void OnPdu(packet::PacketView<true> pdu) override; - std::unique_ptr<packet::BasePacketBuilder> GetNextPacket() override; - void EnableFcs(bool enabled) override; - void SetRetransmissionAndFlowControlOptions( - const RetransmissionAndFlowControlConfigurationOption& option) override; - -private: - ILink* link_; - Cid cid_; - Cid remote_cid_; - os::EnqueueBuffer<UpperEnqueue> enqueue_buffer_; - os::Handler* handler_; - std::queue<std::unique_ptr<packet::BasePacketBuilder>> pdu_queue_; - Scheduler* scheduler_; - - // Configuration options - bool fcs_enabled_ = false; - uint16_t local_tx_window_ = 10; - uint16_t local_max_transmit_ = 20; - uint16_t local_retransmit_timeout_ms_ = 2000; - uint16_t local_monitor_timeout_ms_ = 12000; - - uint16_t remote_tx_window_ = 10; - uint16_t remote_mps_ = 1010; - - class PacketViewForReassembly : public packet::PacketView<kLittleEndian> { - public: - PacketViewForReassembly(const PacketView& packetView) : PacketView(packetView) {} - void AppendPacketView(packet::PacketView<kLittleEndian> to_append) { Append(to_append); } - }; - - class CopyablePacketBuilder : public packet::BasePacketBuilder { - public: - CopyablePacketBuilder(std::shared_ptr<packet::RawBuilder> builder) - : builder_(std::move(builder)) {} - - void Serialize(BitInserter& it) const override; - - size_t size() const override; - - private: - std::shared_ptr<packet::RawBuilder> builder_; - }; - - PacketViewForReassembly reassembly_stage_{ - PacketView<kLittleEndian>(std::make_shared<std::vector<uint8_t>>())}; - SegmentationAndReassembly sar_state_ = SegmentationAndReassembly::END; - uint16_t remaining_sdu_continuation_packet_size_ = 0; - - void stage_for_reassembly(SegmentationAndReassembly sar, uint16_t sdu_size, - const packet::PacketView<kLittleEndian>& payload); - void send_pdu(std::unique_ptr<packet::BasePacketBuilder> pdu); - - void close_channel(); - - void on_pdu_no_fcs(const packet::PacketView<true>& pdu); - void on_pdu_fcs(const packet::PacketView<true>& pdu); - - struct impl; - std::unique_ptr<impl> pimpl_; -}; - -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller_test.cc b/system/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller_test.cc deleted file mode 100644 index 10b6382309..0000000000 --- a/system/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller_test.cc +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/internal/enhanced_retransmission_mode_channel_data_controller.h" - -#include <gtest/gtest.h> - -#include "l2cap/internal/ilink_mock.h" -#include "l2cap/internal/scheduler_mock.h" -#include "l2cap/l2cap_packets.h" -#include "packet/raw_builder.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { -namespace { - -std::unique_ptr<packet::BasePacketBuilder> CreateSdu(std::vector<uint8_t> payload) { - auto raw_builder = std::make_unique<packet::RawBuilder>(); - raw_builder->AddOctets(payload); - return raw_builder; -} - -PacketView<kLittleEndian> GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet) { - auto bytes = std::make_shared<std::vector<uint8_t>>(); - BitInserter i(*bytes); - bytes->reserve(packet->size()); - packet->Serialize(i); - return packet::PacketView<packet::kLittleEndian>(bytes); -} - -void sync_handler(os::Handler* handler) { - std::promise<void> promise; - auto future = promise.get_future(); - handler->Post(common::BindOnce(&std::promise<void>::set_value, common::Unretained(&promise))); - auto status = future.wait_for(std::chrono::milliseconds(300)); - EXPECT_EQ(status, std::future_status::ready); -} - -class ErtmDataControllerTest : public ::testing::Test { -protected: - void SetUp() override { - thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL); - user_handler_ = new os::Handler(thread_); - queue_handler_ = new os::Handler(thread_); - } - - void TearDown() override { - queue_handler_->Clear(); - user_handler_->Clear(); - delete queue_handler_; - delete user_handler_; - delete thread_; - } - - os::Thread* thread_ = nullptr; - os::Handler* user_handler_ = nullptr; - os::Handler* queue_handler_ = nullptr; -}; - -TEST_F(ErtmDataControllerTest, transmit_no_fcs) { - common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10}; - testing::MockScheduler scheduler; - testing::MockILink link; - ErtmController controller{&link, 1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler}; - EXPECT_CALL(scheduler, OnPacketsReady(1, 1)); - controller.OnSdu(CreateSdu({'a', 'b', 'c', 'd'})); - auto next_packet = controller.GetNextPacket(); - EXPECT_NE(next_packet, nullptr); - auto view = GetPacketView(std::move(next_packet)); - auto pdu_view = BasicFrameView::Create(view); - EXPECT_TRUE(pdu_view.IsValid()); - auto standard_view = StandardFrameView::Create(pdu_view); - EXPECT_TRUE(standard_view.IsValid()); - auto i_frame_view = EnhancedInformationFrameView::Create(standard_view); - EXPECT_TRUE(i_frame_view.IsValid()); - auto payload = i_frame_view.GetPayload(); - std::string data = std::string(payload.begin(), payload.end()); - EXPECT_EQ(data, "abcd"); - EXPECT_EQ(i_frame_view.GetTxSeq(), 0); - EXPECT_EQ(i_frame_view.GetReqSeq(), 0); -} - -TEST_F(ErtmDataControllerTest, receive_no_fcs) { - common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10}; - testing::MockScheduler scheduler; - testing::MockILink link; - ErtmController controller{&link, 1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler}; - auto segment = CreateSdu({'a', 'b', 'c', 'd'}); - auto builder = EnhancedInformationFrameBuilder::Create( - 1, 0, Final::NOT_SET, 0, SegmentationAndReassembly::UNSEGMENTED, std::move(segment)); - auto base_view = GetPacketView(std::move(builder)); - controller.OnPdu(base_view); - sync_handler(queue_handler_); - auto payload = channel_queue.GetUpEnd()->TryDequeue(); - EXPECT_NE(payload, nullptr); - std::string data = std::string(payload->begin(), payload->end()); - EXPECT_EQ(data, "abcd"); -} - -TEST_F(ErtmDataControllerTest, reassemble_valid_sdu) { - common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10}; - testing::MockScheduler scheduler; - testing::MockILink link; - ErtmController controller{&link, 1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler}; - auto segment1 = CreateSdu({'a'}); - auto segment2 = CreateSdu({'b', 'c'}); - auto segment3 = CreateSdu({'d', 'e', 'f'}); - auto builder1 = EnhancedInformationStartFrameBuilder::Create(1, 0, Final::NOT_SET, 0, 6, - std::move(segment1)); - auto base_view = GetPacketView(std::move(builder1)); - controller.OnPdu(base_view); - auto builder2 = EnhancedInformationFrameBuilder::Create( - 1, 1, Final::NOT_SET, 0, SegmentationAndReassembly::CONTINUATION, std::move(segment2)); - base_view = GetPacketView(std::move(builder2)); - controller.OnPdu(base_view); - auto builder3 = EnhancedInformationFrameBuilder::Create( - 1, 2, Final::NOT_SET, 0, SegmentationAndReassembly::END, std::move(segment3)); - base_view = GetPacketView(std::move(builder3)); - controller.OnPdu(base_view); - sync_handler(queue_handler_); - auto payload = channel_queue.GetUpEnd()->TryDequeue(); - EXPECT_NE(payload, nullptr); - std::string data = std::string(payload->begin(), payload->end()); - EXPECT_EQ(data, "abcdef"); -} - -TEST_F(ErtmDataControllerTest, reassemble_invalid_sdu_size_in_start_frame_will_disconnect) { - common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10}; - testing::MockScheduler scheduler; - testing::MockILink link; - ErtmController controller{&link, 1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler}; - auto segment1 = CreateSdu({'a'}); - auto segment2 = CreateSdu({'b', 'c'}); - auto segment3 = CreateSdu({'d', 'e', 'f'}); - auto builder1 = EnhancedInformationStartFrameBuilder::Create(1, 0, Final::NOT_SET, 0, 10, - std::move(segment1)); - auto base_view = GetPacketView(std::move(builder1)); - controller.OnPdu(base_view); - auto builder2 = EnhancedInformationFrameBuilder::Create( - 1, 1, Final::NOT_SET, 0, SegmentationAndReassembly::CONTINUATION, std::move(segment2)); - base_view = GetPacketView(std::move(builder2)); - controller.OnPdu(base_view); - auto builder3 = EnhancedInformationFrameBuilder::Create( - 1, 2, Final::NOT_SET, 0, SegmentationAndReassembly::END, std::move(segment3)); - base_view = GetPacketView(std::move(builder3)); - EXPECT_CALL(link, SendDisconnectionRequest(1, 1)); - controller.OnPdu(base_view); - sync_handler(queue_handler_); - auto payload = channel_queue.GetUpEnd()->TryDequeue(); - EXPECT_EQ(payload, nullptr); -} - -TEST_F(ErtmDataControllerTest, transmit_with_fcs) { - common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10}; - testing::MockScheduler scheduler; - testing::MockILink link; - ErtmController controller{&link, 1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler}; - controller.EnableFcs(true); - EXPECT_CALL(scheduler, OnPacketsReady(1, 1)); - controller.OnSdu(CreateSdu({'a', 'b', 'c', 'd'})); - auto next_packet = controller.GetNextPacket(); - EXPECT_NE(next_packet, nullptr); - auto view = GetPacketView(std::move(next_packet)); - auto pdu_view = BasicFrameWithFcsView::Create(view); - EXPECT_TRUE(pdu_view.IsValid()); - auto standard_view = StandardFrameWithFcsView::Create(pdu_view); - EXPECT_TRUE(standard_view.IsValid()); - auto i_frame_view = EnhancedInformationFrameWithFcsView::Create(standard_view); - EXPECT_TRUE(i_frame_view.IsValid()); - auto payload = i_frame_view.GetPayload(); - std::string data = std::string(payload.begin(), payload.end()); - EXPECT_EQ(data, "abcd"); - EXPECT_EQ(i_frame_view.GetTxSeq(), 0); - EXPECT_EQ(i_frame_view.GetReqSeq(), 0); -} - -TEST_F(ErtmDataControllerTest, receive_packet_with_fcs) { - common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10}; - testing::MockScheduler scheduler; - testing::MockILink link; - ErtmController controller{&link, 1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler}; - controller.EnableFcs(true); - auto segment = CreateSdu({'a', 'b', 'c', 'd'}); - auto builder = EnhancedInformationFrameWithFcsBuilder::Create( - 1, 0, Final::NOT_SET, 0, SegmentationAndReassembly::UNSEGMENTED, std::move(segment)); - auto base_view = GetPacketView(std::move(builder)); - controller.OnPdu(base_view); - sync_handler(queue_handler_); - auto payload = channel_queue.GetUpEnd()->TryDequeue(); - EXPECT_NE(payload, nullptr); - std::string data = std::string(payload->begin(), payload->end()); - EXPECT_EQ(data, "abcd"); -} - -} // namespace -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/fixed_channel_allocator.h b/system/gd/l2cap/internal/fixed_channel_allocator.h deleted file mode 100644 index 52b859aaa6..0000000000 --- a/system/gd/l2cap/internal/fixed_channel_allocator.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <type_traits> -#include <unordered_map> - -#include "hci/hci_packets.h" -#include "l2cap/cid.h" -#include "os/handler.h" -#include "os/log.h" - -namespace bluetooth { -namespace l2cap { - -namespace classic { -namespace internal { -class DumpsysHelper; -} // namespace internal -} // namespace classic - -namespace internal { - -// Helper class for keeping channels in a Link. It allocates and frees Channel object, and supports -// querying whether a channel is in use -template <typename FixedChannelImplType, typename LinkType> -class FixedChannelAllocator { -public: - FixedChannelAllocator(LinkType* link, os::Handler* l2cap_handler) - : link_(link), l2cap_handler_(l2cap_handler) { - log::assert_that(link_ != nullptr, "assert failed: link_ != nullptr"); - log::assert_that(l2cap_handler_ != nullptr, "assert failed: l2cap_handler_ != nullptr"); - } - - virtual ~FixedChannelAllocator() = default; - - // Allocates a channel. If cid is used, return nullptr. NOTE: The returned BaseFixedChannelImpl - // object is still owned by the channel allocator, NOT the client. - virtual std::shared_ptr<FixedChannelImplType> AllocateChannel(Cid cid) { - log::assert_that(!IsChannelAllocated(cid), "Cid 0x{:x} for link {} is already in use", cid, - link_->ToRedactedStringForLogging()); - - log::assert_that(cid >= kFirstFixedChannel && cid <= kLastFixedChannel, "Cid {} out of bound", - cid); - auto elem = channels_.try_emplace( - cid, std::make_shared<FixedChannelImplType>(cid, link_, l2cap_handler_)); - log::assert_that(elem.second, "Failed to create channel for cid 0x{:x} link {}", cid, - link_->ToRedactedStringForLogging()); - log::assert_that(elem.first->second != nullptr, "assert failed: elem.first->second != nullptr"); - return elem.first->second; - } - - // Frees a channel. If cid doesn't exist, it will crash - virtual void FreeChannel(Cid cid) { - log::assert_that(IsChannelAllocated(cid), "Channel is not in use: cid {}, link {}", cid, - link_->ToRedactedStringForLogging()); - - channels_.erase(cid); - } - - virtual bool IsChannelAllocated(Cid cid) const { return channels_.find(cid) != channels_.end(); } - - virtual std::shared_ptr<FixedChannelImplType> FindChannel(Cid cid) { - log::assert_that(IsChannelAllocated(cid), "Channel is not in use: cid {}, link {}", cid, - link_->ToRedactedStringForLogging()); - - return channels_.find(cid)->second; - } - - virtual size_t NumberOfChannels() const { return channels_.size(); } - - virtual void OnAclDisconnected(hci::ErrorCode hci_status) { - for (auto& elem : channels_) { - elem.second->OnClosed(hci_status); - } - } - - virtual int GetRefCount() { - int ref_count = 0; - for (auto& elem : channels_) { - if (elem.second->IsAcquired()) { - ref_count++; - } - } - return ref_count; - } - -private: - friend class bluetooth::l2cap::classic::internal::DumpsysHelper; - LinkType* link_; - os::Handler* l2cap_handler_; - std::unordered_map<Cid, std::shared_ptr<FixedChannelImplType>> channels_; -}; - -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/fixed_channel_allocator_test.cc b/system/gd/l2cap/internal/fixed_channel_allocator_test.cc deleted file mode 100644 index 49416bf368..0000000000 --- a/system/gd/l2cap/internal/fixed_channel_allocator_test.cc +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/internal/fixed_channel_allocator.h" - -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include "l2cap/classic/internal/fixed_channel_impl_mock.h" -#include "l2cap/classic/internal/link_mock.h" -#include "l2cap/internal/parameter_provider_mock.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { - -using l2cap::classic::internal::testing::MockFixedChannelImpl; -using l2cap::classic::internal::testing::MockLink; -using testing::MockParameterProvider; -using ::testing::Return; - -const hci::AddressWithType device{{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::PUBLIC_IDENTITY_ADDRESS}; - -class L2capFixedChannelAllocatorTest : public ::testing::Test { -protected: - void SetUp() override { - thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL); - handler_ = new os::Handler(thread_); - mock_parameter_provider_ = new MockParameterProvider(); - mock_classic_link_ = new MockLink(handler_, mock_parameter_provider_); - EXPECT_CALL(*mock_classic_link_, GetDevice()).WillRepeatedly(Return(device)); - // Use classic as a place holder - channel_allocator_ = std::make_unique<FixedChannelAllocator<MockFixedChannelImpl, MockLink>>( - mock_classic_link_, handler_); - } - - void TearDown() override { - channel_allocator_.reset(); - delete mock_classic_link_; - delete mock_parameter_provider_; - handler_->Clear(); - delete handler_; - delete thread_; - } - - os::Thread* thread_{nullptr}; - os::Handler* handler_{nullptr}; - MockParameterProvider* mock_parameter_provider_{nullptr}; - MockLink* mock_classic_link_{nullptr}; - std::unique_ptr<FixedChannelAllocator<MockFixedChannelImpl, MockLink>> channel_allocator_; -}; - -TEST_F(L2capFixedChannelAllocatorTest, precondition) { - Cid cid = kFirstFixedChannel; - EXPECT_FALSE(channel_allocator_->IsChannelAllocated(cid)); -} - -TEST_F(L2capFixedChannelAllocatorTest, allocate_and_free_channel) { - Cid cid = kFirstFixedChannel; - auto channel = channel_allocator_->AllocateChannel(cid); - EXPECT_TRUE(channel_allocator_->IsChannelAllocated(cid)); - EXPECT_EQ(channel, channel_allocator_->FindChannel(cid)); - ASSERT_NO_FATAL_FAILURE(channel_allocator_->FreeChannel(cid)); - EXPECT_FALSE(channel_allocator_->IsChannelAllocated(cid)); -} - -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/ilink.h b/system/gd/l2cap/internal/ilink.h deleted file mode 100644 index 245847f70d..0000000000 --- a/system/gd/l2cap/internal/ilink.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include "hci/address_with_type.h" -#include "l2cap/cid.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { - -/** - * Common interface for link (Classic ACL and LE) - */ -class ILink { -public: - virtual ~ILink() = default; - virtual void SendDisconnectionRequest(Cid local_cid, Cid remote_cid) = 0; - virtual hci::AddressWithType GetDevice() const = 0; - - // Used by sender to indicate whether there is any pending packet to be sent. - // If there is pending packet, don't delete the link. - - virtual void OnPendingPacketChange(Cid /* local_cid */, bool /* has_packet */) {} - // To be used by LE credit based channel data controller over LE link - virtual void SendLeCredit(Cid /* local_cid */, uint16_t /* credit */) {} - - // Used by A2dp software encoding - virtual void SetChannelTxPriority(Cid /* local_cid */, bool /* high_priority */) {} -}; -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/ilink_mock.h b/system/gd/l2cap/internal/ilink_mock.h deleted file mode 100644 index 8343d17f18..0000000000 --- a/system/gd/l2cap/internal/ilink_mock.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <gmock/gmock.h> - -#include "l2cap/internal/ilink.h" - -// Unit test interfaces -namespace bluetooth { -namespace l2cap { -namespace internal { -namespace testing { - -class MockILink : public ILink { -public: - MOCK_METHOD(hci::AddressWithType, GetDevice, (), (const, override)); - MOCK_METHOD(void, SendDisconnectionRequest, (Cid, Cid), (override)); - MOCK_METHOD(void, SendLeCredit, (Cid, uint16_t), (override)); -}; - -} // namespace testing -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/le_credit_based_channel_data_controller.cc b/system/gd/l2cap/internal/le_credit_based_channel_data_controller.cc deleted file mode 100644 index d8f3cd03d2..0000000000 --- a/system/gd/l2cap/internal/le_credit_based_channel_data_controller.cc +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/internal/le_credit_based_channel_data_controller.h" - -#include <bluetooth/log.h> - -#include "l2cap/l2cap_packets.h" -#include "l2cap/le/internal/link.h" -#include "packet/fragmenting_inserter.h" -#include "packet/raw_builder.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { - -LeCreditBasedDataController::LeCreditBasedDataController(ILink* link, Cid cid, Cid remote_cid, - UpperQueueDownEnd* channel_queue_end, - os::Handler* handler, Scheduler* scheduler) - : cid_(cid), - remote_cid_(remote_cid), - enqueue_buffer_(channel_queue_end), - handler_(handler), - scheduler_(scheduler), - link_(link) {} - -void LeCreditBasedDataController::OnSdu(std::unique_ptr<packet::BasePacketBuilder> sdu) { - auto sdu_size = sdu->size(); - if (sdu_size == 0) { - log::warn("Received empty SDU"); - return; - } - if (sdu_size > mtu_) { - log::warn("Received sdu_size {} > mtu {}", static_cast<int>(sdu_size), mtu_); - } - std::vector<std::unique_ptr<packet::RawBuilder>> segments; - // TODO: We don't need to waste 2 bytes for continuation segment. - packet::FragmentingInserter fragmenting_inserter(mps_ - 2, std::back_insert_iterator(segments)); - sdu->Serialize(fragmenting_inserter); - fragmenting_inserter.finalize(); - std::unique_ptr<BasicFrameBuilder> builder; - builder = FirstLeInformationFrameBuilder::Create(remote_cid_, sdu_size, std::move(segments[0])); - pdu_queue_.emplace(std::move(builder)); - for (size_t i = 1; i < segments.size(); i++) { - builder = BasicFrameBuilder::Create(remote_cid_, std::move(segments[i])); - pdu_queue_.emplace(std::move(builder)); - } - if (credits_ >= segments.size()) { - scheduler_->OnPacketsReady(cid_, segments.size()); - credits_ -= segments.size(); - } else if (credits_ > 0) { - scheduler_->OnPacketsReady(cid_, credits_); - pending_frames_count_ += (segments.size() - credits_); - credits_ = 0; - } else { - pending_frames_count_ += segments.size(); - } -} - -void LeCreditBasedDataController::OnPdu(packet::PacketView<true> pdu) { - auto basic_frame_view = BasicFrameView::Create(pdu); - if (!basic_frame_view.IsValid()) { - log::warn("Received invalid frame"); - return; - } - if (basic_frame_view.size() > mps_) { - log::warn("Received frame size {} > mps {}, dropping the packet", - static_cast<int>(basic_frame_view.size()), mps_); - return; - } - if (remaining_sdu_continuation_packet_size_ == 0) { - auto start_frame_view = FirstLeInformationFrameView::Create(basic_frame_view); - if (!start_frame_view.IsValid()) { - log::warn("Received invalid frame"); - return; - } - auto payload = start_frame_view.GetPayload(); - auto sdu_size = start_frame_view.GetL2capSduLength(); - remaining_sdu_continuation_packet_size_ = sdu_size - payload.size(); - reassembly_stage_ = payload; - } else { - auto payload = basic_frame_view.GetPayload(); - remaining_sdu_continuation_packet_size_ -= payload.size(); - reassembly_stage_.AppendPacketView(payload); - } - if (remaining_sdu_continuation_packet_size_ == 0) { - enqueue_buffer_.Enqueue(std::make_unique<PacketView<kLittleEndian>>(reassembly_stage_), - handler_); - } else if (remaining_sdu_continuation_packet_size_ < 0 || reassembly_stage_.size() > mtu_) { - log::warn("Received larger SDU size than expected"); - reassembly_stage_ = PacketViewForReassembly( - PacketView<kLittleEndian>(std::make_shared<std::vector<uint8_t>>())); - remaining_sdu_continuation_packet_size_ = 0; - link_->SendDisconnectionRequest(cid_, remote_cid_); - } - // TODO: Improve the logic by sending credit only after user dequeued the SDU - link_->SendLeCredit(cid_, 1); -} - -std::unique_ptr<packet::BasePacketBuilder> LeCreditBasedDataController::GetNextPacket() { - log::assert_that(!pdu_queue_.empty(), "assert failed: !pdu_queue_.empty()"); - auto next = std::move(pdu_queue_.front()); - pdu_queue_.pop(); - return next; -} - -void LeCreditBasedDataController::SetMtu(Mtu mtu) { mtu_ = mtu; } - -void LeCreditBasedDataController::SetMps(uint16_t mps) { mps_ = mps; } - -void LeCreditBasedDataController::OnCredit(uint16_t credits) { - int total_credits = credits_ + credits; - if (total_credits > 0xffff) { - link_->SendDisconnectionRequest(cid_, remote_cid_); - } - credits_ = total_credits; - if (pending_frames_count_ > 0 && credits_ >= pending_frames_count_) { - scheduler_->OnPacketsReady(cid_, pending_frames_count_); - pending_frames_count_ = 0; - credits_ -= pending_frames_count_; - } else if (pending_frames_count_ > 0) { - scheduler_->OnPacketsReady(cid_, credits_); - pending_frames_count_ -= credits_; - credits_ = 0; - } -} - -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/le_credit_based_channel_data_controller.h b/system/gd/l2cap/internal/le_credit_based_channel_data_controller.h deleted file mode 100644 index aa10b0fb7d..0000000000 --- a/system/gd/l2cap/internal/le_credit_based_channel_data_controller.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <memory> -#include <unordered_map> -#include <utility> - -#include "common/bidi_queue.h" -#include "l2cap/cid.h" -#include "l2cap/internal/channel_impl.h" -#include "l2cap/internal/data_controller.h" -#include "l2cap/internal/ilink.h" -#include "l2cap/internal/scheduler.h" -#include "l2cap/l2cap_packets.h" -#include "l2cap/mtu.h" -#include "os/handler.h" -#include "os/queue.h" -#include "packet/base_packet_builder.h" -#include "packet/packet_view.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { - -class LeCreditBasedDataController : public DataController { -public: - using UpperEnqueue = packet::PacketView<packet::kLittleEndian>; - using UpperDequeue = packet::BasePacketBuilder; - using UpperQueueDownEnd = common::BidiQueueEnd<UpperEnqueue, UpperDequeue>; - LeCreditBasedDataController(ILink* link, Cid cid, Cid remote_cid, - UpperQueueDownEnd* channel_queue_end, os::Handler* handler, - Scheduler* scheduler); - - void OnSdu(std::unique_ptr<packet::BasePacketBuilder> sdu) override; - void OnPdu(packet::PacketView<true> pdu) override; - std::unique_ptr<packet::BasePacketBuilder> GetNextPacket() override; - - void EnableFcs(bool /* enabled */) override {} - void SetRetransmissionAndFlowControlOptions( - const RetransmissionAndFlowControlConfigurationOption& /* option */) override {} - - // TODO: Set MTU and MPS from signalling channel - void SetMtu(Mtu mtu); - void SetMps(uint16_t mps); - // TODO: Handle credits - void OnCredit(uint16_t credits); - -private: - Cid cid_; - Cid remote_cid_; - os::EnqueueBuffer<UpperEnqueue> enqueue_buffer_; - os::Handler* handler_; - std::queue<std::unique_ptr<packet::BasePacketBuilder>> pdu_queue_; - Scheduler* scheduler_; - ILink* link_; - Mtu mtu_ = 512; - uint16_t mps_ = 251; - uint16_t credits_ = 0; - uint16_t pending_frames_count_ = 0; - - class PacketViewForReassembly : public packet::PacketView<kLittleEndian> { - public: - PacketViewForReassembly(const PacketView& packetView) : PacketView(packetView) {} - void AppendPacketView(packet::PacketView<kLittleEndian> to_append) { Append(to_append); } - }; - PacketViewForReassembly reassembly_stage_{ - PacketView<kLittleEndian>(std::make_shared<std::vector<uint8_t>>())}; - uint16_t remaining_sdu_continuation_packet_size_ = 0; -}; - -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/le_credit_based_channel_data_controller_test.cc b/system/gd/l2cap/internal/le_credit_based_channel_data_controller_test.cc deleted file mode 100644 index b561fe3191..0000000000 --- a/system/gd/l2cap/internal/le_credit_based_channel_data_controller_test.cc +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/internal/le_credit_based_channel_data_controller.h" - -#include <gtest/gtest.h> - -#include "l2cap/internal/ilink_mock.h" -#include "l2cap/internal/scheduler_mock.h" -#include "l2cap/l2cap_packets.h" -#include "packet/raw_builder.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { -namespace { - -std::unique_ptr<packet::BasePacketBuilder> CreateSdu(std::vector<uint8_t> payload) { - return std::make_unique<packet::RawBuilder>(std::move(payload)); -} - -PacketView<kLittleEndian> GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet) { - auto bytes = std::make_shared<std::vector<uint8_t>>(); - BitInserter i(*bytes); - bytes->reserve(packet->size()); - packet->Serialize(i); - return packet::PacketView<packet::kLittleEndian>(bytes); -} - -void sync_handler(os::Handler* handler) { - std::promise<void> promise; - auto future = promise.get_future(); - handler->Post(common::BindOnce(&std::promise<void>::set_value, common::Unretained(&promise))); - auto status = future.wait_for(std::chrono::milliseconds(300)); - EXPECT_EQ(status, std::future_status::ready); -} - -class LeCreditBasedDataControllerTest : public ::testing::Test { -protected: - void SetUp() override { - thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL); - user_handler_ = new os::Handler(thread_); - queue_handler_ = new os::Handler(thread_); - } - - void TearDown() override { - queue_handler_->Clear(); - user_handler_->Clear(); - delete queue_handler_; - delete user_handler_; - delete thread_; - } - - os::Thread* thread_ = nullptr; - os::Handler* user_handler_ = nullptr; - os::Handler* queue_handler_ = nullptr; -}; - -TEST_F(LeCreditBasedDataControllerTest, transmit_unsegmented) { - common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10}; - testing::MockScheduler scheduler; - testing::MockILink link; - LeCreditBasedDataController controller{ - &link, 0x41, 0x41, channel_queue.GetDownEnd(), queue_handler_, &scheduler}; - controller.OnCredit(10); - EXPECT_CALL(scheduler, OnPacketsReady(0x41, 1)); - controller.OnSdu(CreateSdu({'a', 'b', 'c', 'd'})); - auto next_packet = controller.GetNextPacket(); - EXPECT_NE(next_packet, nullptr); - auto view = GetPacketView(std::move(next_packet)); - auto pdu_view = BasicFrameView::Create(view); - EXPECT_TRUE(pdu_view.IsValid()); - auto first_le_info_view = FirstLeInformationFrameView::Create(pdu_view); - EXPECT_TRUE(first_le_info_view.IsValid()); - auto payload = first_le_info_view.GetPayload(); - std::string data = std::string(payload.begin(), payload.end()); - EXPECT_EQ(data, "abcd"); -} - -TEST_F(LeCreditBasedDataControllerTest, transmit_segmented) { - common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10}; - testing::MockScheduler scheduler; - testing::MockILink link; - LeCreditBasedDataController controller{ - &link, 0x41, 0x41, channel_queue.GetDownEnd(), queue_handler_, &scheduler}; - controller.OnCredit(10); - controller.SetMps(4); - EXPECT_CALL(scheduler, OnPacketsReady(0x41, 2)); - // Should be divided into 'ab', and 'cd' - controller.OnSdu(CreateSdu({'a', 'b', 'c', 'd'})); - auto next_packet = controller.GetNextPacket(); - EXPECT_NE(next_packet, nullptr); - auto view = GetPacketView(std::move(next_packet)); - auto pdu_view = BasicFrameView::Create(view); - EXPECT_TRUE(pdu_view.IsValid()); - auto first_le_info_view = FirstLeInformationFrameView::Create(pdu_view); - EXPECT_TRUE(first_le_info_view.IsValid()); - auto payload = first_le_info_view.GetPayload(); - std::string data = std::string(payload.begin(), payload.end()); - EXPECT_EQ(data, "ab"); - EXPECT_EQ(first_le_info_view.GetL2capSduLength(), 4); - - next_packet = controller.GetNextPacket(); - EXPECT_NE(next_packet, nullptr); - view = GetPacketView(std::move(next_packet)); - pdu_view = BasicFrameView::Create(view); - EXPECT_TRUE(pdu_view.IsValid()); - payload = pdu_view.GetPayload(); - data = std::string(payload.begin(), payload.end()); - EXPECT_EQ(data, "cd"); -} - -TEST_F(LeCreditBasedDataControllerTest, receive_unsegmented) { - common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10}; - testing::MockScheduler scheduler; - testing::MockILink link; - LeCreditBasedDataController controller{ - &link, 0x41, 0x41, channel_queue.GetDownEnd(), queue_handler_, &scheduler}; - controller.OnCredit(10); - auto segment = CreateSdu({'a', 'b', 'c', 'd'}); - auto builder = FirstLeInformationFrameBuilder::Create(0x41, 4, std::move(segment)); - auto base_view = GetPacketView(std::move(builder)); - controller.OnPdu(base_view); - sync_handler(queue_handler_); - auto payload = channel_queue.GetUpEnd()->TryDequeue(); - EXPECT_NE(payload, nullptr); - std::string data = std::string(payload->begin(), payload->end()); - EXPECT_EQ(data, "abcd"); -} - -TEST_F(LeCreditBasedDataControllerTest, receive_segmented) { - common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10}; - testing::MockScheduler scheduler; - testing::MockILink link; - LeCreditBasedDataController controller{ - &link, 0x41, 0x41, channel_queue.GetDownEnd(), queue_handler_, &scheduler}; - controller.OnCredit(10); - auto segment1 = CreateSdu({'a', 'b', 'c', 'd'}); - auto builder1 = FirstLeInformationFrameBuilder::Create(0x41, 7, std::move(segment1)); - auto base_view = GetPacketView(std::move(builder1)); - controller.OnPdu(base_view); - auto segment2 = CreateSdu({'e', 'f', 'g'}); - auto builder2 = BasicFrameBuilder::Create(0x41, std::move(segment2)); - base_view = GetPacketView(std::move(builder2)); - EXPECT_CALL(link, SendLeCredit(0x41, 1)); - controller.OnPdu(base_view); - sync_handler(queue_handler_); - auto payload = channel_queue.GetUpEnd()->TryDequeue(); - EXPECT_NE(payload, nullptr); - std::string data = std::string(payload->begin(), payload->end()); - EXPECT_EQ(data, "abcdefg"); -} - -TEST_F(LeCreditBasedDataControllerTest, receive_segmented_with_wrong_sdu_length) { - common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10}; - testing::MockScheduler scheduler; - testing::MockILink link; - LeCreditBasedDataController controller{ - &link, 0x41, 0x41, channel_queue.GetDownEnd(), queue_handler_, &scheduler}; - controller.OnCredit(10); - auto segment1 = CreateSdu({'a', 'b', 'c', 'd'}); - auto builder1 = FirstLeInformationFrameBuilder::Create(0x41, 5, std::move(segment1)); - auto base_view = GetPacketView(std::move(builder1)); - controller.OnPdu(base_view); - auto segment2 = CreateSdu({'e', 'f', 'g'}); - auto builder2 = BasicFrameBuilder::Create(0x41, std::move(segment2)); - base_view = GetPacketView(std::move(builder2)); - controller.OnPdu(base_view); - sync_handler(queue_handler_); - auto payload = channel_queue.GetUpEnd()->TryDequeue(); - EXPECT_EQ(payload, nullptr); -} - -} // namespace -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/parameter_provider.h b/system/gd/l2cap/internal/parameter_provider.h deleted file mode 100644 index bb9cb37f7a..0000000000 --- a/system/gd/l2cap/internal/parameter_provider.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <chrono> - -namespace bluetooth { -namespace l2cap { -namespace internal { - -/** - * A class that provide constant parameters to the L2CAP stack - * - * All methods are virtual so that they can be override in unit tests - */ -class ParameterProvider { -public: - virtual ~ParameterProvider() = default; - virtual std::chrono::milliseconds GetClassicLinkIdleDisconnectTimeout() { - return std::chrono::seconds(20); - } - virtual std::chrono::milliseconds GetLeLinkIdleDisconnectTimeout() { - return std::chrono::seconds(1); - } - virtual uint16_t GetLeMps() { return 251; } - virtual uint16_t GetLeInitialCredit() { return 100; } -}; - -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/parameter_provider_mock.h b/system/gd/l2cap/internal/parameter_provider_mock.h deleted file mode 100644 index 218464c740..0000000000 --- a/system/gd/l2cap/internal/parameter_provider_mock.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2019 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. - */ -#pragma once - -#include <gmock/gmock.h> - -#include "l2cap/internal/parameter_provider.h" - -// Unit test interfaces -namespace bluetooth { -namespace l2cap { -namespace internal { -namespace testing { - -class MockParameterProvider : public ParameterProvider { -public: - MOCK_METHOD(std::chrono::milliseconds, GetClassicLinkIdleDisconnectTimeout, (), (override)); - MOCK_METHOD(std::chrono::milliseconds, GetLeLinkIdleDisconnectTimeout, (), (override)); -}; - -} // namespace testing -} // namespace internal -} // namespace l2cap -} // namespace bluetooth
\ No newline at end of file diff --git a/system/gd/l2cap/internal/receiver.cc b/system/gd/l2cap/internal/receiver.cc deleted file mode 100644 index db5bc7b208..0000000000 --- a/system/gd/l2cap/internal/receiver.cc +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/internal/receiver.h" - -#include <bluetooth/log.h> - -#include "common/bidi_queue.h" -#include "l2cap/cid.h" -#include "l2cap/internal/data_pipeline_manager.h" -#include "l2cap/l2cap_packets.h" -#include "packet/packet_view.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { -Receiver::Receiver(LowerQueueUpEnd* link_queue_up_end, os::Handler* handler, - DataPipelineManager* data_pipeline_manager_) - : link_queue_up_end_(link_queue_up_end), - handler_(handler), - buffer_timer_(handler), - data_pipeline_manager_(data_pipeline_manager_) { - log::assert_that(link_queue_up_end_ != nullptr && handler_ != nullptr, - "assert failed: link_queue_up_end_ != nullptr && handler_ != nullptr"); - link_queue_up_end_->RegisterDequeue( - handler_, common::Bind(&Receiver::link_queue_dequeue_callback, common::Unretained(this))); -} - -// Invoked from external handler/thread (ModuleRegistry) -Receiver::~Receiver() { link_queue_up_end_->UnregisterDequeue(); } - -// Invoked from external (Queue Reactable) -void Receiver::link_queue_dequeue_callback() { - auto packet = link_queue_up_end_->TryDequeue(); - auto basic_frame_view = BasicFrameView::Create(*packet); - if (!basic_frame_view.IsValid()) { - log::warn("Received an invalid basic frame"); - return; - } - Cid cid = static_cast<Cid>(basic_frame_view.GetChannelId()); - auto* data_controller = data_pipeline_manager_->GetDataController(cid); - if (data_controller == nullptr) { - // TODO(b/150170271): Buffer a few packets before data controller is attached - log::warn("Received a packet without data controller. cid: {}", cid); - buffered_packets_.emplace(*packet); - log::warn("Enqueued the unexpected packet. Current queue size: {}", buffered_packets_.size()); - buffer_timer_.Schedule( - common::BindOnce(&Receiver::check_buffered_packets, common::Unretained(this)), - std::chrono::milliseconds(500)); - - return; - } - data_controller->OnPdu(*packet); -} - -void Receiver::check_buffered_packets() { - while (!buffered_packets_.empty()) { - auto packet = buffered_packets_.front(); - buffered_packets_.pop(); - auto basic_frame_view = BasicFrameView::Create(packet); - if (!basic_frame_view.IsValid()) { - log::warn("Received an invalid basic frame"); - return; - } - Cid cid = static_cast<Cid>(basic_frame_view.GetChannelId()); - auto* data_controller = data_pipeline_manager_->GetDataController(cid); - if (data_controller == nullptr) { - log::error("Dropping a packet with invalid cid: {}", cid); - } else { - data_controller->OnPdu(packet); - } - } -} - -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/receiver.h b/system/gd/l2cap/internal/receiver.h deleted file mode 100644 index 45681d21d0..0000000000 --- a/system/gd/l2cap/internal/receiver.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <memory> -#include <queue> -#include <unordered_map> -#include <utility> - -#include "common/bidi_queue.h" -#include "l2cap/cid.h" -#include "l2cap/internal/channel_impl.h" -#include "l2cap/internal/scheduler.h" -#include "l2cap/l2cap_packets.h" -#include "l2cap/mtu.h" -#include "os/alarm.h" -#include "os/queue.h" -#include "packet/base_packet_builder.h" -#include "packet/packet_view.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { - -class DataPipelineManager; - -/** - * Handle receiving L2CAP PDUs from link queue and distribute them into into channel data - * controllers. Dequeue incoming packets from LinkQueueUpEnd, and enqueue it to ChannelQueueDownEnd. - * Note: If a channel cannot dequeue from ChannelQueueDownEnd so that the buffer for incoming packet - * is full, further incoming packets will be dropped. The Reassembler keeps the reference to - * ChannelImpl objects, because it needs to check channel mode and parameters. The Reassembler also - * keeps the reference to Scheduler, to get Segmenter and send signals (Tx, Rx seq) to it. - */ -class Receiver { -public: - using UpperEnqueue = packet::PacketView<packet::kLittleEndian>; - using UpperDequeue = packet::BasePacketBuilder; - using UpperQueueDownEnd = common::BidiQueueEnd<UpperEnqueue, UpperDequeue>; - using LowerEnqueue = UpperDequeue; - using LowerDequeue = UpperEnqueue; - using LowerQueueUpEnd = common::BidiQueueEnd<LowerEnqueue, LowerDequeue>; - - Receiver(LowerQueueUpEnd* link_queue_up_end, os::Handler* handler, - DataPipelineManager* data_pipeline_manager); - ~Receiver(); - -private: - LowerQueueUpEnd* link_queue_up_end_; - os::Handler* handler_; - os::Alarm buffer_timer_; - std::queue<LowerDequeue> buffered_packets_; - DataPipelineManager* data_pipeline_manager_; - - void link_queue_dequeue_callback(); - void check_buffered_packets(); -}; - -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/scheduler.h b/system/gd/l2cap/internal/scheduler.h deleted file mode 100644 index 56586216be..0000000000 --- a/system/gd/l2cap/internal/scheduler.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <cstdint> - -#include "common/bidi_queue.h" -#include "l2cap/cid.h" -#include "l2cap/classic/dynamic_channel_configuration_option.h" -#include "l2cap/internal/channel_impl.h" -#include "l2cap/internal/data_controller.h" -#include "l2cap/internal/sender.h" -#include "l2cap/l2cap_packets.h" -#include "packet/base_packet_builder.h" -#include "packet/packet_view.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { - -/** - * Handle the scheduling of packets through the l2cap stack. - * For each attached channel, dequeue its outgoing packets and enqueue it to the - * given LinkQueueUpEnd, according to some policy (cid). - * - * Note: If a channel cannot dequeue from ChannelQueueDownEnd so that the buffer - * for incoming packet is full, further incoming packets will be dropped. - */ -class Scheduler { -public: - using UpperEnqueue = packet::PacketView<packet::kLittleEndian>; - using UpperDequeue = packet::BasePacketBuilder; - using UpperQueueDownEnd = common::BidiQueueEnd<UpperEnqueue, UpperDequeue>; - using LowerEnqueue = UpperDequeue; - using LowerDequeue = UpperEnqueue; - using LowerQueueUpEnd = common::BidiQueueEnd<LowerEnqueue, LowerDequeue>; - - /** - * Callback from the sender to indicate that the scheduler could dequeue - * number_packets from it - */ - virtual void OnPacketsReady(Cid /* cid */, int /* number_packets */) {} - - /** - * Let the scheduler send the specified cid first. - * Used by A2dp software encoding. - */ - virtual void SetChannelTxPriority(Cid /* cid */, bool /* high_priority */) {} - - /** - * Called by data controller to indicate that a channel is closed and packets - * should be dropped - */ - virtual void RemoveChannel(Cid /* cid */) {} - - virtual ~Scheduler() = default; -}; - -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/scheduler_fifo.cc b/system/gd/l2cap/internal/scheduler_fifo.cc deleted file mode 100644 index 732799bd9b..0000000000 --- a/system/gd/l2cap/internal/scheduler_fifo.cc +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/internal/scheduler_fifo.h" - -#include "dynamic_channel_impl.h" -#include "l2cap/internal/data_pipeline_manager.h" -#include "l2cap/l2cap_packets.h" -#include "os/log.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { - -Fifo::Fifo(DataPipelineManager* data_pipeline_manager, LowerQueueUpEnd* link_queue_up_end, - os::Handler* handler) - : data_pipeline_manager_(data_pipeline_manager), - link_queue_up_end_(link_queue_up_end), - handler_(handler) { - log::assert_that(link_queue_up_end_ != nullptr && handler_ != nullptr, - "assert failed: link_queue_up_end_ != nullptr && handler_ != nullptr"); -} - -// Invoked from some external Handler context -Fifo::~Fifo() { - // TODO(hsz): notify Sender don't send callback to me - if (link_queue_enqueue_registered_.exchange(false)) { - link_queue_up_end_->UnregisterEnqueue(); - } -} - -// Invoked within L2CAP Handler context -void Fifo::OnPacketsReady(Cid cid, int number_packets) { - if (number_packets == 0) { - return; - } - int priority = high_priority_cids_.count(cid) != 0; - next_to_dequeue_and_num_packets.push(std::make_pair(cid, number_packets), priority); - try_register_link_queue_enqueue(); -} - -// Invoked within L2CAP Handler context -void Fifo::SetChannelTxPriority(Cid cid, bool high_priority) { - if (high_priority) { - high_priority_cids_.emplace(cid); - } else { - high_priority_cids_.erase(cid); - } -} - -void Fifo::RemoveChannel(Cid cid) { - for (size_t i = 0; i < next_to_dequeue_and_num_packets.size(); i++) { - auto& channel_id_and_number_packets = next_to_dequeue_and_num_packets.front(); - if (channel_id_and_number_packets.second != cid) { - next_to_dequeue_and_num_packets.push(channel_id_and_number_packets); - } - next_to_dequeue_and_num_packets.pop(); - } - if (next_to_dequeue_and_num_packets.empty() && link_queue_enqueue_registered_.exchange(false)) { - link_queue_up_end_->UnregisterEnqueue(); - } -} - -// Invoked from some external Queue Reactable context -std::unique_ptr<Fifo::UpperDequeue> Fifo::link_queue_enqueue_callback() { - log::assert_that(!next_to_dequeue_and_num_packets.empty(), - "assert failed: !next_to_dequeue_and_num_packets.empty()"); - auto& channel_id_and_number_packets = next_to_dequeue_and_num_packets.front(); - auto channel_id = channel_id_and_number_packets.first; - channel_id_and_number_packets.second--; - if (channel_id_and_number_packets.second == 0) { - next_to_dequeue_and_num_packets.pop(); - } - auto packet = data_pipeline_manager_->GetDataController(channel_id)->GetNextPacket(); - - data_pipeline_manager_->OnPacketSent(channel_id); - if (next_to_dequeue_and_num_packets.empty() && link_queue_enqueue_registered_.exchange(false)) { - link_queue_up_end_->UnregisterEnqueue(); - } - return packet; -} - -void Fifo::try_register_link_queue_enqueue() { - if (link_queue_enqueue_registered_.exchange(true)) { - return; - } - link_queue_up_end_->RegisterEnqueue( - handler_, common::Bind(&Fifo::link_queue_enqueue_callback, common::Unretained(this))); -} - -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/scheduler_fifo.h b/system/gd/l2cap/internal/scheduler_fifo.h deleted file mode 100644 index dec737e1e2..0000000000 --- a/system/gd/l2cap/internal/scheduler_fifo.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <atomic> -#include <string> -#include <unordered_map> -#include <unordered_set> - -#include "common/bidi_queue.h" -#include "common/bind.h" -#include "common/multi_priority_queue.h" -#include "l2cap/cid.h" -#include "l2cap/internal/channel_impl.h" -#include "l2cap/internal/scheduler.h" -#include "l2cap/internal/sender.h" -#include "os/handler.h" -#include "os/queue.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { -class DataPipelineManager; - -class Fifo : public Scheduler { -public: - Fifo(DataPipelineManager* data_pipeline_manager, LowerQueueUpEnd* link_queue_up_end, - os::Handler* handler); - ~Fifo(); - void OnPacketsReady(Cid cid, int number_packets) override; - void SetChannelTxPriority(Cid cid, bool high_priority) override; - void RemoveChannel(Cid cid) override; - -private: - DataPipelineManager* data_pipeline_manager_; - LowerQueueUpEnd* link_queue_up_end_; - os::Handler* handler_; - using ChannelAndNumPackets = std::pair<Cid, int>; - common::MultiPriorityQueue<ChannelAndNumPackets, 2> next_to_dequeue_and_num_packets; - std::unordered_set<Cid> high_priority_cids_; - std::atomic_bool link_queue_enqueue_registered_ = false; - - void try_register_link_queue_enqueue(); - std::unique_ptr<LowerEnqueue> link_queue_enqueue_callback(); -}; - -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/scheduler_fifo_test.cc b/system/gd/l2cap/internal/scheduler_fifo_test.cc deleted file mode 100644 index a7a430cb18..0000000000 --- a/system/gd/l2cap/internal/scheduler_fifo_test.cc +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/internal/scheduler_fifo.h" - -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include "l2cap/internal/channel_impl_mock.h" -#include "l2cap/internal/data_controller_mock.h" -#include "l2cap/internal/data_pipeline_manager_mock.h" -#include "os/handler.h" -#include "os/mock_queue.h" -#include "os/thread.h" -#include "packet/raw_builder.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { -namespace { - -using ::testing::_; -using ::testing::Return; - -std::unique_ptr<packet::BasePacketBuilder> CreateSdu(std::vector<uint8_t> payload) { - auto raw_builder = std::make_unique<packet::RawBuilder>(); - raw_builder->AddOctets(payload); - return raw_builder; -} - -PacketView<kLittleEndian> GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet) { - auto bytes = std::make_shared<std::vector<uint8_t>>(); - BitInserter i(*bytes); - bytes->reserve(packet->size()); - packet->Serialize(i); - return packet::PacketView<packet::kLittleEndian>(bytes); -} - -class MyDataController : public testing::MockDataController { -public: - std::unique_ptr<BasePacketBuilder> GetNextPacket() override { - auto next = std::move(next_packets.front()); - next_packets.pop(); - return next; - } - - std::queue<std::unique_ptr<BasePacketBuilder>> next_packets; -}; - -class L2capSchedulerFifoTest : public ::testing::Test { -protected: - void SetUp() override { - thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL); - queue_handler_ = new os::Handler(thread_); - mock_data_pipeline_manager_ = new testing::MockDataPipelineManager(queue_handler_, &queue_end_); - fifo_ = new Fifo(mock_data_pipeline_manager_, &queue_end_, queue_handler_); - } - - void TearDown() override { - delete fifo_; - delete mock_data_pipeline_manager_; - queue_handler_->Clear(); - delete queue_handler_; - delete thread_; - } - - os::Thread* thread_ = nullptr; - os::Handler* queue_handler_ = nullptr; - os::MockIQueueDequeue<Scheduler::LowerDequeue> dequeue_; - os::MockIQueueEnqueue<Scheduler::LowerEnqueue> enqueue_; - common::BidiQueueEnd<Scheduler::LowerEnqueue, Scheduler::LowerDequeue> queue_end_{&enqueue_, - &dequeue_}; - testing::MockDataPipelineManager* mock_data_pipeline_manager_ = nullptr; - MyDataController data_controller_1_; - MyDataController data_controller_2_; - Fifo* fifo_ = nullptr; -}; - -TEST_F(L2capSchedulerFifoTest, send_packet) { - auto frame = BasicFrameBuilder::Create(1, CreateSdu({'a', 'b', 'c'})); - data_controller_1_.next_packets.push(std::move(frame)); - EXPECT_CALL(*mock_data_pipeline_manager_, GetDataController(_)) - .WillOnce(Return(&data_controller_1_)); - EXPECT_CALL(*mock_data_pipeline_manager_, OnPacketSent(1)); - fifo_->OnPacketsReady(1, 1); - enqueue_.run_enqueue(); - auto&& packet = enqueue_.enqueued.front(); - auto packet_view = GetPacketView(std::move(packet)); - auto basic_frame_view = BasicFrameView::Create(packet_view); - ASSERT_TRUE(basic_frame_view.IsValid()); - ASSERT_EQ(basic_frame_view.GetChannelId(), 1); - auto payload = basic_frame_view.GetPayload(); - ASSERT_EQ(std::string(payload.begin(), payload.end()), "abc"); - enqueue_.enqueued.pop(); -} - -TEST_F(L2capSchedulerFifoTest, prioritize_channel) { - auto frame = BasicFrameBuilder::Create(1, CreateSdu({'a', 'b', 'c'})); - data_controller_1_.next_packets.push(std::move(frame)); - frame = BasicFrameBuilder::Create(2, CreateSdu({'d', 'e', 'f'})); - data_controller_2_.next_packets.push(std::move(frame)); - - EXPECT_CALL(*mock_data_pipeline_manager_, GetDataController(1)) - .WillRepeatedly(Return(&data_controller_1_)); - EXPECT_CALL(*mock_data_pipeline_manager_, GetDataController(2)) - .WillRepeatedly(Return(&data_controller_2_)); - EXPECT_CALL(*mock_data_pipeline_manager_, OnPacketSent(1)); - EXPECT_CALL(*mock_data_pipeline_manager_, OnPacketSent(2)); - fifo_->SetChannelTxPriority(1, true); - fifo_->OnPacketsReady(2, 1); - fifo_->OnPacketsReady(1, 1); - enqueue_.run_enqueue(2); - auto packet1 = std::move(enqueue_.enqueued.front()); - auto packet_view = GetPacketView(std::move(packet1)); - auto basic_frame_view = BasicFrameView::Create(packet_view); - ASSERT_TRUE(basic_frame_view.IsValid()); - ASSERT_EQ(basic_frame_view.GetChannelId(), 1); - auto payload = basic_frame_view.GetPayload(); - ASSERT_EQ(std::string(payload.begin(), payload.end()), "abc"); - enqueue_.enqueued.pop(); - - auto packet2 = std::move(enqueue_.enqueued.front()); - packet_view = GetPacketView(std::move(packet2)); - basic_frame_view = BasicFrameView::Create(packet_view); - ASSERT_TRUE(basic_frame_view.IsValid()); - ASSERT_EQ(basic_frame_view.GetChannelId(), 2); - payload = basic_frame_view.GetPayload(); - ASSERT_EQ(std::string(payload.begin(), payload.end()), "def"); - enqueue_.enqueued.pop(); -} - -TEST_F(L2capSchedulerFifoTest, remove_channel) { - auto frame = BasicFrameBuilder::Create(1, CreateSdu({'a', 'b', 'c'})); - data_controller_1_.next_packets.push(std::move(frame)); - frame = BasicFrameBuilder::Create(2, CreateSdu({'d', 'e', 'f'})); - data_controller_2_.next_packets.push(std::move(frame)); - - EXPECT_CALL(*mock_data_pipeline_manager_, GetDataController(1)) - .WillRepeatedly(Return(&data_controller_1_)); - EXPECT_CALL(*mock_data_pipeline_manager_, GetDataController(2)) - .WillRepeatedly(Return(&data_controller_2_)); - EXPECT_CALL(*mock_data_pipeline_manager_, OnPacketSent(2)); - fifo_->OnPacketsReady(1, 1); - fifo_->OnPacketsReady(2, 1); - fifo_->RemoveChannel(1); - enqueue_.run_enqueue(1); - auto packet1 = std::move(enqueue_.enqueued.front()); - auto packet_view = GetPacketView(std::move(packet1)); - auto basic_frame_view = BasicFrameView::Create(packet_view); - ASSERT_TRUE(basic_frame_view.IsValid()); - ASSERT_EQ(basic_frame_view.GetChannelId(), 2); - auto payload = basic_frame_view.GetPayload(); - ASSERT_EQ(std::string(payload.begin(), payload.end()), "def"); - enqueue_.enqueued.pop(); -} - -} // namespace -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/scheduler_mock.h b/system/gd/l2cap/internal/scheduler_mock.h deleted file mode 100644 index 0ec527b741..0000000000 --- a/system/gd/l2cap/internal/scheduler_mock.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2019 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. - */ -#pragma once - -#include <gmock/gmock.h> - -#include "l2cap/internal/channel_impl.h" -#include "l2cap/internal/scheduler.h" - -// Unit test interfaces -namespace bluetooth { -namespace l2cap { -namespace internal { -namespace testing { - -class MockScheduler : public Scheduler { -public: - MOCK_METHOD(void, OnPacketsReady, (Cid cid, int number_packet), (override)); -}; - -} // namespace testing -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/sender.cc b/system/gd/l2cap/internal/sender.cc deleted file mode 100644 index c03a30b2c2..0000000000 --- a/system/gd/l2cap/internal/sender.cc +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/internal/sender.h" - -#include <unordered_map> - -#include "common/bind.h" -#include "l2cap/internal/basic_mode_channel_data_controller.h" -#include "l2cap/internal/enhanced_retransmission_mode_channel_data_controller.h" -#include "l2cap/internal/le_credit_based_channel_data_controller.h" -#include "l2cap/internal/scheduler.h" -#include "os/handler.h" -#include "os/log.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { - -Sender::Sender(os::Handler* handler, ILink* link, Scheduler* scheduler, - std::shared_ptr<ChannelImpl> channel) - : handler_(handler), - link_(link), - queue_end_(channel->GetQueueDownEnd()), - scheduler_(scheduler), - channel_id_(channel->GetCid()), - remote_channel_id_(channel->GetRemoteCid()), - data_controller_(std::make_unique<BasicModeDataController>( - channel_id_, remote_channel_id_, queue_end_, handler_, scheduler_)) { - try_register_dequeue(); -} - -Sender::Sender(os::Handler* handler, ILink* link, Scheduler* scheduler, - std::shared_ptr<ChannelImpl> channel, ChannelMode mode) - : handler_(handler), - link_(link), - queue_end_(channel->GetQueueDownEnd()), - scheduler_(scheduler), - channel_id_(channel->GetCid()), - remote_channel_id_(channel->GetRemoteCid()) { - if (mode == ChannelMode::BASIC) { - data_controller_ = std::make_unique<BasicModeDataController>(channel_id_, remote_channel_id_, - queue_end_, handler_, scheduler_); - } else if (mode == ChannelMode::ERTM) { - data_controller_ = std::make_unique<ErtmController>(link_, channel_id_, remote_channel_id_, - queue_end_, handler_, scheduler_); - } else if (mode == ChannelMode::LE_CREDIT_BASED) { - data_controller_ = std::make_unique<LeCreditBasedDataController>( - link_, channel_id_, remote_channel_id_, queue_end_, handler_, scheduler_); - } - try_register_dequeue(); -} - -Sender::~Sender() { - if (is_dequeue_registered_.exchange(false)) { - queue_end_->UnregisterDequeue(); - } -} - -void Sender::OnPacketSent() { - link_->OnPendingPacketChange(channel_id_, false); - try_register_dequeue(); -} - -std::unique_ptr<Sender::UpperDequeue> Sender::GetNextPacket() { - return data_controller_->GetNextPacket(); -} - -DataController* Sender::GetDataController() { return data_controller_.get(); } - -void Sender::try_register_dequeue() { - if (is_dequeue_registered_.exchange(true)) { - return; - } - queue_end_->RegisterDequeue(handler_, - common::Bind(&Sender::dequeue_callback, common::Unretained(this))); -} - -// From external context -void Sender::dequeue_callback() { - auto packet = queue_end_->TryDequeue(); - log::assert_that(packet != nullptr, "assert failed: packet != nullptr"); - handler_->Post(common::BindOnce(&DataController::OnSdu, - common::Unretained(data_controller_.get()), std::move(packet))); - if (is_dequeue_registered_.exchange(false)) { - queue_end_->UnregisterDequeue(); - } - link_->OnPendingPacketChange(channel_id_, true); -} - -void Sender::UpdateClassicConfiguration(classic::internal::ChannelConfigurationState config) { - auto mode = config.retransmission_and_flow_control_mode_; - if (mode == mode_) { - return; - } - if (mode == RetransmissionAndFlowControlModeOption::L2CAP_BASIC) { - data_controller_ = std::make_unique<BasicModeDataController>(channel_id_, remote_channel_id_, - queue_end_, handler_, scheduler_); - return; - } - if (mode == RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION) { - data_controller_ = std::make_unique<ErtmController>(link_, channel_id_, remote_channel_id_, - queue_end_, handler_, scheduler_); - RetransmissionAndFlowControlConfigurationOption option = - config.local_retransmission_and_flow_control_; - option.tx_window_size_ = config.remote_retransmission_and_flow_control_.tx_window_size_; - data_controller_->SetRetransmissionAndFlowControlOptions(option); - data_controller_->EnableFcs(config.fcs_type_ == FcsType::DEFAULT); - return; - } -} - -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/sender.h b/system/gd/l2cap/internal/sender.h deleted file mode 100644 index 5e39d228c1..0000000000 --- a/system/gd/l2cap/internal/sender.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <atomic> -#include <string> -#include <unordered_map> - -#include "common/bidi_queue.h" -#include "common/bind.h" -#include "data_controller.h" -#include "l2cap/cid.h" -#include "l2cap/classic/internal/channel_configuration_state.h" -#include "l2cap/internal/channel_impl.h" -#include "l2cap/internal/data_controller.h" -#include "l2cap/l2cap_packets.h" -#include "l2cap/mtu.h" -#include "os/handler.h" -#include "os/queue.h" -#include "packet/base_packet_builder.h" -#include "packet/packet_view.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { -class Scheduler; -class ILink; - -/** - * A middle layer between L2CAP channel and outgoing packet scheduler. - * Fetches data (SDU) from an L2CAP channel queue end, handles L2CAP segmentation, and gives data to - * L2CAP scheduler. - */ -class Sender { -public: - using UpperEnqueue = packet::PacketView<packet::kLittleEndian>; - using UpperDequeue = packet::BasePacketBuilder; - using UpperQueueDownEnd = common::BidiQueueEnd<UpperEnqueue, UpperDequeue>; - - enum class ChannelMode { - BASIC = 0, - ERTM = 3, - LE_CREDIT_BASED = 10, - }; - - Sender(os::Handler* handler, ILink* link, Scheduler* scheduler, - std::shared_ptr<ChannelImpl> channel); - Sender(os::Handler* handler, ILink* link, Scheduler* scheduler, - std::shared_ptr<ChannelImpl> channel, ChannelMode mode); - ~Sender(); - - /** - * Callback from scheduler to indicate that scheduler already dequeued a packet from sender's - * queue. Segmenter can continue dequeuing from channel queue end. - */ - void OnPacketSent(); - - /** - * Called by the scheduler to return the next PDU to be sent - */ - std::unique_ptr<UpperDequeue> GetNextPacket(); - - void UpdateClassicConfiguration(classic::internal::ChannelConfigurationState config); - DataController* GetDataController(); - -private: - os::Handler* handler_; - ILink* link_; - UpperQueueDownEnd* queue_end_; - Scheduler* scheduler_; - const Cid channel_id_; - const Cid remote_channel_id_; - std::atomic_bool is_dequeue_registered_ = false; - RetransmissionAndFlowControlModeOption mode_ = - RetransmissionAndFlowControlModeOption::L2CAP_BASIC; - std::unique_ptr<DataController> data_controller_; - - void try_register_dequeue(); - void dequeue_callback(); -}; -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/internal/sender_test.cc b/system/gd/l2cap/internal/sender_test.cc deleted file mode 100644 index 92a02d0ce1..0000000000 --- a/system/gd/l2cap/internal/sender_test.cc +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/internal/sender.h" - -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include <future> - -#include "l2cap/internal/channel_impl_mock.h" -#include "l2cap/internal/ilink_mock.h" -#include "l2cap/internal/scheduler.h" -#include "os/handler.h" -#include "os/queue.h" -#include "os/thread.h" -#include "packet/raw_builder.h" - -namespace bluetooth { -namespace l2cap { -namespace internal { -namespace { - -using ::testing::Return; - -std::unique_ptr<packet::BasePacketBuilder> CreateSdu(std::vector<uint8_t> payload) { - auto raw_builder = std::make_unique<packet::RawBuilder>(); - raw_builder->AddOctets(payload); - return raw_builder; -} - -PacketView<kLittleEndian> GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet) { - auto bytes = std::make_shared<std::vector<uint8_t>>(); - BitInserter i(*bytes); - bytes->reserve(packet->size()); - packet->Serialize(i); - return packet::PacketView<packet::kLittleEndian>(bytes); -} - -class FakeScheduler : public Scheduler { -public: - void OnPacketsReady(Cid cid, int number_packets) override { - on_packets_ready_(cid, number_packets); - } - - void SetOnPacketsReady(std::function<void(Cid cid, int number_packets)> callback) { - on_packets_ready_ = callback; - } - std::function<void(Cid cid, int number_packets)> on_packets_ready_; -}; - -class L2capSenderTest : public ::testing::Test { -public: - std::unique_ptr<Sender::UpperDequeue> enqueue_callback() { - auto packet_one = CreateSdu({'a', 'b', 'c'}); - channel_queue_.GetUpEnd()->UnregisterEnqueue(); - return packet_one; - } - -protected: - void SetUp() override { - thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL); - user_handler_ = new os::Handler(thread_); - queue_handler_ = new os::Handler(thread_); - mock_channel_ = std::make_shared<testing::MockChannelImpl>(); - EXPECT_CALL(*mock_channel_, GetQueueDownEnd()) - .WillRepeatedly(Return(channel_queue_.GetDownEnd())); - EXPECT_CALL(*mock_channel_, GetCid()).WillRepeatedly(Return(cid_)); - EXPECT_CALL(*mock_channel_, GetRemoteCid()).WillRepeatedly(Return(cid_)); - sender_ = new Sender(queue_handler_, &link_, &scheduler_, mock_channel_); - } - - void TearDown() override { - queue_handler_->Clear(); - user_handler_->Clear(); - delete sender_; - delete queue_handler_; - delete user_handler_; - delete thread_; - } - - os::Thread* thread_ = nullptr; - os::Handler* user_handler_ = nullptr; - os::Handler* queue_handler_ = nullptr; - common::BidiQueue<Sender::UpperEnqueue, Sender::UpperDequeue> channel_queue_{10}; - std::shared_ptr<testing::MockChannelImpl> mock_channel_; - Sender* sender_ = nullptr; - Cid cid_ = 0x41; - FakeScheduler scheduler_; - testing::MockILink link_; -}; - -TEST_F(L2capSenderTest, send_packet) { - std::promise<void> promise; - auto future = promise.get_future(); - scheduler_.SetOnPacketsReady([&promise](Cid cid, int number_packets) { promise.set_value(); }); - channel_queue_.GetUpEnd()->RegisterEnqueue( - queue_handler_, - common::Bind(&L2capSenderTest::enqueue_callback, common::Unretained(this))); - auto status = future.wait_for(std::chrono::milliseconds(3)); - EXPECT_EQ(status, std::future_status::ready); - auto packet = sender_->GetNextPacket(); - EXPECT_NE(packet, nullptr); - auto packet_view = GetPacketView(std::move(packet)); - auto basic_frame_view = BasicFrameView::Create(packet_view); - EXPECT_TRUE(basic_frame_view.IsValid()); - EXPECT_EQ(basic_frame_view.GetChannelId(), cid_); - auto payload = basic_frame_view.GetPayload(); - std::string payload_string(payload.begin(), payload.end()); - EXPECT_EQ(payload_string, "abc"); -} - -} // namespace -} // namespace internal -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/l2cap_packet_fuzz_test.cc b/system/gd/l2cap/l2cap_packet_fuzz_test.cc deleted file mode 100644 index f4fe81e719..0000000000 --- a/system/gd/l2cap/l2cap_packet_fuzz_test.cc +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#define PACKET_FUZZ_TESTING -#include <memory> - -#include "l2cap/l2cap_packets.h" -#include "os/log.h" -#include "packet/bit_inserter.h" -#include "packet/raw_builder.h" - -using bluetooth::packet::BitInserter; -using bluetooth::packet::RawBuilder; -using std::vector; - -namespace bluetooth { -namespace l2cap { - -std::vector<void (*)(const uint8_t*, size_t)> l2cap_packet_fuzz_tests; - -DEFINE_AND_REGISTER_ExtendedInformationStartFrameReflectionFuzzTest(l2cap_packet_fuzz_tests); - -DEFINE_AND_REGISTER_StandardInformationFrameWithFcsReflectionFuzzTest(l2cap_packet_fuzz_tests); - -DEFINE_AND_REGISTER_StandardSupervisoryFrameWithFcsReflectionFuzzTest(l2cap_packet_fuzz_tests); - -DEFINE_AND_REGISTER_GroupFrameReflectionFuzzTest(l2cap_packet_fuzz_tests); - -DEFINE_AND_REGISTER_ConfigurationRequestReflectionFuzzTest(l2cap_packet_fuzz_tests); - -} // namespace l2cap -} // namespace bluetooth - -void RunL2capPacketFuzzTest(const uint8_t* data, size_t size) { - if (data == nullptr || size > 65536 /* Max ACL packet size */) { - return; - } - for (auto test_function : bluetooth::l2cap::l2cap_packet_fuzz_tests) { - test_function(data, size); - } -}
\ No newline at end of file diff --git a/system/gd/l2cap/l2cap_packet_test.cc b/system/gd/l2cap/l2cap_packet_test.cc deleted file mode 100644 index 0e87e806dd..0000000000 --- a/system/gd/l2cap/l2cap_packet_test.cc +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#define PACKET_TESTING -#include <gtest/gtest.h> - -#include <forward_list> -#include <memory> - -#include "l2cap/l2cap_packets.h" -#include "os/log.h" -#include "packet/bit_inserter.h" -#include "packet/raw_builder.h" - -using bluetooth::packet::BitInserter; -using bluetooth::packet::RawBuilder; -using std::vector; - -namespace bluetooth { -namespace l2cap { - -std::vector<uint8_t> extended_information_start_frame = { - 0x0B, /* First size byte */ - 0x00, /* Second size byte */ - 0xc1, /* First ChannelId byte */ - 0xc2, /**/ - 0x4A, /* 0x12 ReqSeq, Final, IFrame */ - 0xD0, /* 0x13 ReqSeq */ - 0x89, /* 0x21 TxSeq sar = START */ - 0x8C, /* 0x23 TxSeq */ - 0x10, /* first length byte */ - 0x11, /**/ - 0x01, /* first payload byte */ - 0x02, 0x03, 0x04, 0x05, -}; - -DEFINE_AND_INSTANTIATE_ExtendedInformationStartFrameReflectionTest( - extended_information_start_frame); - -std::vector<uint8_t> i_frame_with_fcs = {0x0E, 0x00, 0x40, 0x00, 0x02, 0x00, 0x00, 0x01, 0x02, - 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x38, 0x61}; -DEFINE_AND_INSTANTIATE_StandardInformationFrameWithFcsReflectionTest(i_frame_with_fcs); - -std::vector<uint8_t> rr_frame_with_fcs = {0x04, 0x00, 0x40, 0x00, 0x01, 0x01, 0xD4, 0x14}; -DEFINE_AND_INSTANTIATE_StandardSupervisoryFrameWithFcsReflectionTest(rr_frame_with_fcs); - -std::vector<uint8_t> g_frame = {0x03, 0x00, 0x02, 0x00, 0x01, 0x02, 0x03}; -DEFINE_AND_INSTANTIATE_GroupFrameReflectionTest(g_frame); - -std::vector<uint8_t> config_mtu_request = {0x04, 0x05, 0x08, 0x00, 0x41, 0x00, - 0x00, 0x00, 0x01, 0x02, 0xa0, 0x02}; -DEFINE_AND_INSTANTIATE_ConfigurationRequestReflectionTest(config_mtu_request); - -std::vector<uint8_t> config_request_one_defined_option = {0x04, 0x05, 0x08, 0x00, 0x41, 0x00, - 0x00, 0x00, 0x01, 0x02, 0x12, 0x34}; -std::vector<uint8_t> config_request_two_defined_options = {0x04, 0x05, 0x0c, 0x00, 0x41, 0x00, - 0x00, 0x00, 0x01, 0x02, 0x12, 0x34, - 0x02, 0x02, 0x56, 0x78}; -std::vector<uint8_t> config_request_two_undefined_options = {0x04, 0x05, 0x0e, 0x00, 0x41, 0x00, - 0x00, 0x00, 0x7f, 0x02, 0x01, 0x00, - 0x7e, 0x04, 0x11, 0x11, 0x00, 0x00}; -std::vector<uint8_t> config_request_hint_one_defined_option = {0x04, 0x05, 0x08, 0x00, 0x41, 0x00, - 0x00, 0x00, 0x81, 0x02, 0x12, 0x34}; -std::vector<uint8_t> config_request_hint_two_undefined_options = { - 0x04, 0x05, 0x0c, 0x00, 0x41, 0x00, 0x00, 0x00, - 0x90, 0x02, 0x01, 0x00, 0x91, 0x02, 0x11, 0x11}; -TEST(L2capPacketsTest, testConfigRequestOptions) { - { - std::shared_ptr<std::vector<uint8_t>> view_bytes = - std::make_shared<std::vector<uint8_t>>(config_request_one_defined_option); - - PacketView<kLittleEndian> packet_bytes_view(view_bytes); - auto view = ConfigurationRequestView::Create(ControlView::Create(packet_bytes_view)); - ASSERT_TRUE(view.IsValid()); - ASSERT_EQ(1ul, view.GetConfig().size()); - } - - { - std::shared_ptr<std::vector<uint8_t>> view_bytes = - std::make_shared<std::vector<uint8_t>>(config_request_two_defined_options); - - PacketView<kLittleEndian> packet_bytes_view(view_bytes); - auto view = ConfigurationRequestView::Create(ControlView::Create(packet_bytes_view)); - ASSERT_TRUE(view.IsValid()); - ASSERT_EQ(2ul, view.GetConfig().size()); - } - - { - std::shared_ptr<std::vector<uint8_t>> view_bytes = - std::make_shared<std::vector<uint8_t>>(config_request_two_undefined_options); - - PacketView<kLittleEndian> packet_bytes_view(view_bytes); - auto view = ConfigurationRequestView::Create(ControlView::Create(packet_bytes_view)); - ASSERT_TRUE(view.IsValid()); - ASSERT_EQ(2ul, view.GetConfig().size()); - } - - { - std::shared_ptr<std::vector<uint8_t>> view_bytes = - std::make_shared<std::vector<uint8_t>>(config_request_hint_one_defined_option); - - PacketView<kLittleEndian> packet_bytes_view(view_bytes); - auto view = ConfigurationRequestView::Create(ControlView::Create(packet_bytes_view)); - ASSERT_TRUE(view.IsValid()); - ASSERT_EQ(1ul, view.GetConfig().size()); - } - - { - std::shared_ptr<std::vector<uint8_t>> view_bytes = - std::make_shared<std::vector<uint8_t>>(config_request_hint_two_undefined_options); - - PacketView<kLittleEndian> packet_bytes_view(view_bytes); - auto view = ConfigurationRequestView::Create(ControlView::Create(packet_bytes_view)); - ASSERT_TRUE(view.IsValid()); - ASSERT_EQ(2ul, view.GetConfig().size()); - } -} - -DEFINE_ConfigurationRequestReflectionFuzzTest(); - -TEST(L2capFuzzRegressions, ConfigurationRequestFuzz_5691566077247488) { - uint8_t bluetooth_gd_fuzz_test_5691566077247488[] = { - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - RunConfigurationRequestReflectionFuzzTest(bluetooth_gd_fuzz_test_5691566077247488, - sizeof(bluetooth_gd_fuzz_test_5691566077247488)); -} - -TEST(L2capFuzzRegressions, ConfigurationRequestFuzz_5747922062802944) { - uint8_t bluetooth_gd_fuzz_test_5747922062802944[] = { - 0x04, 0x02, 0x02, 0x7f, 0x3f, 0x7f, 0x3f, 0x7e, 0x7f, - }; - RunConfigurationRequestReflectionFuzzTest(bluetooth_gd_fuzz_test_5747922062802944, - sizeof(bluetooth_gd_fuzz_test_5747922062802944)); -} - -TEST(L2capFuzzRegressions, ConfigurationRequestFuzz_5202709231697920) { - uint8_t bluetooth_gd_fuzz_test_5747922062802944[] = { - 0x04, 0x01, 0x45, 0x45, 0x05, 0x01, 0x01, 0x45, 0x05, 0x01, - }; - - RunConfigurationRequestReflectionFuzzTest(bluetooth_gd_fuzz_test_5747922062802944, - sizeof(bluetooth_gd_fuzz_test_5747922062802944)); -} - -TEST(L2capFuzzRegressions, ConfigurationRequestFuzz_manual_5655429176229888) { - std::vector<uint8_t> vec{0xc7, 0x0f, 0x0b, 0xe8, 0xfb, 0xff}; - - auto shared_bytes = std::make_shared<std::vector<uint8_t>>(vec); - PacketView<kLittleEndian> packet_bytes_view(shared_bytes); - - auto bfwf = BasicFrameWithFcsView::Create(packet_bytes_view); - ASSERT_FALSE(bfwf.IsValid()); - auto sfwf = StandardFrameWithFcsView::Create(bfwf); - ASSERT_FALSE(sfwf.IsValid()); - auto sif = StandardInformationFrameWithFcsView::Create(sfwf); - ASSERT_FALSE(sif.IsValid()); -} -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/dynamic_channel.cc b/system/gd/l2cap/le/dynamic_channel.cc deleted file mode 100644 index 5005348aa9..0000000000 --- a/system/gd/l2cap/le/dynamic_channel.cc +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/le/dynamic_channel.h" - -#include "l2cap/le/internal/link.h" - -namespace bluetooth { -namespace l2cap { -namespace le { -LinkOptions* DynamicChannel::GetLinkOptions() { return link_->GetLinkOptions(); } - -Mtu DynamicChannel::GetMtu() const { return mtu_; } - -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/dynamic_channel.h b/system/gd/l2cap/le/dynamic_channel.h deleted file mode 100644 index 42a9a3b6fb..0000000000 --- a/system/gd/l2cap/le/dynamic_channel.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include "l2cap/dynamic_channel.h" -#include "l2cap/le/link_options.h" -#include "l2cap/mtu.h" - -namespace bluetooth { -namespace l2cap { -namespace le { -namespace internal { -class Link; -} - -class DynamicChannel : public l2cap::DynamicChannel { -public: - DynamicChannel(std::shared_ptr<l2cap::internal::DynamicChannelImpl> impl, - os::Handler* l2cap_handler, internal::Link* link, Mtu mtu) - : l2cap::DynamicChannel(impl, l2cap_handler), link_(link), mtu_(mtu) {} - - /** - * Get the Proxy for L2CAP Link Options. - * Only few special L2CAP users need to use it, including - * Hearing Aid Profile and Java API. - */ - LinkOptions* GetLinkOptions(); - - Mtu GetMtu() const; - -private: - internal::Link* link_; - Mtu mtu_; -}; - -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/dynamic_channel_configuration_option.h b/system/gd/l2cap/le/dynamic_channel_configuration_option.h deleted file mode 100644 index 60d98b00f0..0000000000 --- a/system/gd/l2cap/le/dynamic_channel_configuration_option.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include "l2cap/mtu.h" - -namespace bluetooth { -namespace l2cap { -namespace le { - -/** - * Configuration Option specified by L2CAP Channel user on a dynamic channel. L2CAP module will - * configure the channel based on user provided option. - */ -struct DynamicChannelConfigurationOption { - /** - * Maximum SDU size that the L2CAP Channel user is able to receive or send. When the channel is - * created, the actual MTU is the minimum of the suggested MTU between two devices. - */ - Mtu mtu = kDefaultClassicMtu; -}; - -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/dynamic_channel_manager.cc b/system/gd/l2cap/le/dynamic_channel_manager.cc deleted file mode 100644 index 72ae165bc0..0000000000 --- a/system/gd/l2cap/le/dynamic_channel_manager.cc +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/le/dynamic_channel_manager.h" - -#include "l2cap/le/internal/dynamic_channel_service_impl.h" -#include "l2cap/le/internal/dynamic_channel_service_manager_impl.h" -#include "l2cap/le/internal/link.h" -#include "l2cap/le/internal/link_manager.h" - -namespace bluetooth { -namespace l2cap { -namespace le { - -bool DynamicChannelManager::ConnectChannel(hci::AddressWithType device, - DynamicChannelConfigurationOption configuration_option, - Psm psm, OnConnectionOpenCallback on_connection_open, - OnConnectionFailureCallback on_fail_callback, - os::Handler* handler) { - internal::Link::PendingDynamicChannelConnection pending_dynamic_channel_connection{ - .handler_ = handler, - .on_open_callback_ = std::move(on_connection_open), - .on_fail_callback_ = std::move(on_fail_callback), - .configuration_ = configuration_option, - }; - l2cap_layer_handler_->Post(common::BindOnce(&internal::LinkManager::ConnectDynamicChannelServices, - common::Unretained(link_manager_), device, - std::move(pending_dynamic_channel_connection), psm)); - - return true; -} - -bool DynamicChannelManager::RegisterService(Psm psm, - DynamicChannelConfigurationOption configuration_option, - const SecurityPolicy& security_policy, - OnRegistrationCompleteCallback on_registration_complete, - OnConnectionOpenCallback on_connection_open, - os::Handler* handler) { - internal::DynamicChannelServiceImpl::PendingRegistration pending_registration{ - .user_handler_ = handler, - .security_policy_ = security_policy, - .on_registration_complete_callback_ = std::move(on_registration_complete), - .on_connection_open_callback_ = std::move(on_connection_open), - .configuration_ = configuration_option, - }; - l2cap_layer_handler_->Post(common::BindOnce(&internal::DynamicChannelServiceManagerImpl::Register, - common::Unretained(service_manager_), psm, - std::move(pending_registration))); - - return true; -} - -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/dynamic_channel_manager.h b/system/gd/l2cap/le/dynamic_channel_manager.h deleted file mode 100644 index 2cef583843..0000000000 --- a/system/gd/l2cap/le/dynamic_channel_manager.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 2019 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. - */ -#pragma once - -#include <string> - -#include "hci/acl_manager.h" -#include "hci/address.h" -#include "l2cap/l2cap_packets.h" -#include "l2cap/le/dynamic_channel.h" -#include "l2cap/le/dynamic_channel_configuration_option.h" -#include "l2cap/le/dynamic_channel_service.h" -#include "l2cap/le/security_policy.h" -#include "l2cap/psm.h" -#include "os/handler.h" - -namespace bluetooth { -namespace l2cap { -namespace le { - -class L2capLeModule; - -namespace internal { -class LinkManager; -class DynamicChannelServiceManagerImpl; -} // namespace internal - -class DynamicChannelManager { -public: - DynamicChannelManager(const DynamicChannelManager&) = delete; - DynamicChannelManager& operator=(const DynamicChannelManager&) = delete; - - enum class ConnectionResultCode { - SUCCESS = 0, - FAIL_NO_SERVICE_REGISTERED = 1, // No service is registered - FAIL_HCI_ERROR = 2, // See hci_error - FAIL_L2CAP_ERROR = 3, // See l2cap_connection_response_result - }; - - struct ConnectionResult { - ConnectionResultCode connection_result_code = ConnectionResultCode::SUCCESS; - hci::ErrorCode hci_error = hci::ErrorCode::SUCCESS; - LeCreditBasedConnectionResponseResult l2cap_connection_response_result = - LeCreditBasedConnectionResponseResult::SUCCESS; - }; - /** - * OnConnectionFailureCallback(std::string failure_reason); - */ - using OnConnectionFailureCallback = common::OnceCallback<void(ConnectionResult result)>; - - /** - * OnConnectionOpenCallback(DynamicChannel channel); - */ - using OnConnectionOpenCallback = common::Callback<void(std::unique_ptr<DynamicChannel>)>; - - enum class RegistrationResult { - SUCCESS = 0, - FAIL_DUPLICATE_SERVICE = 1, // Duplicate service registration for the same PSM - FAIL_INVALID_SERVICE = 2, // Invalid PSM - }; - - /** - * OnRegistrationFailureCallback(RegistrationResult result, DynamicChannelService service); - */ - using OnRegistrationCompleteCallback = - common::OnceCallback<void(RegistrationResult, std::unique_ptr<DynamicChannelService>)>; - - /** - * Connect to a Dynamic channel on a remote device - * - * - This method is asynchronous - * - When false is returned, the connection fails immediately - * - When true is returned, method caller should wait for on_fail_callback or on_open_callback - * - If an LE connection does not exist, this method will create an LE connection - * - If HCI connection failed, on_fail_callback will be triggered with FAIL_HCI_ERROR - * - If Dynamic channel on a remote device is already reported as connected via on_open_callback, - * it won't be reported again - * - * @param device: Remote device to make this connection. - * @param psm: Service PSM to connect. PSM is defined in Core spec Vol 3 Part A 4.2. - * @param on_open_callback: A callback to indicate success of a connection initiated from a remote - * device. - * @param on_fail_callback: A callback to indicate connection failure along with a status code. - * @param handler: The handler context in which to execute the @callback parameters. - * @param configuration_option: The configuration options for this channel - * - * Returns: true if connection was able to be initiated, false otherwise. - */ - bool ConnectChannel(hci::AddressWithType device, - DynamicChannelConfigurationOption configuration_option, Psm psm, - OnConnectionOpenCallback on_connection_open, - OnConnectionFailureCallback on_fail_callback, os::Handler* handler); - - /** - * Register a service to receive incoming connections bound to a specific channel. - * - * - This method is asynchronous. - * - When false is returned, the registration fails immediately. - * - When true is returned, method caller should wait for on_service_registered callback that - * contains a DynamicChannelService object. The registered service can be managed from that - * object. - * - If a PSM is already registered or some other error happens, on_registration_complete will be - * triggered with a non-SUCCESS value - * - After a service is registered, a DynamicChannel is delivered through on_open_callback when - * the remote initiates a channel open and channel is opened successfully - * - on_open_callback, will only be triggered after on_service_registered callback - * - * @param security_policy: The security policy used for the connection. - * @param psm: Service PSM to register. PSM is defined in Core spec Vol 3 Part A 4.2. - * @param on_registration_complete: A callback to indicate the service setup has completed. If the - * return status is not SUCCESS, it means service is not registered due to reasons like PSM - * already take - * @param on_open_callback: A callback to indicate success of a connection initiated from a remote - * device. - * @param handler: The handler context in which to execute the @callback parameter. - * @param configuration_option: The configuration options for this channel - */ - bool RegisterService(Psm psm, DynamicChannelConfigurationOption configuration_option, - const SecurityPolicy& security_policy, - OnRegistrationCompleteCallback on_registration_complete, - OnConnectionOpenCallback on_connection_open, os::Handler* handler); - - friend class L2capLeModule; - -private: - // The constructor is not to be used by user code - DynamicChannelManager(internal::DynamicChannelServiceManagerImpl* service_manager, - internal::LinkManager* link_manager, os::Handler* l2cap_layer_handler) - : service_manager_(service_manager), - link_manager_(link_manager), - l2cap_layer_handler_(l2cap_layer_handler) { - log::assert_that(service_manager_ != nullptr, "assert failed: service_manager_ != nullptr"); - log::assert_that(link_manager_ != nullptr, "assert failed: link_manager_ != nullptr"); - log::assert_that(l2cap_layer_handler_ != nullptr, - "assert failed: l2cap_layer_handler_ != nullptr"); - } - internal::DynamicChannelServiceManagerImpl* service_manager_ = nullptr; - internal::LinkManager* link_manager_ = nullptr; - os::Handler* l2cap_layer_handler_ = nullptr; -}; - -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/dynamic_channel_service.cc b/system/gd/l2cap/le/dynamic_channel_service.cc deleted file mode 100644 index d4f4db62e6..0000000000 --- a/system/gd/l2cap/le/dynamic_channel_service.cc +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/le/dynamic_channel_service.h" - -#include "common/bind.h" -#include "l2cap/le/internal/dynamic_channel_service_manager_impl.h" -#include "os/log.h" - -namespace bluetooth { -namespace l2cap { -namespace le { - -void DynamicChannelService::Unregister(OnUnregisteredCallback on_unregistered, - os::Handler* on_unregistered_handler) { - log::assert_that(manager_ != nullptr, "this service is invalid"); - l2cap_layer_handler_->Post(common::BindOnce( - &internal::DynamicChannelServiceManagerImpl::Unregister, common::Unretained(manager_), - psm_, std::move(on_unregistered), on_unregistered_handler)); -} - -Psm DynamicChannelService::GetPsm() const { return psm_; } - -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/dynamic_channel_service.h b/system/gd/l2cap/le/dynamic_channel_service.h deleted file mode 100644 index 867b57a519..0000000000 --- a/system/gd/l2cap/le/dynamic_channel_service.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <bluetooth/log.h> - -#include "common/callback.h" -#include "l2cap/psm.h" -#include "os/handler.h" -#include "os/log.h" - -namespace bluetooth { -namespace l2cap { -namespace le { - -namespace internal { -class DynamicChannelServiceManagerImpl; -} - -class DynamicChannelService { -public: - DynamicChannelService() = default; - DynamicChannelService(const DynamicChannelService&) = delete; - DynamicChannelService& operator=(const DynamicChannelService&) = delete; - - using OnUnregisteredCallback = common::OnceCallback<void()>; - - /** - * Unregister a service from L2CAP module. This operation cannot fail. - * All channels opened for this service will be closed. - * - * @param on_unregistered will be triggered when unregistration is complete - */ - void Unregister(OnUnregisteredCallback on_unregistered, os::Handler* on_unregistered_handler); - - friend internal::DynamicChannelServiceManagerImpl; - - Psm GetPsm() const; - -protected: - DynamicChannelService(Psm psm, internal::DynamicChannelServiceManagerImpl* manager, - os::Handler* handler) - : psm_(psm), manager_(manager), l2cap_layer_handler_(handler) { - log::assert_that(manager_ != nullptr, "assert failed: manager_ != nullptr"); - log::assert_that(l2cap_layer_handler_ != nullptr, - "assert failed: l2cap_layer_handler_ != nullptr"); - } - -private: - Psm psm_ = kDefaultPsm; - internal::DynamicChannelServiceManagerImpl* manager_ = nullptr; - os::Handler* l2cap_layer_handler_; -}; - -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/facade.cc b/system/gd/l2cap/le/facade.cc deleted file mode 100644 index 2ce76039aa..0000000000 --- a/system/gd/l2cap/le/facade.cc +++ /dev/null @@ -1,487 +0,0 @@ -/* - * Copyright 2020 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 "l2cap/le/facade.h" - -#include <bluetooth/log.h> - -#include "blueberry/facade/l2cap/le/facade.grpc.pb.h" -#include "grpc/grpc_event_queue.h" -#include "l2cap/le/dynamic_channel.h" -#include "l2cap/le/dynamic_channel_manager.h" -#include "l2cap/le/dynamic_channel_service.h" -#include "l2cap/le/l2cap_le_module.h" -#include "l2cap/le/security_policy.h" -#include "l2cap/psm.h" -#include "packet/raw_builder.h" - -namespace bluetooth { -namespace l2cap { -namespace le { - -using namespace blueberry::facade::l2cap::le; - -SecurityPolicy SecurityLevelToPolicy(SecurityLevel level) { - switch (level) { - case SecurityLevel::NO_SECURITY: - return SecurityPolicy::NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK; - case SecurityLevel::UNAUTHENTICATED_PAIRING_WITH_ENCRYPTION: - return SecurityPolicy::ENCRYPTED_TRANSPORT; - case SecurityLevel::AUTHENTICATED_PAIRING_WITH_ENCRYPTION: - return SecurityPolicy::AUTHENTICATED_ENCRYPTED_TRANSPORT; - case SecurityLevel::AUTHENTICATED_PAIRING_WITH_128_BIT_KEY: - return SecurityPolicy::_NOT_FOR_YOU__AUTHENTICATED_PAIRING_WITH_128_BIT_KEY; - case SecurityLevel::AUTHORIZATION: - return SecurityPolicy::_NOT_FOR_YOU__AUTHORIZATION; - default: - return SecurityPolicy::NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK; - } -} - -static constexpr auto kChannelOpenTimeout = std::chrono::seconds(4); - -class L2capLeModuleFacadeService : public L2capLeModuleFacade::Service { -public: - L2capLeModuleFacadeService(L2capLeModule* l2cap_layer, os::Handler* facade_handler) - : l2cap_layer_(l2cap_layer), facade_handler_(facade_handler) { - log::assert_that(l2cap_layer_ != nullptr, "assert failed: l2cap_layer_ != nullptr"); - log::assert_that(facade_handler_ != nullptr, "assert failed: facade_handler_ != nullptr"); - } - - ::grpc::Status FetchL2capData( - ::grpc::ServerContext* context, const ::google::protobuf::Empty* /* request */, - ::grpc::ServerWriter<::bluetooth::l2cap::le::L2capPacket>* writer) override { - return pending_l2cap_data_.RunLoop(context, writer); - } - - ::grpc::Status OpenDynamicChannel(::grpc::ServerContext* /* context */, - const OpenDynamicChannelRequest* request, - OpenDynamicChannelResponse* response) override { - auto service_helper = dynamic_channel_helper_map_.find(request->psm()); - if (service_helper == dynamic_channel_helper_map_.end()) { - return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Psm not registered"); - } - hci::Address peer_address; - log::assert_that( - hci::Address::FromString(request->remote().address().address(), peer_address), - "assert failed: hci::Address::FromString(request->remote().address().address(), " - "peer_address)"); - // TODO: Support different address type - hci::AddressWithType peer(peer_address, hci::AddressType::RANDOM_DEVICE_ADDRESS); - service_helper->second->Connect(peer); - response->set_status(static_cast<int>( - service_helper->second->channel_open_fail_reason_.l2cap_connection_response_result)); - return ::grpc::Status::OK; - } - - ::grpc::Status CloseDynamicChannel(::grpc::ServerContext* /* context */, - const CloseDynamicChannelRequest* request, - ::google::protobuf::Empty* /* response */) override { - auto service_helper = dynamic_channel_helper_map_.find(request->psm()); - if (service_helper == dynamic_channel_helper_map_.end()) { - return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Psm not registered"); - } - if (service_helper->second->channel_ == nullptr) { - return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Channel not open"); - } - auto address = service_helper->second->channel_->GetDevice().GetAddress(); - hci::Address peer_address; - log::assert_that( - hci::Address::FromString(request->remote().address().address(), peer_address), - "assert failed: hci::Address::FromString(request->remote().address().address(), " - "peer_address)"); - if (address != peer_address) { - return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, - "Remote address doesn't match"); - } - service_helper->second->channel_->Close(); - return ::grpc::Status::OK; - } - - ::grpc::Status SetDynamicChannel( - ::grpc::ServerContext* /* context */, - const ::bluetooth::l2cap::le::SetEnableDynamicChannelRequest* request, - ::google::protobuf::Empty* /* response */) override { - if (request->enable()) { - dynamic_channel_helper_map_.emplace( - request->psm(), std::make_unique<L2capDynamicChannelHelper>( - this, l2cap_layer_, facade_handler_, request->psm(), - SecurityLevelToPolicy(request->security_level()))); - return ::grpc::Status::OK; - } else { - auto service_helper = dynamic_channel_helper_map_.find(request->psm()); - if (service_helper == dynamic_channel_helper_map_.end()) { - return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Psm not registered"); - } - service_helper->second->service_->Unregister(common::BindOnce([] {}), facade_handler_); - return ::grpc::Status::OK; - } - } - - ::grpc::Status SendDynamicChannelPacket( - ::grpc::ServerContext* /* context */, - const ::bluetooth::l2cap::le::DynamicChannelPacket* request, - ::google::protobuf::Empty* /* response */) override { - std::unique_lock<std::mutex> lock(channel_map_mutex_); - if (dynamic_channel_helper_map_.find(request->psm()) == dynamic_channel_helper_map_.end()) { - return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Psm not registered"); - } - std::vector<uint8_t> packet(request->payload().begin(), request->payload().end()); - if (!dynamic_channel_helper_map_[request->psm()]->SendPacket(packet)) { - return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Channel not open"); - } - return ::grpc::Status::OK; - } - - class L2capDynamicChannelHelper { - public: - L2capDynamicChannelHelper(L2capLeModuleFacadeService* service, L2capLeModule* l2cap_layer, - os::Handler* handler, Psm psm, SecurityPolicy security_policy) - : facade_service_(service), l2cap_layer_(l2cap_layer), handler_(handler), psm_(psm) { - dynamic_channel_manager_ = l2cap_layer_->GetDynamicChannelManager(); - dynamic_channel_manager_->RegisterService( - psm, {}, security_policy, - common::BindOnce(&L2capDynamicChannelHelper::on_l2cap_service_registration_complete, - common::Unretained(this)), - common::Bind(&L2capDynamicChannelHelper::on_connection_open, - common::Unretained(this)), - handler_); - } - - ~L2capDynamicChannelHelper() { - if (channel_ != nullptr) { - channel_->GetQueueUpEnd()->UnregisterDequeue(); - channel_ = nullptr; - } - } - - void Connect(hci::AddressWithType address) { - dynamic_channel_manager_->ConnectChannel( - address, {}, psm_, - common::Bind(&L2capDynamicChannelHelper::on_connection_open, - common::Unretained(this)), - common::Bind(&L2capDynamicChannelHelper::on_connect_fail, common::Unretained(this)), - handler_); - std::unique_lock<std::mutex> lock(channel_open_cv_mutex_); - if (!channel_open_cv_.wait_for(lock, kChannelOpenTimeout, - [this] { return channel_ != nullptr; })) { - log::warn("Channel is not open for psm {}", psm_); - } - } - - void on_l2cap_service_registration_complete( - DynamicChannelManager::RegistrationResult registration_result, - std::unique_ptr<DynamicChannelService> service) { - if (registration_result != DynamicChannelManager::RegistrationResult::SUCCESS) { - log::error("Service registration failed"); - } else { - service_ = std::move(service); - } - } - - // invoked from Facade Handler - void on_connection_open(std::unique_ptr<DynamicChannel> channel) { - { - std::unique_lock<std::mutex> lock(channel_open_cv_mutex_); - channel_ = std::move(channel); - } - channel_open_cv_.notify_all(); - channel_->RegisterOnCloseCallback(facade_service_->facade_handler_->BindOnceOn( - this, &L2capDynamicChannelHelper::on_close_callback)); - channel_->GetQueueUpEnd()->RegisterDequeue( - facade_service_->facade_handler_, - common::Bind(&L2capDynamicChannelHelper::on_incoming_packet, - common::Unretained(this))); - } - - void on_close_callback(hci::ErrorCode /* error_code */) { - { - std::unique_lock<std::mutex> lock(channel_open_cv_mutex_); - channel_->GetQueueUpEnd()->UnregisterDequeue(); - } - channel_ = nullptr; - } - - void on_connect_fail(DynamicChannelManager::ConnectionResult result) { - { - std::unique_lock<std::mutex> lock(channel_open_cv_mutex_); - channel_ = nullptr; - channel_open_fail_reason_ = result; - } - channel_open_cv_.notify_all(); - } - - void on_incoming_packet() { - auto packet = channel_->GetQueueUpEnd()->TryDequeue(); - std::string data = std::string(packet->begin(), packet->end()); - L2capPacket l2cap_data; - l2cap_data.set_psm(psm_); - l2cap_data.set_payload(data); - facade_service_->pending_l2cap_data_.OnIncomingEvent(l2cap_data); - } - - bool SendPacket(std::vector<uint8_t> packet) { - if (channel_ == nullptr) { - std::unique_lock<std::mutex> lock(channel_open_cv_mutex_); - if (!channel_open_cv_.wait_for(lock, kChannelOpenTimeout, - [this] { return channel_ != nullptr; })) { - log::warn("Channel is not open for psm {}", psm_); - return false; - } - } - std::promise<void> promise; - auto future = promise.get_future(); - channel_->GetQueueUpEnd()->RegisterEnqueue( - handler_, - common::Bind(&L2capDynamicChannelHelper::enqueue_callback, common::Unretained(this), - packet, common::Passed(std::move(promise)))); - auto status = future.wait_for(std::chrono::milliseconds(500)); - if (status != std::future_status::ready) { - log::error("Can't send packet because the previous packet wasn't sent yet"); - return false; - } - return true; - } - - std::unique_ptr<packet::BasePacketBuilder> enqueue_callback(std::vector<uint8_t> packet, - std::promise<void> promise) { - auto packet_one = std::make_unique<packet::RawBuilder>(2000); - packet_one->AddOctets(packet); - channel_->GetQueueUpEnd()->UnregisterEnqueue(); - promise.set_value(); - return packet_one; - } - - L2capLeModuleFacadeService* facade_service_; - L2capLeModule* l2cap_layer_; - os::Handler* handler_; - std::unique_ptr<DynamicChannelManager> dynamic_channel_manager_; - std::unique_ptr<DynamicChannelService> service_; - std::unique_ptr<DynamicChannel> channel_ = nullptr; - Psm psm_; - DynamicChannelManager::ConnectionResult channel_open_fail_reason_; - std::condition_variable channel_open_cv_; - std::mutex channel_open_cv_mutex_; - }; - - ::grpc::Status SetFixedChannel(::grpc::ServerContext* /* context */, - const SetEnableFixedChannelRequest* request, - ::google::protobuf::Empty* /* response */) override { - if (request->enable()) { - fixed_channel_helper_map_.emplace( - request->cid(), std::make_unique<L2capFixedChannelHelper>( - this, l2cap_layer_, facade_handler_, request->cid())); - return ::grpc::Status::OK; - } else { - auto service_helper = fixed_channel_helper_map_.find(request->cid()); - if (service_helper == fixed_channel_helper_map_.end()) { - return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Cid not registered"); - } - service_helper->second->channel_->Release(); - service_helper->second->service_->Unregister(common::BindOnce([] {}), facade_handler_); - return ::grpc::Status::OK; - } - } - - ::grpc::Status SendFixedChannelPacket(::grpc::ServerContext* /* context */, - const FixedChannelPacket* request, - ::google::protobuf::Empty* /* response */) override { - std::unique_lock<std::mutex> lock(channel_map_mutex_); - if (fixed_channel_helper_map_.find(request->cid()) == fixed_channel_helper_map_.end()) { - return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Cid not registered"); - } - std::vector<uint8_t> packet(request->payload().begin(), request->payload().end()); - if (!fixed_channel_helper_map_[request->cid()]->SendPacket(packet)) { - return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Channel not open"); - } - return ::grpc::Status::OK; - } - - class L2capFixedChannelHelper { - public: - L2capFixedChannelHelper(L2capLeModuleFacadeService* service, L2capLeModule* l2cap_layer, - os::Handler* handler, Cid cid) - : facade_service_(service), l2cap_layer_(l2cap_layer), handler_(handler), cid_(cid) { - fixed_channel_manager_ = l2cap_layer_->GetFixedChannelManager(); - fixed_channel_manager_->RegisterService( - cid_, - common::BindOnce(&L2capFixedChannelHelper::on_l2cap_service_registration_complete, - common::Unretained(this)), - common::Bind(&L2capFixedChannelHelper::on_connection_open, common::Unretained(this)), - handler_); - } - - ~L2capFixedChannelHelper() { - if (channel_ != nullptr) { - channel_->GetQueueUpEnd()->UnregisterDequeue(); - channel_->Release(); - channel_ = nullptr; - } - } - - void Connect(hci::AddressWithType address) { - fixed_channel_manager_->ConnectServices( - address, - common::BindOnce(&L2capFixedChannelHelper::on_connect_fail, common::Unretained(this)), - handler_); - std::unique_lock<std::mutex> lock(channel_open_cv_mutex_); - if (!channel_open_cv_.wait_for(lock, kChannelOpenTimeout, - [this] { return channel_ != nullptr; })) { - log::warn("Channel is not open for cid {}", cid_); - } - } - - void on_l2cap_service_registration_complete( - FixedChannelManager::RegistrationResult registration_result, - std::unique_ptr<FixedChannelService> service) { - if (registration_result != FixedChannelManager::RegistrationResult::SUCCESS) { - log::error("Service registration failed"); - } else { - service_ = std::move(service); - } - } - - // invoked from Facade Handler - void on_connection_open(std::unique_ptr<FixedChannel> channel) { - { - std::unique_lock<std::mutex> lock(channel_open_cv_mutex_); - channel_ = std::move(channel); - channel_->RegisterOnCloseCallback( - handler_, common::BindOnce(&L2capFixedChannelHelper::on_close_callback, - common::Unretained(this))); - channel_->Acquire(); - } - channel_open_cv_.notify_all(); - channel_->GetQueueUpEnd()->RegisterDequeue( - facade_service_->facade_handler_, - common::Bind(&L2capFixedChannelHelper::on_incoming_packet, common::Unretained(this))); - } - - void on_close_callback(hci::ErrorCode /* error_code */) { - { - std::unique_lock<std::mutex> lock(channel_open_cv_mutex_); - channel_->GetQueueUpEnd()->UnregisterDequeue(); - } - channel_ = nullptr; - } - - void on_connect_fail(FixedChannelManager::ConnectionResult /* result */) { - { - std::unique_lock<std::mutex> lock(channel_open_cv_mutex_); - channel_ = nullptr; - } - channel_open_cv_.notify_all(); - } - - void on_incoming_packet() { - auto packet = channel_->GetQueueUpEnd()->TryDequeue(); - std::string data = std::string(packet->begin(), packet->end()); - L2capPacket l2cap_data; - l2cap_data.set_fixed_cid(cid_); - l2cap_data.set_payload(data); - facade_service_->pending_l2cap_data_.OnIncomingEvent(l2cap_data); - } - - bool SendPacket(std::vector<uint8_t> packet) { - if (channel_ == nullptr) { - std::unique_lock<std::mutex> lock(channel_open_cv_mutex_); - if (!channel_open_cv_.wait_for(lock, kChannelOpenTimeout, - [this] { return channel_ != nullptr; })) { - log::warn("Channel is not open for cid {}", cid_); - return false; - } - } - std::promise<void> promise; - auto future = promise.get_future(); - channel_->GetQueueUpEnd()->RegisterEnqueue( - handler_, - common::Bind(&L2capFixedChannelHelper::enqueue_callback, common::Unretained(this), - packet, common::Passed(std::move(promise)))); - auto status = future.wait_for(std::chrono::milliseconds(500)); - if (status != std::future_status::ready) { - log::error("Can't send packet because the previous packet wasn't sent yet"); - return false; - } - return true; - } - - std::unique_ptr<packet::BasePacketBuilder> enqueue_callback(std::vector<uint8_t> packet, - std::promise<void> promise) { - auto packet_one = std::make_unique<packet::RawBuilder>(2000); - packet_one->AddOctets(packet); - channel_->GetQueueUpEnd()->UnregisterEnqueue(); - promise.set_value(); - return packet_one; - } - - L2capLeModuleFacadeService* facade_service_; - L2capLeModule* l2cap_layer_; - os::Handler* handler_; - std::unique_ptr<FixedChannelManager> fixed_channel_manager_; - std::unique_ptr<FixedChannelService> service_; - std::unique_ptr<FixedChannel> channel_ = nullptr; - Cid cid_; - std::condition_variable channel_open_cv_; - std::mutex channel_open_cv_mutex_; - }; - - ::grpc::Status SendConnectionParameterUpdate(::grpc::ServerContext* /* context */, - const ConnectionParameter* request, - ::google::protobuf::Empty* /* response */) override { - if (dynamic_channel_helper_map_.empty()) { - return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, - "Need to open at least one dynamic channel first"); - } - auto& dynamic_channel_helper = dynamic_channel_helper_map_.begin()->second; - dynamic_channel_helper->channel_->GetLinkOptions()->UpdateConnectionParameter( - request->conn_interval_min(), request->conn_interval_max(), request->conn_latency(), - request->supervision_timeout(), request->min_ce_length(), request->max_ce_length()); - - return ::grpc::Status::OK; - } - - L2capLeModule* l2cap_layer_; - os::Handler* facade_handler_; - std::mutex channel_map_mutex_; - std::map<Psm, std::unique_ptr<L2capDynamicChannelHelper>> dynamic_channel_helper_map_; - std::map<Cid, std::unique_ptr<L2capFixedChannelHelper>> fixed_channel_helper_map_; - ::bluetooth::grpc::GrpcEventQueue<L2capPacket> pending_l2cap_data_{"FetchL2capData"}; -}; - -void L2capLeModuleFacadeModule::ListDependencies(ModuleList* list) const { - ::bluetooth::grpc::GrpcFacadeModule::ListDependencies(list); - list->add<l2cap::le::L2capLeModule>(); -} - -void L2capLeModuleFacadeModule::Start() { - ::bluetooth::grpc::GrpcFacadeModule::Start(); - service_ = - new L2capLeModuleFacadeService(GetDependency<l2cap::le::L2capLeModule>(), GetHandler()); -} - -void L2capLeModuleFacadeModule::Stop() { - delete service_; - ::bluetooth::grpc::GrpcFacadeModule::Stop(); -} - -::grpc::Service* L2capLeModuleFacadeModule::GetService() const { return service_; } - -const ModuleFactory L2capLeModuleFacadeModule::Factory = - ::bluetooth::ModuleFactory([]() { return new L2capLeModuleFacadeModule(); }); - -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/facade.h b/system/gd/l2cap/le/facade.h deleted file mode 100644 index da12934de7..0000000000 --- a/system/gd/l2cap/le/facade.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2020 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. - */ -#pragma once - -#include <grpc++/grpc++.h> - -#include "grpc/grpc_module.h" - -namespace bluetooth { -namespace l2cap { -namespace le { - -class L2capLeModuleFacadeService; - -class L2capLeModuleFacadeModule : public ::bluetooth::grpc::GrpcFacadeModule { -public: - static const ModuleFactory Factory; - - void ListDependencies(ModuleList* list) const override; - - void Start() override; - - void Stop() override; - - ::grpc::Service* GetService() const override; - -private: - L2capLeModuleFacadeService* service_; -}; - -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/fixed_channel.cc b/system/gd/l2cap/le/fixed_channel.cc deleted file mode 100644 index d1a071aa39..0000000000 --- a/system/gd/l2cap/le/fixed_channel.cc +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/le/fixed_channel.h" - -#include "common/bind.h" -#include "l2cap/le/internal/fixed_channel_impl.h" - -namespace bluetooth { -namespace l2cap { -namespace le { - -hci::AddressWithType FixedChannel::GetDevice() const { return impl_->GetDevice(); } - -void FixedChannel::RegisterOnCloseCallback(os::Handler* user_handler, - FixedChannel::OnCloseCallback on_close_callback) { - l2cap_handler_->Post(common::BindOnce(&internal::FixedChannelImpl::RegisterOnCloseCallback, impl_, - user_handler, std::move(on_close_callback))); -} - -void FixedChannel::Acquire() { - l2cap_handler_->Post(common::BindOnce(&internal::FixedChannelImpl::Acquire, impl_)); -} - -void FixedChannel::Release() { - l2cap_handler_->Post(common::BindOnce(&internal::FixedChannelImpl::Release, impl_)); -} - -common::BidiQueueEnd<packet::BasePacketBuilder, packet::PacketView<packet::kLittleEndian>>* -FixedChannel::GetQueueUpEnd() const { - return impl_->GetQueueUpEnd(); -} - -LinkOptions* FixedChannel::GetLinkOptions() { return impl_->GetLinkOptions(); } - -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/fixed_channel.h b/system/gd/l2cap/le/fixed_channel.h deleted file mode 100644 index ec8b92c6a2..0000000000 --- a/system/gd/l2cap/le/fixed_channel.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2019 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. - */ -#pragma once - -#include "common/bidi_queue.h" -#include "common/callback.h" -#include "hci/acl_manager.h" -#include "l2cap/cid.h" -#include "l2cap/le/link_options.h" -#include "os/handler.h" -#include "packet/base_packet_builder.h" -#include "packet/packet_view.h" - -namespace bluetooth { -namespace l2cap { -namespace le { - -namespace internal { -class FixedChannelImpl; -} // namespace internal - -/** - * L2CAP fixed channel object. When a new object is created, it must be - * acquired through calling {@link FixedChannel#Acquire()} within X seconds. - * Otherwise, {@link FixedChannel#Release()} will be called automatically. - * - */ -class FixedChannel { -public: - // Should only be constructed by modules that have access to LinkManager - FixedChannel(std::shared_ptr<internal::FixedChannelImpl> impl, os::Handler* l2cap_handler) - : impl_(std::move(impl)), l2cap_handler_(l2cap_handler) { - log::assert_that(impl_ != nullptr, "assert failed: impl_ != nullptr"); - log::assert_that(l2cap_handler_ != nullptr, "assert failed: l2cap_handler_ != nullptr"); - } - - hci::AddressWithType GetDevice() const; - - /** - * Register close callback. If close callback is registered, when a channel is closed, the - * channel's resource will only be freed after on_close callback is invoked. Otherwise, if no - * on_close callback is registered, the channel's resource will be freed immediately after - * closing. - * - * @param user_handler The handler used to invoke the callback on - * @param on_close_callback The callback invoked upon channel closing. - */ - using OnCloseCallback = common::OnceCallback<void(hci::ErrorCode)>; - void RegisterOnCloseCallback(os::Handler* user_handler, OnCloseCallback on_close_callback); - - /** - * Indicate that this Fixed Channel is being used. This will prevent ACL connection from being - * disconnected. - */ - void Acquire(); - - /** - * Indicate that this Fixed Channel is no longer being used. ACL connection will be disconnected - * after kLinkIdleDisconnectTimeout if no other DynamicChannel is connected or no other Fixed - * Channel is using this ACL connection. However a module can still receive data on this channel - * as long as it remains open. - */ - void Release(); - - /** - * This method will retrieve the data channel queue to send and receive packets. - * - * {@see BidiQueueEnd} - * - * @return The upper end of a bi-directional queue. - */ - common::BidiQueueEnd<packet::BasePacketBuilder, packet::PacketView<packet::kLittleEndian>>* - GetQueueUpEnd() const; - - /** - * Get the Proxy for L2CAP Link Options. - * Only few special L2CAP users need to use it, including - * GATT, HID Device, Security Manager, and Java API. - */ - LinkOptions* GetLinkOptions(); - -private: - std::shared_ptr<internal::FixedChannelImpl> impl_; - os::Handler* l2cap_handler_; -}; - -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/fixed_channel_manager.cc b/system/gd/l2cap/le/fixed_channel_manager.cc deleted file mode 100644 index 29ae1c6b6c..0000000000 --- a/system/gd/l2cap/le/fixed_channel_manager.cc +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/le/fixed_channel_manager.h" - -#include "l2cap/le/internal/fixed_channel_service_impl.h" -#include "l2cap/le/internal/fixed_channel_service_manager_impl.h" -#include "l2cap/le/internal/link_manager.h" - -namespace bluetooth { -namespace l2cap { -namespace le { - -bool FixedChannelManager::ConnectServices(hci::AddressWithType address_with_type, - OnConnectionFailureCallback on_fail_callback, - os::Handler* handler) { - internal::LinkManager::PendingFixedChannelConnection pending_fixed_channel_connection{ - .handler_ = handler, - .on_fail_callback_ = std::move(on_fail_callback), - }; - l2cap_layer_handler_->Post(common::BindOnce(&internal::LinkManager::ConnectFixedChannelServices, - common::Unretained(link_manager_), address_with_type, - std::move(pending_fixed_channel_connection))); - return true; -} - -bool FixedChannelManager::RegisterService(Cid cid, - OnRegistrationCompleteCallback on_registration_complete, - OnConnectionOpenCallback on_connection_open, - os::Handler* handler) { - internal::FixedChannelServiceImpl::PendingRegistration pending_registration{ - .user_handler_ = handler, - .on_registration_complete_callback_ = std::move(on_registration_complete), - .on_connection_open_callback_ = std::move(on_connection_open)}; - l2cap_layer_handler_->Post(common::BindOnce(&internal::FixedChannelServiceManagerImpl::Register, - common::Unretained(service_manager_), cid, - std::move(pending_registration))); - return true; -} - -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/fixed_channel_manager.h b/system/gd/l2cap/le/fixed_channel_manager.h deleted file mode 100644 index 9c7c893305..0000000000 --- a/system/gd/l2cap/le/fixed_channel_manager.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright 2019 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. - */ -#pragma once - -#include <string> - -#include "hci/address_with_type.h" -#include "l2cap/cid.h" -#include "l2cap/le/fixed_channel.h" -#include "l2cap/le/fixed_channel_service.h" -#include "os/handler.h" - -namespace bluetooth { -namespace l2cap { -namespace le { - -class L2capLeModule; - -namespace internal { -class LinkManager; -class FixedChannelServiceManagerImpl; -} // namespace internal - -class FixedChannelManager { -public: - FixedChannelManager(const FixedChannelManager&) = delete; - FixedChannelManager& operator=(const FixedChannelManager&) = delete; - - enum class ConnectionResultCode { - SUCCESS = 0, - FAIL_NO_SERVICE_REGISTERED = 1, // No service is registered - FAIL_ALL_SERVICES_HAVE_CHANNEL = 2, // All registered services already have a channel - FAIL_HCI_ERROR = 3, // See hci_error - }; - - struct ConnectionResult { - ConnectionResultCode connection_result_code = ConnectionResultCode::SUCCESS; - hci::ErrorCode hci_error = hci::ErrorCode::SUCCESS; - }; - /** - * OnConnectionFailureCallback(ConnectionResult failure_reason); - */ - using OnConnectionFailureCallback = common::OnceCallback<void(ConnectionResult)>; - - /** - * OnConnectionOpenCallback(FixedChannel channel); - */ - using OnConnectionOpenCallback = common::Callback<void(std::unique_ptr<FixedChannel>)>; - - enum class RegistrationResult { - SUCCESS = 0, - FAIL_DUPLICATE_SERVICE = 1, // Duplicate service registration for the same CID - FAIL_INVALID_SERVICE = 2, // Invalid CID - }; - - /** - * OnRegistrationFailureCallback(RegistrationResult result, FixedChannelService service); - */ - using OnRegistrationCompleteCallback = - common::OnceCallback<void(RegistrationResult, std::unique_ptr<FixedChannelService>)>; - - /** - * Connect to ALL fixed channels on a remote device - * - * - This method is asynchronous - * - When false is returned, the connection fails immediately - * - When true is returned, method caller should wait for on_fail_callback or on_open_callback - * registered through RegisterService() API. - * - If an ACL connection does not exist, this method will create an ACL connection. As a result, - * on_open_callback supplied through RegisterService() will be triggered to provide the actual - * FixedChannel objects - * - If HCI connection failed, on_fail_callback will be triggered with FAIL_HCI_ERROR - * - If fixed channel on a remote device is already reported as connected via on_open_callback and - * has been acquired via FixedChannel#Acquire() API, it won't be reported again - * - If no service is registered, on_fail_callback will be triggered with - * FAIL_NO_SERVICE_REGISTERED - * - If there is an ACL connection and channels for each service is allocated, on_fail_callback - * will be triggered with FAIL_ALL_SERVICES_HAVE_CHANNEL - * - * NOTE: - * This call will initiate an effort to connect all fixed channel services on a remote device. - * Due to the connectionless nature of fixed channels, all fixed channels will be connected - * together. If a fixed channel service does not need a particular fixed channel. It should - * release the received channel immediately after receiving on_open_callback via - * FixedChannel#Release() - * - * A module calling ConnectServices() must have called RegisterService() before. - * The callback will come back from on_open_callback in the service that is registered - * - * @param address_with_type: Remote device with type to make this connection. - * @param address_type: Address type of remote device - * @param on_fail_callback: A callback to indicate connection failure along with a status code. - * @param handler: The handler context in which to execute the @callback parameters. - * - * Returns: true if connection was able to be initiated, false otherwise. - */ - bool ConnectServices(hci::AddressWithType address_with_type, - OnConnectionFailureCallback on_fail_callback, os::Handler* handler); - - /** - * Register a service to receive incoming connections bound to a specific channel. - * - * - This method is asynchronous. - * - When false is returned, the registration fails immediately. - * - When true is returned, method caller should wait for on_service_registered callback that - * contains a FixedChannelService object. The registered service can be managed from that object. - * - If a CID is already registered or some other error happens, on_registration_complete will be - * triggered with a non-SUCCESS value - * - After a service is registered, any LE ACL connection will create a FixedChannel object that - * is delivered through on_open_callback - * - on_open_callback, will only be triggered after on_service_registered callback - * - * @param cid: cid used to receive incoming connections - * @param on_registration_complete: A callback to indicate the service setup has completed. If the - * return status is not SUCCESS, it means service is not registered due to reasons like CID - * already take - * @param on_open_callback: A callback to indicate success of a connection initiated from a remote - * device. - * @param handler: The handler context in which to execute the @callback parameter. - */ - bool RegisterService(Cid cid, OnRegistrationCompleteCallback on_registration_complete, - OnConnectionOpenCallback on_connection_open, os::Handler* handler); - - friend class L2capLeModule; - -private: - // The constructor is not to be used by user code - FixedChannelManager(internal::FixedChannelServiceManagerImpl* service_manager, - internal::LinkManager* link_manager, os::Handler* l2cap_layer_handler) - : service_manager_(service_manager), - link_manager_(link_manager), - l2cap_layer_handler_(l2cap_layer_handler) {} - internal::FixedChannelServiceManagerImpl* service_manager_ = nullptr; - internal::LinkManager* link_manager_ = nullptr; - os::Handler* l2cap_layer_handler_ = nullptr; -}; - -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/fixed_channel_service.cc b/system/gd/l2cap/le/fixed_channel_service.cc deleted file mode 100644 index ad7de59b0c..0000000000 --- a/system/gd/l2cap/le/fixed_channel_service.cc +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/le/fixed_channel_service.h" - -#include "l2cap/le/internal/fixed_channel_service_manager_impl.h" - -namespace bluetooth { -namespace l2cap { -namespace le { - -void FixedChannelService::Unregister(OnUnregisteredCallback on_unregistered, - os::Handler* on_unregistered_handler) { - log::assert_that(manager_ != nullptr, "this service is invalid"); - l2cap_layer_handler_->Post(common::BindOnce(&internal::FixedChannelServiceManagerImpl::Unregister, - common::Unretained(manager_), cid_, - std::move(on_unregistered), on_unregistered_handler)); -} - -} // namespace le -} // namespace l2cap -} // namespace bluetooth
\ No newline at end of file diff --git a/system/gd/l2cap/le/fixed_channel_service.h b/system/gd/l2cap/le/fixed_channel_service.h deleted file mode 100644 index fbee65fd74..0000000000 --- a/system/gd/l2cap/le/fixed_channel_service.h +++ /dev/null @@ -1,61 +0,0 @@ - -/* - * Copyright 2019 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. - */ -#pragma once - -#include "common/callback.h" -#include "hci/address.h" -#include "l2cap/cid.h" -#include "os/handler.h" - -namespace bluetooth { -namespace l2cap { -namespace le { - -namespace internal { -class FixedChannelServiceManagerImpl; -} - -class FixedChannelService { -public: - FixedChannelService() = default; - FixedChannelService(const FixedChannelService&) = delete; - FixedChannelService& operator=(const FixedChannelService&) = delete; - - using OnUnregisteredCallback = common::OnceCallback<void()>; - - /** - * Unregister a service from L2CAP module. This operation cannot fail. - * All channels opened for this service will be invalidated. - * - * @param on_unregistered will be triggered when unregistration is complete - */ - void Unregister(OnUnregisteredCallback on_unregistered, os::Handler* on_unregistered_handler); - - friend internal::FixedChannelServiceManagerImpl; - -private: - FixedChannelService(Cid cid, internal::FixedChannelServiceManagerImpl* manager, - os::Handler* handler) - : cid_(cid), manager_(manager), l2cap_layer_handler_(handler) {} - Cid cid_ = kInvalidCid; - internal::FixedChannelServiceManagerImpl* manager_ = nullptr; - os::Handler* l2cap_layer_handler_; -}; - -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/internal/dynamic_channel_service_impl.h b/system/gd/l2cap/le/internal/dynamic_channel_service_impl.h deleted file mode 100644 index 16e9a2005c..0000000000 --- a/system/gd/l2cap/le/internal/dynamic_channel_service_impl.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include "common/bind.h" -#include "l2cap/le/dynamic_channel.h" -#include "l2cap/le/dynamic_channel_configuration_option.h" -#include "l2cap/le/dynamic_channel_manager.h" -#include "l2cap/le/dynamic_channel_service.h" -#include "l2cap/le/security_policy.h" - -namespace bluetooth { -namespace l2cap { -namespace le { -namespace internal { -class DynamicChannelServiceImpl { -public: - virtual ~DynamicChannelServiceImpl() = default; - - struct PendingRegistration { - os::Handler* user_handler_ = nullptr; - SecurityPolicy security_policy_; - DynamicChannelManager::OnRegistrationCompleteCallback on_registration_complete_callback_; - DynamicChannelManager::OnConnectionOpenCallback on_connection_open_callback_; - DynamicChannelConfigurationOption configuration_; - }; - - virtual void NotifyChannelCreation(std::unique_ptr<DynamicChannel> channel) { - user_handler_->Post(common::BindOnce(on_connection_open_callback_, std::move(channel))); - } - - DynamicChannelConfigurationOption GetConfigOption() const { return config_option_; } - - SecurityPolicy GetSecurityPolicy() { return security_policy_; } - - friend class DynamicChannelServiceManagerImpl; - -protected: - // protected access for mocking - DynamicChannelServiceImpl( - os::Handler* user_handler, - DynamicChannelManager::OnConnectionOpenCallback on_connection_open_callback, - DynamicChannelConfigurationOption config_option, SecurityPolicy security_policy) - : user_handler_(user_handler), - on_connection_open_callback_(std::move(on_connection_open_callback)), - config_option_(config_option), - security_policy_(security_policy) {} - -private: - os::Handler* user_handler_ = nullptr; - DynamicChannelManager::OnConnectionOpenCallback on_connection_open_callback_; - DynamicChannelConfigurationOption config_option_; - SecurityPolicy security_policy_; -}; - -} // namespace internal -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/internal/dynamic_channel_service_impl_mock.h b/system/gd/l2cap/le/internal/dynamic_channel_service_impl_mock.h deleted file mode 100644 index c4573e990a..0000000000 --- a/system/gd/l2cap/le/internal/dynamic_channel_service_impl_mock.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2020 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. - */ -#pragma once - -#include <gmock/gmock.h> - -#include "l2cap/le/internal/dynamic_channel_service_impl.h" - -// Unit test interfaces -namespace bluetooth { -namespace l2cap { -namespace le { -namespace internal { -namespace testing { - -class MockDynamicChannelServiceImpl : public DynamicChannelServiceImpl { -public: - MOCK_METHOD(SecurityPolicy, GetSecurityPolicy, (), (const, override)); -}; - -} // namespace testing -} // namespace internal -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/internal/dynamic_channel_service_manager_impl.cc b/system/gd/l2cap/le/internal/dynamic_channel_service_manager_impl.cc deleted file mode 100644 index 80be1b39fd..0000000000 --- a/system/gd/l2cap/le/internal/dynamic_channel_service_manager_impl.cc +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/le/internal/dynamic_channel_service_manager_impl.h" - -#include <bluetooth/log.h> - -#include "common/bind.h" -#include "l2cap/le/internal/dynamic_channel_service_impl.h" -#include "l2cap/psm.h" -#include "os/log.h" - -namespace bluetooth { -namespace l2cap { -namespace le { -namespace internal { - -void DynamicChannelServiceManagerImpl::Register( - Psm psm, DynamicChannelServiceImpl::PendingRegistration pending_registration) { - if (IsServiceRegistered(psm)) { - std::unique_ptr<DynamicChannelService> invalid_service(new DynamicChannelService()); - pending_registration.user_handler_->Post( - common::BindOnce(std::move(pending_registration.on_registration_complete_callback_), - DynamicChannelManager::RegistrationResult::FAIL_DUPLICATE_SERVICE, - std::move(invalid_service))); - } else { - service_map_.try_emplace( - psm, - DynamicChannelServiceImpl(pending_registration.user_handler_, - std::move(pending_registration.on_connection_open_callback_), - pending_registration.configuration_, - pending_registration.security_policy_)); - std::unique_ptr<DynamicChannelService> user_service( - new DynamicChannelService(psm, this, l2cap_layer_handler_)); - pending_registration.user_handler_->Post(common::BindOnce( - std::move(pending_registration.on_registration_complete_callback_), - DynamicChannelManager::RegistrationResult::SUCCESS, std::move(user_service))); - } -} - -void DynamicChannelServiceManagerImpl::Unregister( - Psm psm, DynamicChannelService::OnUnregisteredCallback callback, os::Handler* handler) { - if (IsServiceRegistered(psm)) { - service_map_.erase(psm); - handler->Post(std::move(callback)); - } else { - log::error("service not registered psm:{}", psm); - } -} - -bool DynamicChannelServiceManagerImpl::IsServiceRegistered(Psm psm) const { - return service_map_.find(psm) != service_map_.end(); -} - -DynamicChannelServiceImpl* DynamicChannelServiceManagerImpl::GetService(Psm psm) { - log::assert_that(IsServiceRegistered(psm), "assert failed: IsServiceRegistered(psm)"); - return &service_map_.find(psm)->second; -} - -std::vector<std::pair<Psm, DynamicChannelServiceImpl*>> -DynamicChannelServiceManagerImpl::GetRegisteredServices() { - std::vector<std::pair<Psm, DynamicChannelServiceImpl*>> results; - for (auto& elem : service_map_) { - results.emplace_back(elem.first, &elem.second); - } - return results; -} - -} // namespace internal -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/internal/dynamic_channel_service_manager_impl.h b/system/gd/l2cap/le/internal/dynamic_channel_service_manager_impl.h deleted file mode 100644 index 28a4f9830f..0000000000 --- a/system/gd/l2cap/le/internal/dynamic_channel_service_manager_impl.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <unordered_map> - -#include "l2cap/le/dynamic_channel_service.h" -#include "l2cap/le/internal/dynamic_channel_service_impl.h" -#include "l2cap/le/security_enforcement_interface.h" -#include "l2cap/psm.h" -#include "os/handler.h" - -namespace bluetooth { -namespace l2cap { -namespace le { -namespace internal { - -class DynamicChannelServiceManagerImpl { -public: - explicit DynamicChannelServiceManagerImpl(os::Handler* l2cap_layer_handler) - : l2cap_layer_handler_(l2cap_layer_handler) {} - - virtual ~DynamicChannelServiceManagerImpl() = default; - // - // All APIs must be invoked in L2CAP layer handler - // - virtual void Register(Psm psm, - DynamicChannelServiceImpl::PendingRegistration pending_registration); - virtual void Unregister(Psm psm, DynamicChannelService::OnUnregisteredCallback callback, - os::Handler* handler); - virtual bool IsServiceRegistered(Psm psm) const; - virtual DynamicChannelServiceImpl* GetService(Psm psm); - - virtual std::vector<std::pair<Psm, DynamicChannelServiceImpl*>> GetRegisteredServices(); - - // Implementation is set by SecurityManager through L2capModule - void SetSecurityEnforcementInterface(SecurityEnforcementInterface* impl) { - security_enforcement_interface_ = impl; - } - - SecurityEnforcementInterface* GetSecurityEnforcementInterface() { - return security_enforcement_interface_; - } - -private: - os::Handler* l2cap_layer_handler_ = nullptr; - std::unordered_map<Psm, DynamicChannelServiceImpl> service_map_; - SecurityEnforcementInterface* security_enforcement_interface_; -}; -} // namespace internal -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/internal/dynamic_channel_service_manager_test.cc b/system/gd/l2cap/le/internal/dynamic_channel_service_manager_test.cc deleted file mode 100644 index 87a5153bca..0000000000 --- a/system/gd/l2cap/le/internal/dynamic_channel_service_manager_test.cc +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2018 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 <future> - -#include "common/bind.h" -#include "l2cap/cid.h" -#include "l2cap/le/dynamic_channel_manager.h" -#include "l2cap/le/dynamic_channel_service.h" -#include "l2cap/le/internal/dynamic_channel_service_manager_impl.h" -#include "os/handler.h" -#include "os/thread.h" - -namespace bluetooth { -namespace l2cap { -namespace le { -namespace internal { - -class L2capLeDynamicServiceManagerTest : public ::testing::Test { -public: - ~L2capLeDynamicServiceManagerTest() = default; - - void OnServiceRegistered(bool expect_success, DynamicChannelManager::RegistrationResult result, - std::unique_ptr<DynamicChannelService> user_service) { - EXPECT_EQ(result == DynamicChannelManager::RegistrationResult::SUCCESS, expect_success); - service_registered_ = expect_success; - } - -protected: - void SetUp() override { - thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL); - user_handler_ = new os::Handler(thread_); - l2cap_handler_ = new os::Handler(thread_); - manager_ = new DynamicChannelServiceManagerImpl{l2cap_handler_}; - } - - void TearDown() override { - delete manager_; - l2cap_handler_->Clear(); - delete l2cap_handler_; - user_handler_->Clear(); - delete user_handler_; - delete thread_; - } - - void sync_user_handler() { - std::promise<void> promise; - auto future = promise.get_future(); - user_handler_->Post( - common::BindOnce(&std::promise<void>::set_value, common::Unretained(&promise))); - future.wait_for(std::chrono::milliseconds(3)); - } - - DynamicChannelServiceManagerImpl* manager_ = nullptr; - os::Thread* thread_ = nullptr; - os::Handler* user_handler_ = nullptr; - os::Handler* l2cap_handler_ = nullptr; - - bool service_registered_ = false; -}; - -TEST_F(L2capLeDynamicServiceManagerTest, register_and_unregister_le_dynamic_channel) { - DynamicChannelServiceImpl::PendingRegistration pending_registration{ - .user_handler_ = user_handler_, - .security_policy_ = SecurityPolicy::NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK, - .on_registration_complete_callback_ = - common::BindOnce(&L2capLeDynamicServiceManagerTest::OnServiceRegistered, - common::Unretained(this), true)}; - Psm psm = 0x41; - EXPECT_FALSE(manager_->IsServiceRegistered(psm)); - manager_->Register(psm, std::move(pending_registration)); - EXPECT_TRUE(manager_->IsServiceRegistered(psm)); - sync_user_handler(); - EXPECT_TRUE(service_registered_); - manager_->Unregister(psm, common::BindOnce([] {}), user_handler_); - EXPECT_FALSE(manager_->IsServiceRegistered(psm)); -} - -TEST_F(L2capLeDynamicServiceManagerTest, register_le_dynamic_channel_even_number_psm) { - DynamicChannelServiceImpl::PendingRegistration pending_registration{ - .user_handler_ = user_handler_, - .security_policy_ = SecurityPolicy::NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK, - .on_registration_complete_callback_ = - common::BindOnce(&L2capLeDynamicServiceManagerTest::OnServiceRegistered, - common::Unretained(this), true)}; - Psm psm = 0x0100; - EXPECT_FALSE(manager_->IsServiceRegistered(psm)); - manager_->Register(psm, std::move(pending_registration)); - EXPECT_TRUE(manager_->IsServiceRegistered(psm)); - sync_user_handler(); - EXPECT_TRUE(service_registered_); -} - -} // namespace internal -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/internal/fixed_channel_impl.cc b/system/gd/l2cap/le/internal/fixed_channel_impl.cc deleted file mode 100644 index 5a9dbbecf8..0000000000 --- a/system/gd/l2cap/le/internal/fixed_channel_impl.cc +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/le/internal/fixed_channel_impl.h" - -#include <bluetooth/log.h> - -#include <unordered_map> - -#include "hci/acl_manager/le_acl_connection.h" -#include "l2cap/cid.h" -#include "l2cap/le/internal/link.h" -#include "os/handler.h" -#include "os/log.h" - -namespace bluetooth { -namespace l2cap { -namespace le { -namespace internal { - -hci::Role FixedChannelImpl::GetRole() const { return link_->GetRole(); } - -hci::acl_manager::LeAclConnection* FixedChannelImpl::GetAclConnection() const { - return link_->GetAclConnection(); -} - -FixedChannelImpl::FixedChannelImpl(Cid cid, Link* link, os::Handler* l2cap_handler) - : cid_(cid), device_(link->GetDevice()), link_(link), l2cap_handler_(l2cap_handler) { - log::assert_that(cid_ >= kFirstFixedChannel && cid_ <= kLastFixedChannel, "Invalid cid: {}", - cid_); - log::assert_that(link_ != nullptr, "assert failed: link_ != nullptr"); - log::assert_that(l2cap_handler_ != nullptr, "assert failed: l2cap_handler_ != nullptr"); -} - -void FixedChannelImpl::RegisterOnCloseCallback(os::Handler* user_handler, - FixedChannel::OnCloseCallback on_close_callback) { - log::assert_that(user_handler_ == nullptr, "OnCloseCallback can only be registered once"); - // If channel is already closed, call the callback immediately without saving it - if (closed_) { - user_handler->Post(common::BindOnce(std::move(on_close_callback), close_reason_)); - return; - } - user_handler_ = user_handler; - on_close_callback_ = std::move(on_close_callback); -} - -void FixedChannelImpl::OnClosed(hci::ErrorCode status) { - log::assert_that(!closed_, - "Device {} Cid 0x{:x} closed twice, old status 0x{:x}, new status 0x{:x}", - ADDRESS_TO_LOGGABLE_CSTR(device_), cid_, static_cast<int>(close_reason_), - static_cast<int>(status)); - closed_ = true; - close_reason_ = status; - acquired_ = false; - link_ = nullptr; - l2cap_handler_ = nullptr; - if (user_handler_ == nullptr) { - return; - } - // On close callback can only be called once - user_handler_->Post(common::BindOnce(std::move(on_close_callback_), status)); - user_handler_ = nullptr; - on_close_callback_.Reset(); -} - -void FixedChannelImpl::Acquire() { - log::assert_that(user_handler_ != nullptr, - "Must register OnCloseCallback before calling any methods"); - if (closed_) { - log::warn("{} is already closed", ToRedactedStringForLogging()); - log::assert_that(!acquired_, "assert failed: !acquired_"); - return; - } - if (acquired_) { - log::info("{} was already acquired", ToRedactedStringForLogging()); - return; - } - acquired_ = true; - link_->RefreshRefCount(); -} - -void FixedChannelImpl::Release() { - log::assert_that(user_handler_ != nullptr, - "Must register OnCloseCallback before calling any methods"); - if (closed_) { - log::warn("{} is already closed", ToRedactedStringForLogging()); - log::assert_that(!acquired_, "assert failed: !acquired_"); - return; - } - if (!acquired_) { - log::info("{} was already released", ToRedactedStringForLogging()); - return; - } - acquired_ = false; - link_->RefreshRefCount(); -} - -Cid FixedChannelImpl::GetCid() const { return cid_; } - -Cid FixedChannelImpl::GetRemoteCid() const { return cid_; } - -LinkOptions* FixedChannelImpl::GetLinkOptions() { return link_->GetLinkOptions(); } - -} // namespace internal -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/internal/fixed_channel_impl.h b/system/gd/l2cap/le/internal/fixed_channel_impl.h deleted file mode 100644 index 12948d14c5..0000000000 --- a/system/gd/l2cap/le/internal/fixed_channel_impl.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include "common/bidi_queue.h" -#include "common/interfaces/ILoggable.h" -#include "hci/acl_manager/le_acl_connection.h" -#include "l2cap/cid.h" -#include "l2cap/internal/channel_impl.h" -#include "l2cap/le/fixed_channel.h" -#include "l2cap/le/link_options.h" -#include "os/handler.h" -#include "os/log.h" -namespace bluetooth { -namespace l2cap { -namespace le { -namespace internal { - -class Link; - -class FixedChannelImpl : public l2cap::internal::ChannelImpl, - public bluetooth::common::IRedactableLoggable { -public: - FixedChannelImpl(Cid cid, Link* link, os::Handler* l2cap_handler); - - FixedChannelImpl(const FixedChannelImpl&) = delete; - FixedChannelImpl& operator=(const FixedChannelImpl&) = delete; - - virtual ~FixedChannelImpl() = default; - - hci::AddressWithType GetDevice() const { return device_; } - - /* Return the role we have in the associated link */ - virtual hci::Role GetRole() const; - - virtual hci::acl_manager::LeAclConnection* GetAclConnection() const; - - virtual void RegisterOnCloseCallback(os::Handler* user_handler, - FixedChannel::OnCloseCallback on_close_callback); - - virtual void Acquire(); - - virtual void Release(); - - virtual bool IsAcquired() const { return acquired_; } - - Cid GetCid() const override; - Cid GetRemoteCid() const override; - virtual void OnClosed(hci::ErrorCode status); - - virtual std::string ToString() { - std::ostringstream ss; - ss << "Device " << device_ << " Cid 0x" << std::hex << cid_; - return ss.str(); - } - - std::string ToStringForLogging() const override { - std::ostringstream ss; - ss << "Device " << device_.ToStringForLogging() << " Cid 0x" << std::hex << cid_; - return ss.str(); - } - - std::string ToRedactedStringForLogging() const override { - std::ostringstream ss; - ss << "Device " << device_.ToRedactedStringForLogging() << " Cid 0x" << std::hex << cid_; - return ss.str(); - } - - common::BidiQueueEnd<packet::BasePacketBuilder, packet::PacketView<packet::kLittleEndian>>* - GetQueueUpEnd() { - return channel_queue_.GetUpEnd(); - } - - common::BidiQueueEnd<packet::PacketView<packet::kLittleEndian>, packet::BasePacketBuilder>* - GetQueueDownEnd() { - return channel_queue_.GetDownEnd(); - } - - LinkOptions* GetLinkOptions(); - -private: - // Constructor states - // For logging purpose only - const Cid cid_; - // For logging purpose only - const hci::AddressWithType device_; - // Needed to handle Acquire() and Release() - Link* link_; - os::Handler* l2cap_handler_; - - // User supported states - os::Handler* user_handler_ = nullptr; - FixedChannel::OnCloseCallback on_close_callback_{}; - - // Internal states - bool acquired_ = false; - bool closed_ = false; - hci::ErrorCode close_reason_ = hci::ErrorCode::SUCCESS; - static constexpr size_t kChannelQueueSize = 10; - common::BidiQueue<packet::PacketView<packet::kLittleEndian>, packet::BasePacketBuilder> - channel_queue_{kChannelQueueSize}; -}; - -} // namespace internal -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/internal/fixed_channel_impl_mock.h b/system/gd/l2cap/le/internal/fixed_channel_impl_mock.h deleted file mode 100644 index 084e657b36..0000000000 --- a/system/gd/l2cap/le/internal/fixed_channel_impl_mock.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2019 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. - */ -#pragma once - -#include <gmock/gmock.h> - -#include "l2cap/le/internal/fixed_channel_impl.h" - -// Unit test interfaces -namespace bluetooth { -namespace l2cap { -namespace le { -namespace internal { -namespace testing { - -class MockFixedChannelImpl : public FixedChannelImpl { -public: - MOCK_METHOD(void, RegisterOnCloseCallback, - (os::Handler * user_handler, FixedChannel::OnCloseCallback on_close_callback), - (override)); - MOCK_METHOD(void, Acquire, (), (override)); - MOCK_METHOD(void, Release, (), (override)); - MOCK_METHOD(bool, IsAcquired, (), (override, const)); - MOCK_METHOD(void, OnClosed, (hci::ErrorCode status), (override)); -}; - -} // namespace testing -} // namespace internal -} // namespace le -} // namespace l2cap -} // namespace bluetooth
\ No newline at end of file diff --git a/system/gd/l2cap/le/internal/fixed_channel_impl_test.cc b/system/gd/l2cap/le/internal/fixed_channel_impl_test.cc deleted file mode 100644 index 761b7742f1..0000000000 --- a/system/gd/l2cap/le/internal/fixed_channel_impl_test.cc +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/le/internal/fixed_channel_impl.h" - -#include <bluetooth/log.h> -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include "common/testing/bind_test_util.h" -#include "hci/address_with_type.h" -#include "l2cap/cid.h" -#include "l2cap/internal/parameter_provider_mock.h" -#include "l2cap/le/internal/link_mock.h" -#include "os/handler.h" - -namespace bluetooth { -namespace l2cap { -namespace le { -namespace internal { - -using hci::Address; -using hci::AddressWithType; -using l2cap::internal::testing::MockParameterProvider; -using testing::MockLink; -using ::testing::Return; - -class L2capLeFixedChannelImplTest : public ::testing::Test { -public: - static void SyncHandler(os::Handler* handler) { - std::promise<void> promise; - auto future = promise.get_future(); - handler->Post(common::BindOnce(&std::promise<void>::set_value, common::Unretained(&promise))); - future.wait_for(std::chrono::milliseconds(3)); - } - -protected: - void SetUp() override { - thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL); - l2cap_handler_ = new os::Handler(thread_); - } - - void TearDown() override { - l2cap_handler_->Clear(); - delete l2cap_handler_; - delete thread_; - } - - os::Thread* thread_ = nullptr; - os::Handler* l2cap_handler_ = nullptr; -}; - -TEST_F(L2capLeFixedChannelImplTest, get_device) { - MockParameterProvider mock_parameter_provider; - EXPECT_CALL(mock_parameter_provider, GetLeLinkIdleDisconnectTimeout()).Times(1); - testing::MockLeAclConnection* mock_acl_connection = new testing::MockLeAclConnection(); - EXPECT_CALL(*mock_acl_connection, GetRemoteAddress()).Times(1); - MockLink mock_le_link(l2cap_handler_, &mock_parameter_provider, - std::unique_ptr<testing::MockLeAclConnection>(mock_acl_connection), - nullptr /* LinkManager* */); - AddressWithType device{{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::PUBLIC_DEVICE_ADDRESS}; - EXPECT_CALL(mock_le_link, GetDevice()).WillRepeatedly(Return(device)); - log::info("------------------"); - FixedChannelImpl fixed_channel_impl(kSmpBrCid, &mock_le_link, l2cap_handler_); - EXPECT_EQ(device, fixed_channel_impl.GetDevice()); -} - -TEST_F(L2capLeFixedChannelImplTest, close_triggers_callback) { - MockParameterProvider mock_parameter_provider; - EXPECT_CALL(mock_parameter_provider, GetLeLinkIdleDisconnectTimeout()).Times(1); - testing::MockLeAclConnection* mock_acl_connection = new testing::MockLeAclConnection(); - EXPECT_CALL(*mock_acl_connection, GetRemoteAddress()).Times(1); - MockLink mock_le_link(l2cap_handler_, &mock_parameter_provider, - std::unique_ptr<testing::MockLeAclConnection>(mock_acl_connection), - nullptr /* LinkManager* */); - AddressWithType device{{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::PUBLIC_DEVICE_ADDRESS}; - EXPECT_CALL(mock_le_link, GetDevice()).WillRepeatedly(Return(device)); - FixedChannelImpl fixed_channel_impl(kSmpBrCid, &mock_le_link, l2cap_handler_); - - // Register on close callback - auto user_handler = std::make_unique<os::Handler>(thread_); - hci::ErrorCode my_status = hci::ErrorCode::SUCCESS; - fixed_channel_impl.RegisterOnCloseCallback( - user_handler.get(), common::testing::BindLambdaForTesting( - [&](hci::ErrorCode status) { my_status = status; })); - - // Channel closure should trigger such callback - fixed_channel_impl.OnClosed(hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION); - SyncHandler(user_handler.get()); - EXPECT_EQ(hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION, my_status); - - user_handler->Clear(); -} - -TEST_F(L2capLeFixedChannelImplTest, register_callback_after_close_should_call_immediately) { - MockParameterProvider mock_parameter_provider; - EXPECT_CALL(mock_parameter_provider, GetLeLinkIdleDisconnectTimeout()).Times(1); - testing::MockLeAclConnection* mock_acl_connection = new testing::MockLeAclConnection(); - EXPECT_CALL(*mock_acl_connection, GetRemoteAddress()).Times(1); - MockLink mock_le_link(l2cap_handler_, &mock_parameter_provider, - std::unique_ptr<testing::MockLeAclConnection>(mock_acl_connection), - nullptr /* LinkManager* */); - AddressWithType device{{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::PUBLIC_DEVICE_ADDRESS}; - EXPECT_CALL(mock_le_link, GetDevice()).WillRepeatedly(Return(device)); - FixedChannelImpl fixed_channel_impl(kSmpBrCid, &mock_le_link, l2cap_handler_); - - // Channel closure should do nothing - fixed_channel_impl.OnClosed(hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION); - - // Register on close callback should trigger callback immediately - auto user_handler = std::make_unique<os::Handler>(thread_); - hci::ErrorCode my_status = hci::ErrorCode::SUCCESS; - fixed_channel_impl.RegisterOnCloseCallback( - user_handler.get(), common::testing::BindLambdaForTesting( - [&](hci::ErrorCode status) { my_status = status; })); - SyncHandler(user_handler.get()); - EXPECT_EQ(hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION, my_status); - - user_handler->Clear(); -} - -TEST_F(L2capLeFixedChannelImplTest, close_twice_should_fail) { - MockParameterProvider mock_parameter_provider; - EXPECT_CALL(mock_parameter_provider, GetLeLinkIdleDisconnectTimeout()).Times(1); - testing::MockLeAclConnection* mock_acl_connection = new testing::MockLeAclConnection(); - EXPECT_CALL(*mock_acl_connection, GetRemoteAddress()).Times(1); - MockLink mock_le_link(l2cap_handler_, &mock_parameter_provider, - std::unique_ptr<testing::MockLeAclConnection>(mock_acl_connection), - nullptr /* LinkManager* */); - AddressWithType device{{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::PUBLIC_DEVICE_ADDRESS}; - EXPECT_CALL(mock_le_link, GetDevice()).WillRepeatedly(Return(device)); - FixedChannelImpl fixed_channel_impl(kSmpBrCid, &mock_le_link, l2cap_handler_); - - // Register on close callback - auto user_handler = std::make_unique<os::Handler>(thread_); - hci::ErrorCode my_status = hci::ErrorCode::SUCCESS; - fixed_channel_impl.RegisterOnCloseCallback( - user_handler.get(), common::testing::BindLambdaForTesting( - [&](hci::ErrorCode status) { my_status = status; })); - - // Channel closure should trigger such callback - fixed_channel_impl.OnClosed(hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION); - SyncHandler(user_handler.get()); - EXPECT_EQ(hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION, my_status); - - // 2nd OnClose() callback should fail - EXPECT_DEATH(fixed_channel_impl.OnClosed(hci::ErrorCode::PAGE_TIMEOUT), ".*OnClosed.*"); - - user_handler->Clear(); -} - -TEST_F(L2capLeFixedChannelImplTest, multiple_registeration_should_fail) { - MockParameterProvider mock_parameter_provider; - EXPECT_CALL(mock_parameter_provider, GetLeLinkIdleDisconnectTimeout()).Times(1); - testing::MockLeAclConnection* mock_acl_connection = new testing::MockLeAclConnection(); - EXPECT_CALL(*mock_acl_connection, GetRemoteAddress()).Times(1); - MockLink mock_le_link(l2cap_handler_, &mock_parameter_provider, - std::unique_ptr<testing::MockLeAclConnection>(mock_acl_connection), - nullptr /* LinkManager* */); - AddressWithType device{{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::PUBLIC_DEVICE_ADDRESS}; - EXPECT_CALL(mock_le_link, GetDevice()).WillRepeatedly(Return(device)); - FixedChannelImpl fixed_channel_impl(kSmpBrCid, &mock_le_link, l2cap_handler_); - - // Register on close callback - auto user_handler = std::make_unique<os::Handler>(thread_); - hci::ErrorCode my_status = hci::ErrorCode::SUCCESS; - fixed_channel_impl.RegisterOnCloseCallback( - user_handler.get(), common::testing::BindLambdaForTesting( - [&](hci::ErrorCode status) { my_status = status; })); - - EXPECT_DEATH(fixed_channel_impl.RegisterOnCloseCallback( - user_handler.get(), common::BindOnce([](hci::ErrorCode status) { FAIL(); })), - ".*RegisterOnCloseCallback.*"); - - user_handler->Clear(); -} - -TEST_F(L2capLeFixedChannelImplTest, call_acquire_before_registeration_should_fail) { - MockParameterProvider mock_parameter_provider; - EXPECT_CALL(mock_parameter_provider, GetLeLinkIdleDisconnectTimeout()).Times(1); - testing::MockLeAclConnection* mock_acl_connection = new testing::MockLeAclConnection(); - EXPECT_CALL(*mock_acl_connection, GetRemoteAddress()).Times(1); - MockLink mock_le_link(l2cap_handler_, &mock_parameter_provider, - std::unique_ptr<testing::MockLeAclConnection>(mock_acl_connection), - nullptr /* LinkManager* */); - AddressWithType device{{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::PUBLIC_DEVICE_ADDRESS}; - EXPECT_CALL(mock_le_link, GetDevice()).WillRepeatedly(Return(device)); - FixedChannelImpl fixed_channel_impl(kSmpBrCid, &mock_le_link, l2cap_handler_); - EXPECT_DEATH(fixed_channel_impl.Acquire(), ".*Acquire.*"); -} - -TEST_F(L2capLeFixedChannelImplTest, call_release_before_registeration_should_fail) { - MockParameterProvider mock_parameter_provider; - EXPECT_CALL(mock_parameter_provider, GetLeLinkIdleDisconnectTimeout()).Times(1); - testing::MockLeAclConnection* mock_acl_connection = new testing::MockLeAclConnection(); - EXPECT_CALL(*mock_acl_connection, GetRemoteAddress()).Times(1); - MockLink mock_le_link(l2cap_handler_, &mock_parameter_provider, - std::unique_ptr<testing::MockLeAclConnection>(mock_acl_connection), - nullptr /* LinkManager* */); - AddressWithType device{{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::PUBLIC_DEVICE_ADDRESS}; - EXPECT_CALL(mock_le_link, GetDevice()).WillRepeatedly(Return(device)); - FixedChannelImpl fixed_channel_impl(kSmpBrCid, &mock_le_link, l2cap_handler_); - EXPECT_DEATH(fixed_channel_impl.Release(), ".*Release.*"); -} - -TEST_F(L2capLeFixedChannelImplTest, test_acquire_release_channel) { - MockParameterProvider mock_parameter_provider; - EXPECT_CALL(mock_parameter_provider, GetLeLinkIdleDisconnectTimeout()).Times(1); - testing::MockLeAclConnection* mock_acl_connection = new testing::MockLeAclConnection(); - EXPECT_CALL(*mock_acl_connection, GetRemoteAddress()).Times(1); - MockLink mock_le_link(l2cap_handler_, &mock_parameter_provider, - std::unique_ptr<testing::MockLeAclConnection>(mock_acl_connection), - nullptr /* LinkManager* */); - AddressWithType device{{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::PUBLIC_DEVICE_ADDRESS}; - EXPECT_CALL(mock_le_link, GetDevice()).WillRepeatedly(Return(device)); - FixedChannelImpl fixed_channel_impl(kSmpBrCid, &mock_le_link, l2cap_handler_); - - // Register on close callback - auto user_handler = std::make_unique<os::Handler>(thread_); - hci::ErrorCode my_status = hci::ErrorCode::SUCCESS; - fixed_channel_impl.RegisterOnCloseCallback( - user_handler.get(), common::testing::BindLambdaForTesting( - [&](hci::ErrorCode status) { my_status = status; })); - - // Default should be false - EXPECT_FALSE(fixed_channel_impl.IsAcquired()); - - // Should be called 2 times after Acquire() and Release() - EXPECT_CALL(mock_le_link, RefreshRefCount()).Times(2); - - fixed_channel_impl.Acquire(); - EXPECT_TRUE(fixed_channel_impl.IsAcquired()); - - fixed_channel_impl.Release(); - EXPECT_FALSE(fixed_channel_impl.IsAcquired()); - - user_handler->Clear(); -} - -TEST_F(L2capLeFixedChannelImplTest, test_acquire_after_close) { - MockParameterProvider mock_parameter_provider; - EXPECT_CALL(mock_parameter_provider, GetLeLinkIdleDisconnectTimeout()).Times(1); - testing::MockLeAclConnection* mock_acl_connection = new testing::MockLeAclConnection(); - EXPECT_CALL(*mock_acl_connection, GetRemoteAddress()).Times(1); - MockLink mock_le_link(l2cap_handler_, &mock_parameter_provider, - std::unique_ptr<testing::MockLeAclConnection>(mock_acl_connection), - nullptr /* LinkManager* */); - AddressWithType device{{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::PUBLIC_DEVICE_ADDRESS}; - EXPECT_CALL(mock_le_link, GetDevice()).WillRepeatedly(Return(device)); - FixedChannelImpl fixed_channel_impl(kSmpBrCid, &mock_le_link, l2cap_handler_); - - // Register on close callback - auto user_handler = std::make_unique<os::Handler>(thread_); - hci::ErrorCode my_status = hci::ErrorCode::SUCCESS; - fixed_channel_impl.RegisterOnCloseCallback( - user_handler.get(), common::testing::BindLambdaForTesting( - [&](hci::ErrorCode status) { my_status = status; })); - - // Channel closure should trigger such callback - fixed_channel_impl.OnClosed(hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION); - SyncHandler(user_handler.get()); - EXPECT_EQ(hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION, my_status); - - // Release or Acquire after closing should crash - EXPECT_CALL(mock_le_link, RefreshRefCount()).Times(0); - EXPECT_FALSE(fixed_channel_impl.IsAcquired()); - EXPECT_DEATH(fixed_channel_impl.Acquire(), ".*Acquire.*"); - - user_handler->Clear(); -} - -} // namespace internal -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/internal/fixed_channel_service_impl.h b/system/gd/l2cap/le/internal/fixed_channel_service_impl.h deleted file mode 100644 index 8e70214543..0000000000 --- a/system/gd/l2cap/le/internal/fixed_channel_service_impl.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include "l2cap/le/fixed_channel.h" -#include "l2cap/le/fixed_channel_manager.h" -#include "l2cap/le/fixed_channel_service.h" - -namespace bluetooth { -namespace l2cap { -namespace le { -namespace internal { - -class FixedChannelServiceImpl { -public: - virtual ~FixedChannelServiceImpl() = default; - - struct PendingRegistration { - os::Handler* user_handler_ = nullptr; - FixedChannelManager::OnRegistrationCompleteCallback on_registration_complete_callback_; - FixedChannelManager::OnConnectionOpenCallback on_connection_open_callback_; - }; - - virtual void NotifyChannelCreation(std::unique_ptr<FixedChannel> channel) { - user_handler_->Post(common::BindOnce(on_connection_open_callback_, std::move(channel))); - } - - friend class FixedChannelServiceManagerImpl; - -protected: - // protected access for mocking - FixedChannelServiceImpl(os::Handler* user_handler, - FixedChannelManager::OnConnectionOpenCallback on_connection_open_callback) - : user_handler_(user_handler), - on_connection_open_callback_(std::move(on_connection_open_callback)) {} - -private: - os::Handler* user_handler_ = nullptr; - FixedChannelManager::OnConnectionOpenCallback on_connection_open_callback_; -}; - -} // namespace internal -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/internal/fixed_channel_service_impl_mock.h b/system/gd/l2cap/le/internal/fixed_channel_service_impl_mock.h deleted file mode 100644 index f85437102c..0000000000 --- a/system/gd/l2cap/le/internal/fixed_channel_service_impl_mock.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2019 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. - */ -#pragma once - -#include <gmock/gmock.h> - -#include "l2cap/le/internal/fixed_channel_impl.h" -#include "l2cap/le/internal/fixed_channel_service_manager_impl.h" - -// Unit test interfaces -namespace bluetooth { -namespace l2cap { -namespace le { -namespace internal { -namespace testing { - -class MockFixedChannelServiceImpl : public FixedChannelServiceImpl { -public: - MockFixedChannelServiceImpl() - : FixedChannelServiceImpl(nullptr, FixedChannelManager::OnConnectionOpenCallback()) {} - MOCK_METHOD(void, NotifyChannelCreation, (std::unique_ptr<FixedChannel> channel), (override)); -}; - -} // namespace testing -} // namespace internal -} // namespace le -} // namespace l2cap -} // namespace bluetooth
\ No newline at end of file diff --git a/system/gd/l2cap/le/internal/fixed_channel_service_manager_impl.cc b/system/gd/l2cap/le/internal/fixed_channel_service_manager_impl.cc deleted file mode 100644 index dcd0398cee..0000000000 --- a/system/gd/l2cap/le/internal/fixed_channel_service_manager_impl.cc +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/le/internal/fixed_channel_service_manager_impl.h" - -#include <bluetooth/log.h> - -#include "common/bind.h" -#include "l2cap/cid.h" -#include "l2cap/le/internal/fixed_channel_service_impl.h" -#include "os/log.h" - -namespace bluetooth { -namespace l2cap { -namespace le { -namespace internal { - -void FixedChannelServiceManagerImpl::Register( - Cid cid, FixedChannelServiceImpl::PendingRegistration pending_registration) { - if (cid < kFirstFixedChannel || cid > kLastFixedChannel || cid == kLeSignallingCid) { - std::unique_ptr<FixedChannelService> invalid_service(new FixedChannelService()); - pending_registration.user_handler_->Post( - common::BindOnce(std::move(pending_registration.on_registration_complete_callback_), - FixedChannelManager::RegistrationResult::FAIL_INVALID_SERVICE, - std::move(invalid_service))); - } else if (IsServiceRegistered(cid)) { - std::unique_ptr<FixedChannelService> invalid_service(new FixedChannelService()); - pending_registration.user_handler_->Post( - common::BindOnce(std::move(pending_registration.on_registration_complete_callback_), - FixedChannelManager::RegistrationResult::FAIL_DUPLICATE_SERVICE, - std::move(invalid_service))); - } else { - service_map_.try_emplace( - cid, - FixedChannelServiceImpl(pending_registration.user_handler_, - std::move(pending_registration.on_connection_open_callback_))); - std::unique_ptr<FixedChannelService> user_service( - new FixedChannelService(cid, this, l2cap_layer_handler_)); - pending_registration.user_handler_->Post(common::BindOnce( - std::move(pending_registration.on_registration_complete_callback_), - FixedChannelManager::RegistrationResult::SUCCESS, std::move(user_service))); - } -} - -void FixedChannelServiceManagerImpl::Unregister( - Cid cid, FixedChannelService::OnUnregisteredCallback callback, os::Handler* handler) { - if (IsServiceRegistered(cid)) { - service_map_.erase(cid); - handler->Post(std::move(callback)); - } else { - log::error("service not registered cid:{}", cid); - } -} - -bool FixedChannelServiceManagerImpl::IsServiceRegistered(Cid cid) const { - return service_map_.find(cid) != service_map_.end(); -} - -FixedChannelServiceImpl* FixedChannelServiceManagerImpl::GetService(Cid cid) { - log::assert_that(IsServiceRegistered(cid), "assert failed: IsServiceRegistered(cid)"); - return &service_map_.find(cid)->second; -} - -std::vector<std::pair<Cid, FixedChannelServiceImpl*>> -FixedChannelServiceManagerImpl::GetRegisteredServices() { - std::vector<std::pair<Cid, FixedChannelServiceImpl*>> results; - for (auto& elem : service_map_) { - results.emplace_back(elem.first, &elem.second); - } - return results; -} - -} // namespace internal -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/internal/fixed_channel_service_manager_impl.h b/system/gd/l2cap/le/internal/fixed_channel_service_manager_impl.h deleted file mode 100644 index b49a4f4f35..0000000000 --- a/system/gd/l2cap/le/internal/fixed_channel_service_manager_impl.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <unordered_map> - -#include "l2cap/cid.h" -#include "l2cap/le/fixed_channel_service.h" -#include "l2cap/le/internal/fixed_channel_service_impl.h" -#include "os/handler.h" - -namespace bluetooth { -namespace l2cap { -namespace le { -namespace internal { - -class FixedChannelServiceManagerImpl { -public: - explicit FixedChannelServiceManagerImpl(os::Handler* l2cap_layer_handler) - : l2cap_layer_handler_(l2cap_layer_handler) {} - virtual ~FixedChannelServiceManagerImpl() = default; - - // All APIs must be invoked in L2CAP layer handler - - virtual void Register(Cid cid, FixedChannelServiceImpl::PendingRegistration pending_registration); - virtual void Unregister(Cid cid, FixedChannelService::OnUnregisteredCallback callback, - os::Handler* handler); - virtual bool IsServiceRegistered(Cid cid) const; - virtual FixedChannelServiceImpl* GetService(Cid cid); - virtual std::vector<std::pair<Cid, FixedChannelServiceImpl*>> GetRegisteredServices(); - -private: - os::Handler* l2cap_layer_handler_ = nullptr; - std::unordered_map<Cid, FixedChannelServiceImpl> service_map_; -}; -} // namespace internal -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/internal/fixed_channel_service_manager_impl_mock.h b/system/gd/l2cap/le/internal/fixed_channel_service_manager_impl_mock.h deleted file mode 100644 index f8e51f53ff..0000000000 --- a/system/gd/l2cap/le/internal/fixed_channel_service_manager_impl_mock.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2019 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. - */ -#pragma once - -#include <gmock/gmock.h> - -#include "l2cap/le/internal/fixed_channel_impl.h" -#include "l2cap/le/internal/fixed_channel_service_manager_impl.h" - -// Unit test interfaces -namespace bluetooth { -namespace l2cap { -namespace le { -namespace internal { -namespace testing { - -class MockFixedChannelServiceManagerImpl : public FixedChannelServiceManagerImpl { -public: - MockFixedChannelServiceManagerImpl() : FixedChannelServiceManagerImpl(nullptr) {} - MOCK_METHOD(void, Register, - (Cid cid, FixedChannelServiceImpl::PendingRegistration pending_registration), - (override)); - MOCK_METHOD(void, Unregister, - (Cid cid, FixedChannelService::OnUnregisteredCallback callback, os::Handler* handler), - (override)); - MOCK_METHOD(bool, IsServiceRegistered, (Cid cid), (const, override)); - MOCK_METHOD(FixedChannelServiceImpl*, GetService, (Cid cid), (override)); - MOCK_METHOD((std::vector<std::pair<Cid, FixedChannelServiceImpl*>>), GetRegisteredServices, (), - (override)); -}; - -} // namespace testing -} // namespace internal -} // namespace le -} // namespace l2cap -} // namespace bluetooth
\ No newline at end of file diff --git a/system/gd/l2cap/le/internal/fixed_channel_service_manager_test.cc b/system/gd/l2cap/le/internal/fixed_channel_service_manager_test.cc deleted file mode 100644 index 645b30ba71..0000000000 --- a/system/gd/l2cap/le/internal/fixed_channel_service_manager_test.cc +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2018 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 <future> - -#include "common/bind.h" -#include "l2cap/cid.h" -#include "l2cap/le/fixed_channel_manager.h" -#include "l2cap/le/fixed_channel_service.h" -#include "l2cap/le/internal/fixed_channel_service_manager_impl.h" -#include "os/handler.h" -#include "os/thread.h" - -namespace bluetooth { -namespace l2cap { -namespace le { -namespace internal { - -class L2capLeServiceManagerTest : public ::testing::Test { -public: - ~L2capLeServiceManagerTest() = default; - - void OnServiceRegistered(bool expect_success, FixedChannelManager::RegistrationResult result, - std::unique_ptr<FixedChannelService> user_service) { - EXPECT_EQ(result == FixedChannelManager::RegistrationResult::SUCCESS, expect_success); - service_registered_ = expect_success; - } - -protected: - void SetUp() override { - manager_ = new FixedChannelServiceManagerImpl{nullptr}; - thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL); - user_handler_ = new os::Handler(thread_); - } - - void TearDown() override { - user_handler_->Clear(); - delete user_handler_; - delete thread_; - delete manager_; - } - - void sync_user_handler() { - std::promise<void> promise; - auto future = promise.get_future(); - user_handler_->Post( - common::BindOnce(&std::promise<void>::set_value, common::Unretained(&promise))); - future.wait_for(std::chrono::milliseconds(3)); - } - - FixedChannelServiceManagerImpl* manager_ = nullptr; - os::Thread* thread_ = nullptr; - os::Handler* user_handler_ = nullptr; - - bool service_registered_ = false; -}; - -TEST_F(L2capLeServiceManagerTest, register_and_unregister_le_fixed_channel) { - FixedChannelServiceImpl::PendingRegistration pending_registration{ - .user_handler_ = user_handler_, - .on_registration_complete_callback_ = common::BindOnce( - &L2capLeServiceManagerTest::OnServiceRegistered, common::Unretained(this), true)}; - Cid cid = kSmpBrCid; - EXPECT_FALSE(manager_->IsServiceRegistered(cid)); - manager_->Register(cid, std::move(pending_registration)); - EXPECT_TRUE(manager_->IsServiceRegistered(cid)); - sync_user_handler(); - EXPECT_TRUE(service_registered_); - manager_->Unregister(cid, common::BindOnce([] {}), user_handler_); - EXPECT_FALSE(manager_->IsServiceRegistered(cid)); -} - -TEST_F(L2capLeServiceManagerTest, register_le_fixed_channel_bad_cid) { - FixedChannelServiceImpl::PendingRegistration pending_registration{ - .user_handler_ = user_handler_, - .on_registration_complete_callback_ = - common::BindOnce(&L2capLeServiceManagerTest::OnServiceRegistered, - common::Unretained(this), false)}; - Cid cid = 0x1000; - EXPECT_FALSE(manager_->IsServiceRegistered(cid)); - manager_->Register(cid, std::move(pending_registration)); - EXPECT_FALSE(manager_->IsServiceRegistered(cid)); - sync_user_handler(); - EXPECT_FALSE(service_registered_); -} - -} // namespace internal -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/internal/link.cc b/system/gd/l2cap/le/internal/link.cc deleted file mode 100644 index 8143a9cf45..0000000000 --- a/system/gd/l2cap/le/internal/link.cc +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/le/internal/link.h" - -#include <bluetooth/log.h> - -#include <chrono> -#include <memory> - -#include "hci/acl_manager/le_acl_connection.h" -#include "l2cap/internal/dynamic_channel_impl.h" -#include "l2cap/internal/parameter_provider.h" -#include "l2cap/le/dynamic_channel_manager.h" -#include "l2cap/le/internal/fixed_channel_impl.h" -#include "l2cap/le/internal/link_manager.h" -#include "os/alarm.h" - -namespace bluetooth { -namespace l2cap { -namespace le { -namespace internal { - -static constexpr uint16_t kDefaultMinimumCeLength = 0x0002; -static constexpr uint16_t kDefaultMaximumCeLength = 0x0C00; - -Link::Link(os::Handler* l2cap_handler, - std::unique_ptr<hci::acl_manager::LeAclConnection> acl_connection, - l2cap::internal::ParameterProvider* parameter_provider, - DynamicChannelServiceManagerImpl* dynamic_service_manager, - FixedChannelServiceManagerImpl* /* fixed_service_manager */, LinkManager* link_manager) - : l2cap_handler_(l2cap_handler), - acl_connection_(std::move(acl_connection)), - data_pipeline_manager_(l2cap_handler, this, acl_connection_->GetAclQueueEnd()), - parameter_provider_(parameter_provider), - dynamic_service_manager_(dynamic_service_manager), - signalling_manager_(l2cap_handler_, this, &data_pipeline_manager_, dynamic_service_manager_, - &dynamic_channel_allocator_), - link_manager_(link_manager) { - log::assert_that(l2cap_handler_ != nullptr, "assert failed: l2cap_handler_ != nullptr"); - log::assert_that(acl_connection_ != nullptr, "assert failed: acl_connection_ != nullptr"); - log::assert_that(parameter_provider_ != nullptr, "assert failed: parameter_provider_ != nullptr"); - link_idle_disconnect_alarm_.Schedule( - common::BindOnce(&Link::Disconnect, common::Unretained(this)), - parameter_provider_->GetLeLinkIdleDisconnectTimeout()); - acl_connection_->RegisterCallbacks(this, l2cap_handler_); -} - -void Link::OnAclDisconnected(hci::ErrorCode reason) { - fixed_channel_allocator_.OnAclDisconnected(static_cast<hci::ErrorCode>(reason)); - dynamic_channel_allocator_.OnAclDisconnected(static_cast<hci::ErrorCode>(reason)); -} - -void Link::OnDisconnection(hci::ErrorCode status) { - OnAclDisconnected(status); - - link_manager_->OnDisconnect(GetAclConnection()->GetRemoteAddress()); -} - -void Link::OnConnectionUpdate(hci::ErrorCode /* hci_status */, uint16_t connection_interval, - uint16_t connection_latency, uint16_t supervision_timeout) { - log::info("interval {:x} latency {:x} supervision_timeout {:x}", connection_interval, - connection_latency, supervision_timeout); - if (update_request_signal_id_ != kInvalidSignalId) { - hci::ErrorCode result = hci::ErrorCode::SUCCESS; - if (connection_interval > update_request_interval_max_ || - connection_interval < update_request_interval_min_ || - connection_latency != update_request_latency_ || - supervision_timeout != update_request_supervision_timeout_) { - log::info( - "Received connection update complete with different parameters that provided by the " - "Host"); - } - - if (!CheckConnectionParameters(connection_interval, connection_interval, connection_latency, - supervision_timeout)) { - result = hci::ErrorCode::UNSPECIFIED_ERROR; - } - - on_connection_update_complete(update_request_signal_id_, result); - update_request_signal_id_ = kInvalidSignalId; - } -} - -void Link::OnParameterUpdateRequest(uint16_t interval_min, uint16_t interval_max, uint16_t latency, - uint16_t supervision_timeout) { - log::info("interval_min {:x} interval_max {:x} latency {:x} supervision_timeout {:x}", - interval_min, interval_max, latency, supervision_timeout); - hci::ErrorCode result = hci::ErrorCode::SUCCESS; - if (interval_max > update_request_interval_max_ || interval_min < update_request_interval_min_ || - latency != update_request_latency_ || - supervision_timeout != update_request_supervision_timeout_) { - log::info( - "Received connection update complete with different parameters that provided by the " - "Host"); - } - - if (!CheckConnectionParameters(interval_min, interval_max, latency, supervision_timeout)) { - // TODO: Reject - } else { - // TODO: Accept - } -} - -void Link::OnDataLengthChange(uint16_t tx_octets, uint16_t tx_time, uint16_t rx_octets, - uint16_t rx_time) { - log::info("tx_octets {:x} tx_time {:x} rx_octets {:x} rx_time {:x}", tx_octets, tx_time, - rx_octets, rx_time); -} - -void Link::OnReadRemoteVersionInformationComplete(hci::ErrorCode hci_status, uint8_t lmp_version, - uint16_t manufacturer_name, - uint16_t sub_version) { - log::info("lmp_version:{} manufacturer_name:{} sub_version:{}", lmp_version, manufacturer_name, - sub_version); - link_manager_->OnReadRemoteVersionInformationComplete(hci_status, GetDevice(), lmp_version, - manufacturer_name, sub_version); -} - -void Link::OnLeReadRemoteFeaturesComplete(hci::ErrorCode /* hci_status*/, uint64_t /* features */) { -} - -void Link::OnPhyUpdate(hci::ErrorCode /* hci_status */, uint8_t /* tx_phy */, - uint8_t /* rx_phy */) {} - -void Link::OnLeSubrateChange(hci::ErrorCode hci_status, uint16_t subrate_factor, - uint16_t peripheral_latency, uint16_t continuation_number, - uint16_t supervision_timeout) { - log::info( - "hci_status: {}, subrate_factor: {:#x}, peripheral_latency: {:#x}, continuation_number: " - "{:#x}, supervision_timeout: {:#x}", - ErrorCodeText(hci_status), subrate_factor, peripheral_latency, continuation_number, - supervision_timeout); -} - -void Link::Disconnect() { - acl_connection_->Disconnect(hci::DisconnectReason::REMOTE_USER_TERMINATED_CONNECTION); -} - -void Link::UpdateConnectionParameterFromRemote(SignalId signal_id, uint16_t conn_interval_min, - uint16_t conn_interval_max, uint16_t conn_latency, - uint16_t supervision_timeout) { - acl_connection_->LeConnectionUpdate(conn_interval_min, conn_interval_max, conn_latency, - supervision_timeout, kDefaultMinimumCeLength, - kDefaultMaximumCeLength); - update_request_signal_id_ = signal_id; - update_request_interval_min_ = conn_interval_min; - update_request_interval_max_ = conn_interval_max; - update_request_latency_ = conn_latency; - update_request_supervision_timeout_ = supervision_timeout; -} - -bool Link::CheckConnectionParameters(uint16_t conn_interval_min, uint16_t conn_interval_max, - uint16_t conn_latency, uint16_t supervision_timeout) { - if (conn_interval_min < 0x0006 || conn_interval_min > 0x0C80 || conn_interval_max < 0x0006 || - conn_interval_max > 0x0C80 || conn_latency > 0x01F3 || supervision_timeout < 0x000A || - supervision_timeout > 0x0C80) { - log::error("Invalid parameter"); - return false; - } - - // The Maximum interval in milliseconds will be conn_interval_max * 1.25 ms - // The Timeout in milliseconds will be expected_supervision_timeout * 10 ms - // The Timeout in milliseconds shall be larger than (1 + Latency) * Interval_Max * 2, where - // Interval_Max is given in milliseconds. - uint32_t supervision_timeout_min = (uint32_t)(1 + conn_latency) * conn_interval_max * 2 + 1; - if (supervision_timeout * 8 < supervision_timeout_min || conn_interval_max < conn_interval_min) { - log::error("Invalid parameter"); - return false; - } - - return true; -} - -void Link::SendConnectionParameterUpdate(uint16_t conn_interval_min, uint16_t conn_interval_max, - uint16_t conn_latency, uint16_t supervision_timeout, - uint16_t min_ce_length, uint16_t max_ce_length) { - if (acl_connection_->GetRole() == hci::Role::PERIPHERAL) { - // TODO: If both LL central and peripheral support 4.1, use HCI command directly - signalling_manager_.SendConnectionParameterUpdateRequest(conn_interval_min, conn_interval_max, - conn_latency, supervision_timeout); - return; - } - acl_connection_->LeConnectionUpdate(conn_interval_min, conn_interval_max, conn_latency, - supervision_timeout, min_ce_length, max_ce_length); - update_request_signal_id_ = kInvalidSignalId; -} - -std::shared_ptr<FixedChannelImpl> Link::AllocateFixedChannel(Cid cid, - SecurityPolicy /* security_policy */) { - auto channel = fixed_channel_allocator_.AllocateChannel(cid); - data_pipeline_manager_.AttachChannel(cid, channel, - l2cap::internal::DataPipelineManager::ChannelMode::BASIC); - return channel; -} - -bool Link::IsFixedChannelAllocated(Cid cid) { - return fixed_channel_allocator_.IsChannelAllocated(cid); -} - -Cid Link::ReserveDynamicChannel() { return dynamic_channel_allocator_.ReserveChannel(); } - -void Link::SendConnectionRequest( - Psm psm, PendingDynamicChannelConnection pending_dynamic_channel_connection) { - if (dynamic_channel_allocator_.IsPsmUsed(psm)) { - log::info("Psm {} is already connected", psm); - return; - } - auto reserved_cid = ReserveDynamicChannel(); - auto mtu = pending_dynamic_channel_connection.configuration_.mtu; - local_cid_to_pending_dynamic_channel_connection_map_[reserved_cid] = - std::move(pending_dynamic_channel_connection); - signalling_manager_.SendConnectionRequest(psm, reserved_cid, mtu); -} - -void Link::SendDisconnectionRequest(Cid local_cid, Cid remote_cid) { - auto channel = dynamic_channel_allocator_.FindChannelByCid(local_cid); - if (channel == nullptr || channel->GetRemoteCid() != remote_cid) { - log::error("Invalid cid"); - } - signalling_manager_.SendDisconnectRequest(local_cid, remote_cid); -} - -void Link::OnOutgoingConnectionRequestFail(Cid local_cid, - LeCreditBasedConnectionResponseResult response_result) { - if (local_cid_to_pending_dynamic_channel_connection_map_.find(local_cid) != - local_cid_to_pending_dynamic_channel_connection_map_.end()) { - // TODO(hsz): Currently we only notify the client when the remote didn't send connection - // response SUCCESS. - // Should we notify the client when the link failed to establish? - DynamicChannelManager::ConnectionResult result{ - .connection_result_code = DynamicChannelManager::ConnectionResultCode::FAIL_L2CAP_ERROR, - .hci_error = hci::ErrorCode::SUCCESS, - .l2cap_connection_response_result = response_result, - }; - NotifyChannelFail(local_cid, result); - } - dynamic_channel_allocator_.FreeChannel(local_cid); -} - -std::shared_ptr<l2cap::internal::DynamicChannelImpl> Link::AllocateDynamicChannel(Psm psm, - Cid remote_cid) { - auto channel = dynamic_channel_allocator_.AllocateChannel(psm, remote_cid); - if (channel != nullptr) { - data_pipeline_manager_.AttachChannel( - channel->GetCid(), channel, - l2cap::internal::DataPipelineManager::ChannelMode::LE_CREDIT_BASED); - RefreshRefCount(); - channel->local_initiated_ = false; - } - return channel; -} - -std::shared_ptr<l2cap::internal::DynamicChannelImpl> Link::AllocateReservedDynamicChannel( - Cid reserved_cid, Psm psm, Cid remote_cid) { - auto channel = dynamic_channel_allocator_.AllocateReservedChannel(reserved_cid, psm, remote_cid); - if (channel != nullptr) { - data_pipeline_manager_.AttachChannel( - channel->GetCid(), channel, - l2cap::internal::DataPipelineManager::ChannelMode::LE_CREDIT_BASED); - RefreshRefCount(); - channel->local_initiated_ = true; - } - return channel; -} - -void Link::FreeDynamicChannel(Cid cid) { - if (dynamic_channel_allocator_.FindChannelByCid(cid) == nullptr) { - return; - } - data_pipeline_manager_.DetachChannel(cid); - dynamic_channel_allocator_.FreeChannel(cid); - RefreshRefCount(); -} - -void Link::RefreshRefCount() { - int ref_count = 0; - ref_count += fixed_channel_allocator_.GetRefCount(); - ref_count += dynamic_channel_allocator_.NumberOfChannels(); - log::assert_that(ref_count >= 0, "ref_count {} is less than 0", ref_count); - if (ref_count > 0) { - link_idle_disconnect_alarm_.Cancel(); - } else { - link_idle_disconnect_alarm_.Schedule( - common::BindOnce(&Link::Disconnect, common::Unretained(this)), - parameter_provider_->GetLeLinkIdleDisconnectTimeout()); - } -} - -void Link::NotifyChannelCreation(Cid cid, std::unique_ptr<DynamicChannel> user_channel) { - log::assert_that( - local_cid_to_pending_dynamic_channel_connection_map_.find(cid) != - local_cid_to_pending_dynamic_channel_connection_map_.end(), - "assert failed: local_cid_to_pending_dynamic_channel_connection_map_.find(cid) != " - "local_cid_to_pending_dynamic_channel_connection_map_.end()"); - auto& pending_dynamic_channel_connection = - local_cid_to_pending_dynamic_channel_connection_map_[cid]; - pending_dynamic_channel_connection.handler_->Post( - common::BindOnce(std::move(pending_dynamic_channel_connection.on_open_callback_), - std::move(user_channel))); - local_cid_to_pending_dynamic_channel_connection_map_.erase(cid); -} - -void Link::NotifyChannelFail(Cid cid, DynamicChannelManager::ConnectionResult result) { - log::assert_that( - local_cid_to_pending_dynamic_channel_connection_map_.find(cid) != - local_cid_to_pending_dynamic_channel_connection_map_.end(), - "assert failed: local_cid_to_pending_dynamic_channel_connection_map_.find(cid) != " - "local_cid_to_pending_dynamic_channel_connection_map_.end()"); - auto& pending_dynamic_channel_connection = - local_cid_to_pending_dynamic_channel_connection_map_[cid]; - // TODO(cmanton) Pass proper connection falure result to user - pending_dynamic_channel_connection.handler_->Post(common::BindOnce( - std::move(pending_dynamic_channel_connection.on_fail_callback_), result)); - local_cid_to_pending_dynamic_channel_connection_map_.erase(cid); -} - -uint16_t Link::GetMps() const { return parameter_provider_->GetLeMps(); } - -uint16_t Link::GetInitialCredit() const { return parameter_provider_->GetLeInitialCredit(); } - -void Link::SendLeCredit(Cid local_cid, uint16_t credit) { - signalling_manager_.SendCredit(local_cid, credit); -} - -void Link::ReadRemoteVersionInformation() { acl_connection_->ReadRemoteVersionInformation(); } - -void Link::on_connection_update_complete(SignalId signal_id, hci::ErrorCode error_code) { - if (!signal_id.IsValid()) { - log::info("Invalid signal_id"); - return; - } - ConnectionParameterUpdateResponseResult result = - (error_code == hci::ErrorCode::SUCCESS) - ? ConnectionParameterUpdateResponseResult::ACCEPTED - : ConnectionParameterUpdateResponseResult::REJECTED; - signalling_manager_.SendConnectionParameterUpdateResponse(SignalId(), result); -} - -void Link::OnPendingPacketChange(Cid /* local_cid */, bool has_packet) { - if (has_packet) { - remaining_packets_to_be_sent_++; - } else { - remaining_packets_to_be_sent_--; - } - link_manager_->OnPendingPacketChange(GetDevice(), remaining_packets_to_be_sent_); -} - -} // namespace internal -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/internal/link.h b/system/gd/l2cap/le/internal/link.h deleted file mode 100644 index fa8c06ea71..0000000000 --- a/system/gd/l2cap/le/internal/link.h +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <atomic> -#include <chrono> -#include <memory> - -#include "common/interfaces/ILoggable.h" -#include "hci/acl_manager/le_acl_connection.h" -#include "l2cap/internal/data_pipeline_manager.h" -#include "l2cap/internal/dynamic_channel_allocator.h" -#include "l2cap/internal/fixed_channel_allocator.h" -#include "l2cap/internal/ilink.h" -#include "l2cap/internal/parameter_provider.h" -#include "l2cap/le/dynamic_channel_manager.h" -#include "l2cap/le/internal/dynamic_channel_service_manager_impl.h" -#include "l2cap/le/internal/fixed_channel_impl.h" -#include "l2cap/le/internal/fixed_channel_service_manager_impl.h" -#include "l2cap/le/internal/signalling_manager.h" -#include "l2cap/le/link_options.h" -#include "l2cap/le/security_enforcement_interface.h" -#include "os/alarm.h" - -namespace bluetooth { -namespace l2cap { -namespace le { -namespace internal { - -class LinkManager; - -class Link : public l2cap::internal::ILink, - public hci::acl_manager::LeConnectionManagementCallbacks, - public bluetooth::common::IRedactableLoggable { -public: - Link(os::Handler* l2cap_handler, - std::unique_ptr<hci::acl_manager::LeAclConnection> acl_connection, - l2cap::internal::ParameterProvider* parameter_provider, - DynamicChannelServiceManagerImpl* dynamic_service_manager, - FixedChannelServiceManagerImpl* fixed_service_manager, LinkManager* link_manager); - - Link(const Link&) = delete; - Link& operator=(const Link&) = delete; - - ~Link() = default; - - inline hci::AddressWithType GetDevice() const override { - return acl_connection_->GetRemoteAddress(); - } - - struct PendingDynamicChannelConnection { - os::Handler* handler_; - DynamicChannelManager::OnConnectionOpenCallback on_open_callback_; - DynamicChannelManager::OnConnectionFailureCallback on_fail_callback_; - le::DynamicChannelConfigurationOption configuration_; - }; - - inline virtual hci::Role GetRole() { return acl_connection_->GetRole(); } - - inline virtual hci::acl_manager::LeAclConnection* GetAclConnection() { - return acl_connection_.get(); - } - - // ACL methods - - virtual void OnAclDisconnected(hci::ErrorCode reason); - - void OnDisconnection(hci::ErrorCode reason) override; - - void OnConnectionUpdate(hci::ErrorCode hci_status, uint16_t connection_interval, - uint16_t connection_latency, uint16_t supervision_timeout) override; - - void OnParameterUpdateRequest(uint16_t interval_min, uint16_t interval_max, uint16_t latency, - uint16_t supervision_timeout) override; - - void OnDataLengthChange(uint16_t tx_octets, uint16_t tx_time, uint16_t rx_octets, - uint16_t rx_time) override; - - void OnReadRemoteVersionInformationComplete(hci::ErrorCode hci_status, uint8_t lmp_version, - uint16_t manufacturer_name, - uint16_t sub_version) override; - - void OnLeReadRemoteFeaturesComplete(hci::ErrorCode hci_status, uint64_t features) override; - - void OnPhyUpdate(hci::ErrorCode hci_status, uint8_t tx_phy, uint8_t rx_phy) override; - - void OnLeSubrateChange(hci::ErrorCode hci_status, uint16_t subrate_factor, - uint16_t peripheral_latency, uint16_t continuation_number, - uint16_t supervision_timeout) override; - - virtual void Disconnect(); - - // Handles connection parameter update request from remote - virtual void UpdateConnectionParameterFromRemote(SignalId signal_id, uint16_t conn_interval_min, - uint16_t conn_interval_max, - uint16_t conn_latency, - uint16_t supervision_timeout); - virtual bool CheckConnectionParameters(uint16_t conn_interval_min, uint16_t conn_interval_max, - uint16_t conn_latency, uint16_t supervision_timeout); - - virtual void SendConnectionParameterUpdate(uint16_t conn_interval_min, uint16_t conn_interval_max, - uint16_t conn_latency, uint16_t supervision_timeout, - uint16_t min_ce_length, uint16_t max_ce_length); - - // FixedChannel methods - - virtual std::shared_ptr<FixedChannelImpl> AllocateFixedChannel(Cid cid, - SecurityPolicy security_policy); - - virtual bool IsFixedChannelAllocated(Cid cid); - - // DynamicChannel methods - - virtual Cid ReserveDynamicChannel(); - - virtual void SendConnectionRequest( - Psm psm, PendingDynamicChannelConnection pending_dynamic_channel_connection); - - void SendDisconnectionRequest(Cid local_cid, Cid remote_cid) override; - - // Invoked by signalling manager to indicate an outgoing connection request failed and link shall - // free resources - virtual void OnOutgoingConnectionRequestFail(Cid local_cid, - LeCreditBasedConnectionResponseResult result); - - virtual std::shared_ptr<l2cap::internal::DynamicChannelImpl> AllocateDynamicChannel( - Psm psm, Cid remote_cid); - - virtual std::shared_ptr<l2cap::internal::DynamicChannelImpl> AllocateReservedDynamicChannel( - Cid reserved_cid, Psm psm, Cid remote_cid); - - virtual void FreeDynamicChannel(Cid cid); - - // Check how many channels are acquired or in use, if zero, start tear down timer, if non-zero, - // cancel tear down timer - virtual void RefreshRefCount(); - - void NotifyChannelCreation(Cid cid, std::unique_ptr<DynamicChannel> user_channel); - void NotifyChannelFail(Cid cid, DynamicChannelManager::ConnectionResult result); - - virtual std::string ToString() { return GetDevice().ToString(); } - - std::string ToStringForLogging() const override { return GetDevice().ToStringForLogging(); } - - std::string ToRedactedStringForLogging() const override { - return GetDevice().ToRedactedStringForLogging(); - } - - virtual uint16_t GetMps() const; - - virtual uint16_t GetInitialCredit() const; - - void SendLeCredit(Cid local_cid, uint16_t credit) override; - - LinkOptions* GetLinkOptions() { return &link_options_; } - - void ReadRemoteVersionInformation(); - - void OnPendingPacketChange(Cid local_cid, bool has_packet) override; - -private: - os::Handler* l2cap_handler_; - l2cap::internal::FixedChannelAllocator<FixedChannelImpl, Link> fixed_channel_allocator_{ - this, l2cap_handler_}; - l2cap::internal::DynamicChannelAllocator dynamic_channel_allocator_{this, l2cap_handler_}; - std::unique_ptr<hci::acl_manager::LeAclConnection> acl_connection_; - l2cap::internal::DataPipelineManager data_pipeline_manager_; - l2cap::internal::ParameterProvider* parameter_provider_; - DynamicChannelServiceManagerImpl* dynamic_service_manager_; - LeSignallingManager signalling_manager_; - std::unordered_map<Cid, PendingDynamicChannelConnection> - local_cid_to_pending_dynamic_channel_connection_map_; - os::Alarm link_idle_disconnect_alarm_{l2cap_handler_}; - LinkOptions link_options_{acl_connection_.get(), this, l2cap_handler_}; - LinkManager* link_manager_; - SignalId update_request_signal_id_ = kInvalidSignalId; - uint16_t update_request_interval_min_; - uint16_t update_request_interval_max_; - uint16_t update_request_latency_; - uint16_t update_request_supervision_timeout_; - std::atomic_int remaining_packets_to_be_sent_ = 0; - - // Received connection update complete from ACL manager. SignalId is bound to a valid number when - // we need to send a response to remote. If SignalId is bound to an invalid number, we don't send - // a response to remote, because the connection update request is not from remote LL peripheral. - void on_connection_update_complete(SignalId signal_id, hci::ErrorCode error_code); -}; - -} // namespace internal -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/internal/link_manager.cc b/system/gd/l2cap/le/internal/link_manager.cc deleted file mode 100644 index ba0782be49..0000000000 --- a/system/gd/l2cap/le/internal/link_manager.cc +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/le/internal/link_manager.h" - -#include <bluetooth/log.h> - -#include <memory> -#include <unordered_map> - -#include "hci/acl_manager/le_acl_connection.h" -#include "hci/address.h" -#include "l2cap/internal/scheduler_fifo.h" -#include "l2cap/le/internal/link.h" -#include "os/handler.h" -#include "os/log.h" - -namespace bluetooth { -namespace l2cap { -namespace le { -namespace internal { - -void LinkManager::ConnectFixedChannelServices( - hci::AddressWithType address_with_type, - PendingFixedChannelConnection pending_fixed_channel_connection) { - // Check if there is any service registered - auto fixed_channel_services = fixed_channel_service_manager_->GetRegisteredServices(); - if (fixed_channel_services.empty()) { - // If so, return error - pending_fixed_channel_connection.handler_->Post( - common::BindOnce(std::move(pending_fixed_channel_connection.on_fail_callback_), - FixedChannelManager::ConnectionResult{ - .connection_result_code = FixedChannelManager:: - ConnectionResultCode::FAIL_NO_SERVICE_REGISTERED})); - return; - } - // Otherwise, check if device has an ACL connection - auto* link = GetLink(address_with_type); - if (link != nullptr) { - // If device already have an ACL connection - // Check if all registered services have an allocated channel and allocate one if not already - // allocated - int num_new_channels = 0; - for (auto& fixed_channel_service : fixed_channel_services) { - if (link->IsFixedChannelAllocated(fixed_channel_service.first)) { - // This channel is already allocated for this link, do not allocated twice - continue; - } - // Allocate channel for newly registered fixed channels - auto fixed_channel_impl = link->AllocateFixedChannel( - fixed_channel_service.first, - SecurityPolicy::NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK); - fixed_channel_service.second->NotifyChannelCreation( - std::make_unique<FixedChannel>(fixed_channel_impl, l2cap_handler_)); - num_new_channels++; - } - // Declare connection failure if no new channels are created - if (num_new_channels == 0) { - pending_fixed_channel_connection.handler_->Post(common::BindOnce( - std::move(pending_fixed_channel_connection.on_fail_callback_), - FixedChannelManager::ConnectionResult{ - .connection_result_code = FixedChannelManager::ConnectionResultCode:: - FAIL_ALL_SERVICES_HAVE_CHANNEL})); - } - // No need to create ACL connection, return without saving any pending connections - return; - } - // If not, create new ACL connection - // Add request to pending link list first - auto pending_link = pending_links_.find(address_with_type); - if (pending_link == pending_links_.end()) { - // Create pending link if not exist - pending_links_.try_emplace(address_with_type); - pending_link = pending_links_.find(address_with_type); - } - pending_link->second.pending_fixed_channel_connections_.push_back( - std::move(pending_fixed_channel_connection)); - // Then create new ACL connection - acl_manager_->CreateLeConnection(address_with_type, /* is_direct */ true); -} - -void LinkManager::ConnectDynamicChannelServices( - hci::AddressWithType device, - Link::PendingDynamicChannelConnection pending_dynamic_channel_connection, Psm psm) { - auto* link = GetLink(device); - if (link == nullptr) { - acl_manager_->CreateLeConnection(device, /* is_direct */ true); - pending_dynamic_channels_[device].push_back( - std::make_pair(psm, std::move(pending_dynamic_channel_connection))); - return; - } - link->SendConnectionRequest(psm, std::move(pending_dynamic_channel_connection)); -} - -Link* LinkManager::GetLink(hci::AddressWithType address_with_type) { - if (links_.find(address_with_type) == links_.end()) { - return nullptr; - } - return &links_.find(address_with_type)->second; -} - -void LinkManager::OnLeConnectSuccess( - hci::AddressWithType connecting_address_with_type, - std::unique_ptr<hci::acl_manager::LeAclConnection> acl_connection) { - // Same link should not be connected twice - hci::AddressWithType connected_address_with_type = acl_connection->GetRemoteAddress(); - uint16_t handle = acl_connection->GetHandle(); - log::assert_that(GetLink(connected_address_with_type) == nullptr, - "{} is connected twice without disconnection", - ADDRESS_TO_LOGGABLE_CSTR(acl_connection->GetRemoteAddress())); - links_.try_emplace(connected_address_with_type, l2cap_handler_, std::move(acl_connection), - parameter_provider_, dynamic_channel_service_manager_, - fixed_channel_service_manager_, this); - auto* link = GetLink(connected_address_with_type); - - if (link_property_callback_handler_ != nullptr) { - link_property_callback_handler_->CallOn(link_property_listener_, - &LinkPropertyListener::OnLinkConnected, - connected_address_with_type, handle, link->GetRole()); - } - - // Remove device from pending links list, if any - pending_links_.erase(connecting_address_with_type); - - link->ReadRemoteVersionInformation(); -} - -void LinkManager::OnLeConnectFail(hci::AddressWithType address_with_type, hci::ErrorCode reason) { - // Notify all pending links for this device - auto pending_link = pending_links_.find(address_with_type); - if (pending_link == pending_links_.end()) { - // There is no pending link, exit - log::info("Connection to {} failed without a pending link", address_with_type); - return; - } - for (auto& pending_fixed_channel_connection : - pending_link->second.pending_fixed_channel_connections_) { - pending_fixed_channel_connection.handler_->Post(common::BindOnce( - std::move(pending_fixed_channel_connection.on_fail_callback_), - FixedChannelManager::ConnectionResult{ - .connection_result_code = - FixedChannelManager::ConnectionResultCode::FAIL_HCI_ERROR, - .hci_error = reason})); - } - // Remove entry in pending link list - pending_links_.erase(pending_link); -} - -void LinkManager::OnDisconnect(bluetooth::hci::AddressWithType address_with_type) { - auto* link = GetLink(address_with_type); - log::assert_that(link != nullptr, "Device {} is disconnected but not in local database", - ADDRESS_TO_LOGGABLE_CSTR(address_with_type)); - if (links_with_pending_packets_.count(address_with_type) != 0) { - disconnected_links_.emplace(address_with_type); - } else { - links_.erase(address_with_type); - } - - if (link_property_callback_handler_ != nullptr) { - link_property_callback_handler_->CallOn( - link_property_listener_, &LinkPropertyListener::OnLinkDisconnected, address_with_type); - } -} - -void LinkManager::RegisterLinkPropertyListener(os::Handler* handler, - LinkPropertyListener* listener) { - link_property_callback_handler_ = handler; - link_property_listener_ = listener; -} - -void LinkManager::OnReadRemoteVersionInformationComplete(hci::ErrorCode hci_status, - hci::AddressWithType address_with_type, - uint8_t lmp_version, - uint16_t manufacturer_name, - uint16_t sub_version) { - if (link_property_callback_handler_ != nullptr) { - link_property_callback_handler_->CallOn( - link_property_listener_, &LinkPropertyListener::OnReadRemoteVersionInformation, - hci_status, address_with_type, lmp_version, manufacturer_name, sub_version); - } - - auto* link = GetLink(address_with_type); - // Allocate and distribute channels for all registered fixed channel services - auto fixed_channel_services = fixed_channel_service_manager_->GetRegisteredServices(); - for (auto& fixed_channel_service : fixed_channel_services) { - auto fixed_channel_impl = link->AllocateFixedChannel( - fixed_channel_service.first, - SecurityPolicy::NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK); - fixed_channel_service.second->NotifyChannelCreation( - std::make_unique<FixedChannel>(fixed_channel_impl, l2cap_handler_)); - } - if (pending_dynamic_channels_.find(address_with_type) != pending_dynamic_channels_.end()) { - for (auto& psm_callback : pending_dynamic_channels_[address_with_type]) { - link->SendConnectionRequest(psm_callback.first, std::move(psm_callback.second)); - } - pending_dynamic_channels_.erase(address_with_type); - } -} - -void LinkManager::OnPendingPacketChange(hci::AddressWithType remote, int num_packets) { - if (disconnected_links_.count(remote) != 0 && num_packets == 0) { - links_.erase(remote); - links_with_pending_packets_.erase(remote); - } else if (num_packets != 0) { - links_with_pending_packets_.emplace(remote); - } else { - links_with_pending_packets_.erase(remote); - } -} - -} // namespace internal -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/internal/link_manager.h b/system/gd/l2cap/le/internal/link_manager.h deleted file mode 100644 index 4453d11c18..0000000000 --- a/system/gd/l2cap/le/internal/link_manager.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <memory> -#include <unordered_map> -#include <unordered_set> -#include <utility> -#include <vector> - -#include "hci/acl_manager/le_acl_connection.h" -#include "hci/address.h" -#include "hci/address_with_type.h" -#include "hci/le_advertising_manager.h" -#include "l2cap/internal/parameter_provider.h" -#include "l2cap/internal/scheduler.h" -#include "l2cap/le/fixed_channel_manager.h" -#include "l2cap/le/internal/dynamic_channel_service_manager_impl.h" -#include "l2cap/le/internal/fixed_channel_service_manager_impl.h" -#include "l2cap/le/internal/link.h" -#include "l2cap/le/link_property_listener.h" -#include "os/handler.h" - -namespace bluetooth { -namespace l2cap { -namespace le { -namespace internal { - -class LinkManager : public hci::acl_manager::LeConnectionCallbacks { -public: - LinkManager(os::Handler* l2cap_handler, hci::AclManager* acl_manager, - FixedChannelServiceManagerImpl* service_manager, - DynamicChannelServiceManagerImpl* dynamic_service_manager, - l2cap::internal::ParameterProvider* parameter_provider) - : l2cap_handler_(l2cap_handler), - acl_manager_(acl_manager), - fixed_channel_service_manager_(service_manager), - dynamic_channel_service_manager_(dynamic_service_manager), - parameter_provider_(parameter_provider) { - acl_manager_->RegisterLeCallbacks(this, l2cap_handler_); - } - - LinkManager(const LinkManager&) = delete; - LinkManager& operator=(const LinkManager&) = delete; - - struct PendingFixedChannelConnection { - os::Handler* handler_; - FixedChannelManager::OnConnectionFailureCallback on_fail_callback_; - }; - - struct PendingLink { - std::vector<PendingFixedChannelConnection> pending_fixed_channel_connections_; - }; - - // ACL methods - - Link* GetLink(hci::AddressWithType address_with_type); - void OnLeConnectSuccess( - hci::AddressWithType connecting_address_with_type, - std::unique_ptr<hci::acl_manager::LeAclConnection> acl_connection) override; - void OnLeConnectFail(hci::AddressWithType address_with_type, hci::ErrorCode reason) override; - - // FixedChannelManager methods - - void ConnectFixedChannelServices(hci::AddressWithType address_with_type, - PendingFixedChannelConnection pending_fixed_channel_connection); - - // DynamicChannelManager methods - - void ConnectDynamicChannelServices( - hci::AddressWithType device, - Link::PendingDynamicChannelConnection pending_dynamic_channel_connection, Psm psm); - - void OnDisconnect(hci::AddressWithType address_with_type); - - // Link methods - - void RegisterLinkPropertyListener(os::Handler* handler, LinkPropertyListener* listener); - - void OnReadRemoteVersionInformationComplete(hci::ErrorCode hci_status, - hci::AddressWithType address_with_type, - uint8_t lmp_version, uint16_t manufacturer_name, - uint16_t sub_version); - - // Reported by link to indicate how many pending packets are remaining to be set. - // If there is anything outstanding, don't delete link - void OnPendingPacketChange(hci::AddressWithType remote, int num_packets); - -private: - // Dependencies - os::Handler* l2cap_handler_; - hci::AclManager* acl_manager_; - FixedChannelServiceManagerImpl* fixed_channel_service_manager_; - DynamicChannelServiceManagerImpl* dynamic_channel_service_manager_; - l2cap::internal::ParameterProvider* parameter_provider_; - - // Internal states - std::unordered_map<hci::AddressWithType, PendingLink> pending_links_; - std::unordered_map<hci::AddressWithType, Link> links_; - std::unordered_map<hci::AddressWithType, - std::list<std::pair<Psm, Link::PendingDynamicChannelConnection>>> - pending_dynamic_channels_; - os::Handler* link_property_callback_handler_ = nullptr; - LinkPropertyListener* link_property_listener_ = nullptr; - std::unordered_set<hci::AddressWithType> disconnected_links_; - std::unordered_set<hci::AddressWithType> links_with_pending_packets_; -}; - -} // namespace internal -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/internal/link_manager_test.cc b/system/gd/l2cap/le/internal/link_manager_test.cc deleted file mode 100644 index bfdaf51838..0000000000 --- a/system/gd/l2cap/le/internal/link_manager_test.cc +++ /dev/null @@ -1,620 +0,0 @@ -/* - * Copyright 2018 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 "l2cap/le/internal/link_manager.h" - -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include <future> -#include <thread> - -#include "common/bind.h" -#include "common/testing/bind_test_util.h" -#include "hci/acl_manager_mock.h" -#include "hci/address.h" -#include "l2cap/cid.h" -#include "l2cap/internal/parameter_provider_mock.h" -#include "l2cap/le/fixed_channel_manager.h" -#include "l2cap/le/internal/fixed_channel_service_impl_mock.h" -#include "l2cap/le/internal/fixed_channel_service_manager_impl_mock.h" -#include "os/handler.h" -#include "os/thread.h" - -namespace bluetooth { -namespace l2cap { -namespace le { -namespace internal { -namespace { - -using hci::testing::MockAclManager; -using hci::testing::MockLeAclConnection; -using l2cap::internal::testing::MockParameterProvider; -using ::testing::_; // Matcher to any value -using ::testing::ByMove; -using ::testing::DoAll; -using testing::MockFixedChannelServiceImpl; -using testing::MockFixedChannelServiceManagerImpl; -using ::testing::Return; -using ::testing::SaveArg; - -constexpr static auto kTestIdleDisconnectTimeoutLong = std::chrono::milliseconds(1000); -constexpr static auto kTestIdleDisconnectTimeoutShort = std::chrono::milliseconds(1000); - -class L2capLeLinkManagerTest : public ::testing::Test { -public: - static void SyncHandler(os::Handler* handler) { - std::promise<void> promise; - auto future = promise.get_future(); - handler->Post(common::BindOnce(&std::promise<void>::set_value, common::Unretained(&promise))); - future.wait_for(std::chrono::milliseconds(3)); - } - -protected: - void SetUp() override { - thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL); - l2cap_handler_ = new os::Handler(thread_); - user_handler_ = new os::Handler(thread_); - mock_parameter_provider_ = new MockParameterProvider; - EXPECT_CALL(*mock_parameter_provider_, GetLeLinkIdleDisconnectTimeout) - .WillRepeatedly(Return(kTestIdleDisconnectTimeoutLong)); - } - - void TearDown() override { - delete mock_parameter_provider_; - l2cap_handler_->Clear(); - delete l2cap_handler_; - user_handler_->Clear(); - delete user_handler_; - delete thread_; - } - - os::Thread* thread_ = nullptr; - os::Handler* l2cap_handler_ = nullptr; - os::Handler* user_handler_ = nullptr; - MockParameterProvider* mock_parameter_provider_ = nullptr; -}; - -TEST_F(L2capLeLinkManagerTest, connect_fixed_channel_service_without_acl) { - MockFixedChannelServiceManagerImpl mock_le_fixed_channel_service_manager; - MockAclManager mock_acl_manager; - hci::AddressWithType address_with_type({{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::RANDOM_DEVICE_ADDRESS); - - // Step 1: Verify callback registration with HCI - hci::acl_manager::LeConnectionCallbacks* hci_le_connection_callbacks = nullptr; - os::Handler* hci_callback_handler = nullptr; - EXPECT_CALL(mock_acl_manager, RegisterLeCallbacks(_, _)) - .WillOnce(DoAll(SaveArg<0>(&hci_le_connection_callbacks), - SaveArg<1>(&hci_callback_handler))); - LinkManager le_link_manager(l2cap_handler_, &mock_acl_manager, - &mock_le_fixed_channel_service_manager, nullptr, - mock_parameter_provider_); - EXPECT_EQ(hci_le_connection_callbacks, &le_link_manager); - EXPECT_EQ(hci_callback_handler, l2cap_handler_); - - // Register fake services - MockFixedChannelServiceImpl mock_service_1, mock_service_2; - std::vector<std::pair<Cid, FixedChannelServiceImpl*>> results; - results.emplace_back(kSmpBrCid, &mock_service_1); - results.emplace_back(kConnectionlessCid, &mock_service_2); - EXPECT_CALL(mock_le_fixed_channel_service_manager, GetRegisteredServices()) - .WillRepeatedly(Return(results)); - - // Step 2: Connect to fixed channel without ACL connection should trigger ACL connection process - EXPECT_CALL(mock_acl_manager, CreateLeConnection(address_with_type, true)).Times(1); - LinkManager::PendingFixedChannelConnection pending_fixed_channel_connection{ - .handler_ = user_handler_, - .on_fail_callback_ = - common::BindOnce([](FixedChannelManager::ConnectionResult result) { FAIL(); })}; - le_link_manager.ConnectFixedChannelServices(address_with_type, - std::move(pending_fixed_channel_connection)); - - // Step 3: ACL connection success event should trigger channel creation for all registered - // services - std::unique_ptr<MockLeAclConnection> acl_connection = std::make_unique<MockLeAclConnection>(); - EXPECT_CALL(*acl_connection, GetRemoteAddress()).WillRepeatedly(Return(address_with_type)); - hci::acl_manager::LeConnectionManagementCallbacks* connection_management_callbacks = nullptr; - os::Handler* connection_management_handler = nullptr; - EXPECT_CALL(*acl_connection, RegisterCallbacks(_, _)) - .WillOnce(DoAll(SaveArg<0>(&connection_management_callbacks), - SaveArg<1>(&connection_management_handler))); - std::unique_ptr<FixedChannel> channel_1, channel_2; - std::promise<void> promise_1, promise_2; - auto future_1 = promise_1.get_future(); - auto future_2 = promise_2.get_future(); - EXPECT_CALL(mock_service_1, NotifyChannelCreation(_)) - .WillOnce([&channel_1, &promise_1](std::unique_ptr<FixedChannel> channel) { - channel_1 = std::move(channel); - promise_1.set_value(); - }); - EXPECT_CALL(mock_service_2, NotifyChannelCreation(_)) - .WillOnce([&channel_2, &promise_2](std::unique_ptr<FixedChannel> channel) { - channel_2 = std::move(channel); - promise_2.set_value(); - }); - hci_callback_handler->Post( - common::BindOnce(&hci::acl_manager::LeConnectionCallbacks::OnLeConnectSuccess, - common::Unretained(hci_le_connection_callbacks), address_with_type, - std::move(acl_connection))); - SyncHandler(hci_callback_handler); - connection_management_handler->Post(common::BindOnce( - &hci::acl_manager::LeConnectionManagementCallbacks:: - OnReadRemoteVersionInformationComplete, - common::Unretained(connection_management_callbacks), hci::ErrorCode::SUCCESS, 0, 0, 0)); - auto future_1_status = future_1.wait_for(kTestIdleDisconnectTimeoutShort); - EXPECT_EQ(future_1_status, std::future_status::ready); - auto future_2_status = future_2.wait_for(kTestIdleDisconnectTimeoutShort); - EXPECT_EQ(future_2_status, std::future_status::ready); - ASSERT_NE(channel_1, nullptr); - ASSERT_NE(channel_2, nullptr); - - // Step 4: Calling ConnectServices() to the same device will not trigger another connection - // attempt - FixedChannelManager::ConnectionResult my_result; - LinkManager::PendingFixedChannelConnection pending_fixed_channel_connection_2{ - .handler_ = user_handler_, - .on_fail_callback_ = common::testing::BindLambdaForTesting( - [&my_result](FixedChannelManager::ConnectionResult result) { - my_result = result; - })}; - le_link_manager.ConnectFixedChannelServices(address_with_type, - std::move(pending_fixed_channel_connection_2)); - SyncHandler(user_handler_); - EXPECT_EQ(my_result.connection_result_code, - FixedChannelManager::ConnectionResultCode::FAIL_ALL_SERVICES_HAVE_CHANNEL); - - // Step 5: Register new service will cause new channels to be created during ConnectServices() - MockFixedChannelServiceImpl mock_service_3; - results.emplace_back(kSmpBrCid + 1, &mock_service_3); - EXPECT_CALL(mock_le_fixed_channel_service_manager, GetRegisteredServices()) - .WillRepeatedly(Return(results)); - LinkManager::PendingFixedChannelConnection pending_fixed_channel_connection_3{ - .handler_ = user_handler_, - .on_fail_callback_ = - common::BindOnce([](FixedChannelManager::ConnectionResult result) { FAIL(); })}; - std::unique_ptr<FixedChannel> channel_3; - std::promise<void> promise_3; - auto future_3 = promise_3.get_future(); - EXPECT_CALL(mock_service_3, NotifyChannelCreation(_)) - .WillOnce([&channel_3, &promise_3](std::unique_ptr<FixedChannel> channel) { - channel_3 = std::move(channel); - promise_3.set_value(); - }); - le_link_manager.ConnectFixedChannelServices(address_with_type, - std::move(pending_fixed_channel_connection_3)); - auto future_3_status = future_3.wait_for(kTestIdleDisconnectTimeoutShort); - EXPECT_EQ(future_3_status, std::future_status::ready); - EXPECT_NE(channel_3, nullptr); - - connection_management_handler->Post( - common::BindOnce(&hci::acl_manager::LeConnectionManagementCallbacks::OnDisconnection, - common::Unretained(connection_management_callbacks), - hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION)); - SyncHandler(connection_management_handler); -} - -TEST_F(L2capLeLinkManagerTest, connect_fixed_channel_service_without_acl_with_no_service) { - MockFixedChannelServiceManagerImpl mock_le_fixed_channel_service_manager; - MockAclManager mock_acl_manager; - hci::AddressWithType address_with_type({{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::PUBLIC_DEVICE_ADDRESS); - - // Step 1: Verify callback registration with HCI - hci::acl_manager::LeConnectionCallbacks* hci_le_connection_callbacks = nullptr; - os::Handler* hci_callback_handler = nullptr; - EXPECT_CALL(mock_acl_manager, RegisterLeCallbacks(_, _)) - .WillOnce(DoAll(SaveArg<0>(&hci_le_connection_callbacks), - SaveArg<1>(&hci_callback_handler))); - LinkManager le_link_manager(l2cap_handler_, &mock_acl_manager, - &mock_le_fixed_channel_service_manager, nullptr, - mock_parameter_provider_); - EXPECT_EQ(hci_le_connection_callbacks, &le_link_manager); - EXPECT_EQ(hci_callback_handler, l2cap_handler_); - - // Make sure no service is registered - std::vector<std::pair<Cid, FixedChannelServiceImpl*>> results; - EXPECT_CALL(mock_le_fixed_channel_service_manager, GetRegisteredServices()) - .WillRepeatedly(Return(results)); - - // Step 2: Connect to fixed channel without any service registered will result in failure - EXPECT_CALL(mock_acl_manager, CreateLeConnection(address_with_type, true)).Times(0); - FixedChannelManager::ConnectionResult my_result; - LinkManager::PendingFixedChannelConnection pending_fixed_channel_connection{ - .handler_ = user_handler_, - .on_fail_callback_ = common::testing::BindLambdaForTesting( - [&my_result](FixedChannelManager::ConnectionResult result) { - my_result = result; - })}; - le_link_manager.ConnectFixedChannelServices(address_with_type, - std::move(pending_fixed_channel_connection)); - SyncHandler(user_handler_); - EXPECT_EQ(my_result.connection_result_code, - FixedChannelManager::ConnectionResultCode::FAIL_NO_SERVICE_REGISTERED); -} - -TEST_F(L2capLeLinkManagerTest, connect_fixed_channel_service_without_acl_with_hci_failure) { - MockFixedChannelServiceManagerImpl mock_le_fixed_channel_service_manager; - MockAclManager mock_acl_manager; - hci::AddressWithType address_with_type({{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::RANDOM_DEVICE_ADDRESS); - - // Step 1: Verify callback registration with HCI - hci::acl_manager::LeConnectionCallbacks* hci_le_connection_callbacks = nullptr; - os::Handler* hci_callback_handler = nullptr; - EXPECT_CALL(mock_acl_manager, RegisterLeCallbacks(_, _)) - .WillOnce(DoAll(SaveArg<0>(&hci_le_connection_callbacks), - SaveArg<1>(&hci_callback_handler))); - LinkManager le_link_manager(l2cap_handler_, &mock_acl_manager, - &mock_le_fixed_channel_service_manager, nullptr, - mock_parameter_provider_); - EXPECT_EQ(hci_le_connection_callbacks, &le_link_manager); - EXPECT_EQ(hci_callback_handler, l2cap_handler_); - - // Register fake services - MockFixedChannelServiceImpl mock_service_1; - std::vector<std::pair<Cid, FixedChannelServiceImpl*>> results; - results.emplace_back(kSmpBrCid, &mock_service_1); - EXPECT_CALL(mock_le_fixed_channel_service_manager, GetRegisteredServices()) - .WillRepeatedly(Return(results)); - - // Step 2: Connect to fixed channel without ACL connection should trigger ACL connection process - EXPECT_CALL(mock_acl_manager, CreateLeConnection(address_with_type, true)).Times(1); - FixedChannelManager::ConnectionResult my_result; - LinkManager::PendingFixedChannelConnection pending_fixed_channel_connection{ - .handler_ = user_handler_, - .on_fail_callback_ = common::testing::BindLambdaForTesting( - [&my_result](FixedChannelManager::ConnectionResult result) { - my_result = result; - })}; - le_link_manager.ConnectFixedChannelServices(address_with_type, - std::move(pending_fixed_channel_connection)); - - // Step 3: ACL connection failure event should trigger connection failure callback - EXPECT_CALL(mock_service_1, NotifyChannelCreation(_)).Times(0); - hci_callback_handler->Post( - common::BindOnce(&hci::acl_manager::LeConnectionCallbacks::OnLeConnectFail, - common::Unretained(hci_le_connection_callbacks), address_with_type, - hci::ErrorCode::PAGE_TIMEOUT)); - SyncHandler(hci_callback_handler); - SyncHandler(user_handler_); - EXPECT_EQ(my_result.connection_result_code, - FixedChannelManager::ConnectionResultCode::FAIL_HCI_ERROR); - EXPECT_EQ(my_result.hci_error, hci::ErrorCode::PAGE_TIMEOUT); -} - -TEST_F(L2capLeLinkManagerTest, not_acquiring_channels_should_disconnect_acl_after_timeout) { - EXPECT_CALL(*mock_parameter_provider_, GetLeLinkIdleDisconnectTimeout) - .WillRepeatedly(Return(kTestIdleDisconnectTimeoutShort)); - MockFixedChannelServiceManagerImpl mock_le_fixed_channel_service_manager; - MockAclManager mock_acl_manager; - hci::AddressWithType address_with_type({{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::RANDOM_DEVICE_ADDRESS); - - // Step 1: Verify callback registration with HCI - hci::acl_manager::LeConnectionCallbacks* hci_le_connection_callbacks = nullptr; - os::Handler* hci_callback_handler = nullptr; - EXPECT_CALL(mock_acl_manager, RegisterLeCallbacks(_, _)) - .WillOnce(DoAll(SaveArg<0>(&hci_le_connection_callbacks), - SaveArg<1>(&hci_callback_handler))); - LinkManager le_link_manager(l2cap_handler_, &mock_acl_manager, - &mock_le_fixed_channel_service_manager, nullptr, - mock_parameter_provider_); - EXPECT_EQ(hci_le_connection_callbacks, &le_link_manager); - EXPECT_EQ(hci_callback_handler, l2cap_handler_); - - // Register fake services - MockFixedChannelServiceImpl mock_service_1, mock_service_2; - std::vector<std::pair<Cid, FixedChannelServiceImpl*>> results; - results.emplace_back(kSmpBrCid, &mock_service_1); - results.emplace_back(kConnectionlessCid, &mock_service_2); - EXPECT_CALL(mock_le_fixed_channel_service_manager, GetRegisteredServices()) - .WillRepeatedly(Return(results)); - - // Step 2: Connect to fixed channel without ACL connection should trigger ACL connection process - EXPECT_CALL(mock_acl_manager, CreateLeConnection(address_with_type, true)).Times(1); - LinkManager::PendingFixedChannelConnection pending_fixed_channel_connection{ - .handler_ = user_handler_, - .on_fail_callback_ = - common::BindOnce([](FixedChannelManager::ConnectionResult result) { FAIL(); })}; - le_link_manager.ConnectFixedChannelServices(address_with_type, - std::move(pending_fixed_channel_connection)); - - // Step 3: ACL connection success event should trigger channel creation for all registered - // services - auto* raw_acl_connection = new MockLeAclConnection(); - std::unique_ptr<MockLeAclConnection> acl_connection(raw_acl_connection); - EXPECT_CALL(*acl_connection, GetRemoteAddress()).WillRepeatedly(Return(address_with_type)); - hci::acl_manager::LeConnectionManagementCallbacks* connection_management_callbacks = nullptr; - os::Handler* connection_management_handler = nullptr; - EXPECT_CALL(*acl_connection, RegisterCallbacks(_, _)) - .WillOnce(DoAll(SaveArg<0>(&connection_management_callbacks), - SaveArg<1>(&connection_management_handler))); - std::unique_ptr<FixedChannel> channel_1, channel_2; - std::promise<void> promise_1, promise_2; - auto future_1 = promise_1.get_future(); - auto future_2 = promise_2.get_future(); - EXPECT_CALL(mock_service_1, NotifyChannelCreation(_)) - .WillOnce([&channel_1, &promise_1](std::unique_ptr<FixedChannel> channel) { - channel_1 = std::move(channel); - promise_1.set_value(); - }); - EXPECT_CALL(mock_service_2, NotifyChannelCreation(_)) - .WillOnce([&channel_2, &promise_2](std::unique_ptr<FixedChannel> channel) { - channel_2 = std::move(channel); - promise_2.set_value(); - }); - hci_callback_handler->Post( - common::BindOnce(&hci::acl_manager::LeConnectionCallbacks::OnLeConnectSuccess, - common::Unretained(hci_le_connection_callbacks), address_with_type, - std::move(acl_connection))); - SyncHandler(hci_callback_handler); - connection_management_handler->Post(common::BindOnce( - &hci::acl_manager::LeConnectionManagementCallbacks:: - OnReadRemoteVersionInformationComplete, - common::Unretained(connection_management_callbacks), hci::ErrorCode::SUCCESS, 0, 0, 0)); - auto future_1_status = future_1.wait_for(kTestIdleDisconnectTimeoutShort); - EXPECT_EQ(future_1_status, std::future_status::ready); - EXPECT_NE(channel_1, nullptr); - auto future_2_status = future_2.wait_for(kTestIdleDisconnectTimeoutShort); - EXPECT_EQ(future_2_status, std::future_status::ready); - EXPECT_NE(channel_2, nullptr); - hci::ErrorCode status_1 = hci::ErrorCode::SUCCESS; - channel_1->RegisterOnCloseCallback( - user_handler_, - common::testing::BindLambdaForTesting([&](hci::ErrorCode status) { status_1 = status; })); - hci::ErrorCode status_2 = hci::ErrorCode::SUCCESS; - channel_2->RegisterOnCloseCallback( - user_handler_, - common::testing::BindLambdaForTesting([&](hci::ErrorCode status) { status_2 = status; })); - - // Step 4: Leave channel IDLE long enough, they will disconnect - EXPECT_CALL(*raw_acl_connection, - Disconnect(hci::DisconnectReason::REMOTE_USER_TERMINATED_CONNECTION)) - .Times(1); - std::this_thread::sleep_for(kTestIdleDisconnectTimeoutShort * 1.2); - connection_management_handler->Post( - common::BindOnce(&hci::acl_manager::LeConnectionManagementCallbacks::OnDisconnection, - common::Unretained(connection_management_callbacks), - hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST)); - SyncHandler(connection_management_handler); - - // Step 5: Link disconnect will trigger all callbacks - SyncHandler(user_handler_); - EXPECT_EQ(hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST, status_1); - EXPECT_EQ(hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST, status_2); -} - -TEST_F(L2capLeLinkManagerTest, acquiring_channels_should_not_disconnect_acl_after_timeout) { - EXPECT_CALL(*mock_parameter_provider_, GetLeLinkIdleDisconnectTimeout) - .WillRepeatedly(Return(kTestIdleDisconnectTimeoutShort)); - MockFixedChannelServiceManagerImpl mock_le_fixed_channel_service_manager; - MockAclManager mock_acl_manager; - hci::AddressWithType address_with_type({{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::RANDOM_DEVICE_ADDRESS); - - // Step 1: Verify callback registration with HCI - hci::acl_manager::LeConnectionCallbacks* hci_le_connection_callbacks = nullptr; - os::Handler* hci_callback_handler = nullptr; - EXPECT_CALL(mock_acl_manager, RegisterLeCallbacks(_, _)) - .WillOnce(DoAll(SaveArg<0>(&hci_le_connection_callbacks), - SaveArg<1>(&hci_callback_handler))); - LinkManager le_link_manager(l2cap_handler_, &mock_acl_manager, - &mock_le_fixed_channel_service_manager, nullptr, - mock_parameter_provider_); - EXPECT_EQ(hci_le_connection_callbacks, &le_link_manager); - EXPECT_EQ(hci_callback_handler, l2cap_handler_); - - // Register fake services - MockFixedChannelServiceImpl mock_service_1, mock_service_2; - std::vector<std::pair<Cid, FixedChannelServiceImpl*>> results; - results.emplace_back(kSmpBrCid, &mock_service_1); - results.emplace_back(kConnectionlessCid, &mock_service_2); - EXPECT_CALL(mock_le_fixed_channel_service_manager, GetRegisteredServices()) - .WillRepeatedly(Return(results)); - - // Step 2: Connect to fixed channel without ACL connection should trigger ACL connection process - EXPECT_CALL(mock_acl_manager, CreateLeConnection(address_with_type, true)).Times(1); - LinkManager::PendingFixedChannelConnection pending_fixed_channel_connection{ - .handler_ = user_handler_, - .on_fail_callback_ = - common::BindOnce([](FixedChannelManager::ConnectionResult result) { FAIL(); })}; - le_link_manager.ConnectFixedChannelServices(address_with_type, - std::move(pending_fixed_channel_connection)); - - // Step 3: ACL connection success event should trigger channel creation for all registered - // services - auto* raw_acl_connection = new MockLeAclConnection(); - std::unique_ptr<MockLeAclConnection> acl_connection(raw_acl_connection); - EXPECT_CALL(*acl_connection, GetRemoteAddress()).WillRepeatedly(Return(address_with_type)); - hci::acl_manager::LeConnectionManagementCallbacks* connection_management_callbacks = nullptr; - os::Handler* connection_management_handler = nullptr; - EXPECT_CALL(*acl_connection, RegisterCallbacks(_, _)) - .WillOnce(DoAll(SaveArg<0>(&connection_management_callbacks), - SaveArg<1>(&connection_management_handler))); - std::unique_ptr<FixedChannel> channel_1, channel_2; - std::promise<void> promise_1, promise_2; - auto future_1 = promise_1.get_future(); - auto future_2 = promise_2.get_future(); - EXPECT_CALL(mock_service_1, NotifyChannelCreation(_)) - .WillOnce([&channel_1, &promise_1](std::unique_ptr<FixedChannel> channel) { - channel_1 = std::move(channel); - promise_1.set_value(); - }); - EXPECT_CALL(mock_service_2, NotifyChannelCreation(_)) - .WillOnce([&channel_2, &promise_2](std::unique_ptr<FixedChannel> channel) { - channel_2 = std::move(channel); - promise_2.set_value(); - }); - hci_callback_handler->Post( - common::BindOnce(&hci::acl_manager::LeConnectionCallbacks::OnLeConnectSuccess, - common::Unretained(hci_le_connection_callbacks), address_with_type, - std::move(acl_connection))); - SyncHandler(hci_callback_handler); - connection_management_handler->Post(common::BindOnce( - &hci::acl_manager::LeConnectionManagementCallbacks:: - OnReadRemoteVersionInformationComplete, - common::Unretained(connection_management_callbacks), hci::ErrorCode::SUCCESS, 0, 0, 0)); - auto future_1_status = future_1.wait_for(kTestIdleDisconnectTimeoutShort); - EXPECT_EQ(future_1_status, std::future_status::ready); - EXPECT_NE(channel_1, nullptr); - auto future_2_status = future_2.wait_for(kTestIdleDisconnectTimeoutShort); - EXPECT_EQ(future_2_status, std::future_status::ready); - EXPECT_NE(channel_2, nullptr); - hci::ErrorCode status_1 = hci::ErrorCode::SUCCESS; - channel_1->RegisterOnCloseCallback( - user_handler_, - common::testing::BindLambdaForTesting([&](hci::ErrorCode status) { status_1 = status; })); - hci::ErrorCode status_2 = hci::ErrorCode::SUCCESS; - channel_2->RegisterOnCloseCallback( - user_handler_, - common::testing::BindLambdaForTesting([&](hci::ErrorCode status) { status_2 = status; })); - - channel_1->Acquire(); - - // Step 4: ave channel IDLE, it won't disconnect to due acquired channel 1 - EXPECT_CALL(*raw_acl_connection, - Disconnect(hci::DisconnectReason::REMOTE_USER_TERMINATED_CONNECTION)) - .Times(0); - std::this_thread::sleep_for(kTestIdleDisconnectTimeoutShort * 2); - - // Step 5: Link disconnect will trigger all callbacks - connection_management_handler->Post( - common::BindOnce(&hci::acl_manager::LeConnectionManagementCallbacks::OnDisconnection, - common::Unretained(connection_management_callbacks), - hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST)); - SyncHandler(connection_management_handler); - SyncHandler(user_handler_); - EXPECT_EQ(hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST, status_1); - EXPECT_EQ(hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST, status_2); -} - -TEST_F(L2capLeLinkManagerTest, acquiring_and_releasing_channels_should_eventually_disconnect_acl) { - EXPECT_CALL(*mock_parameter_provider_, GetLeLinkIdleDisconnectTimeout) - .WillRepeatedly(Return(kTestIdleDisconnectTimeoutShort)); - MockFixedChannelServiceManagerImpl mock_le_fixed_channel_service_manager; - MockAclManager mock_acl_manager; - hci::AddressWithType address_with_type({{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - hci::AddressType::PUBLIC_IDENTITY_ADDRESS); - - // Step 1: Verify callback registration with HCI - hci::acl_manager::LeConnectionCallbacks* hci_le_connection_callbacks = nullptr; - os::Handler* hci_callback_handler = nullptr; - EXPECT_CALL(mock_acl_manager, RegisterLeCallbacks(_, _)) - .WillOnce(DoAll(SaveArg<0>(&hci_le_connection_callbacks), - SaveArg<1>(&hci_callback_handler))); - LinkManager le_link_manager(l2cap_handler_, &mock_acl_manager, - &mock_le_fixed_channel_service_manager, nullptr, - mock_parameter_provider_); - EXPECT_EQ(hci_le_connection_callbacks, &le_link_manager); - EXPECT_EQ(hci_callback_handler, l2cap_handler_); - - // Register fake services - MockFixedChannelServiceImpl mock_service_1, mock_service_2; - std::vector<std::pair<Cid, FixedChannelServiceImpl*>> results; - results.emplace_back(kSmpBrCid, &mock_service_1); - results.emplace_back(kConnectionlessCid, &mock_service_2); - EXPECT_CALL(mock_le_fixed_channel_service_manager, GetRegisteredServices()) - .WillRepeatedly(Return(results)); - - // Step 2: Connect to fixed channel without ACL connection should trigger ACL connection process - EXPECT_CALL(mock_acl_manager, CreateLeConnection(address_with_type, true)).Times(1); - LinkManager::PendingFixedChannelConnection pending_fixed_channel_connection{ - .handler_ = user_handler_, - .on_fail_callback_ = - common::BindOnce([](FixedChannelManager::ConnectionResult result) { FAIL(); })}; - le_link_manager.ConnectFixedChannelServices(address_with_type, - std::move(pending_fixed_channel_connection)); - - // Step 3: ACL connection success event should trigger channel creation for all registered - // services - auto* raw_acl_connection = new MockLeAclConnection(); - std::unique_ptr<MockLeAclConnection> acl_connection(raw_acl_connection); - EXPECT_CALL(*acl_connection, GetRemoteAddress()).WillRepeatedly(Return(address_with_type)); - hci::acl_manager::LeConnectionManagementCallbacks* connection_management_callbacks = nullptr; - os::Handler* connection_management_handler = nullptr; - EXPECT_CALL(*acl_connection, RegisterCallbacks(_, _)) - .WillOnce(DoAll(SaveArg<0>(&connection_management_callbacks), - SaveArg<1>(&connection_management_handler))); - std::unique_ptr<FixedChannel> channel_1, channel_2; - std::promise<void> promise_1, promise_2; - auto future_1 = promise_1.get_future(); - auto future_2 = promise_2.get_future(); - EXPECT_CALL(mock_service_1, NotifyChannelCreation(_)) - .WillOnce([&channel_1, &promise_1](std::unique_ptr<FixedChannel> channel) { - channel_1 = std::move(channel); - promise_1.set_value(); - }); - EXPECT_CALL(mock_service_2, NotifyChannelCreation(_)) - .WillOnce([&channel_2, &promise_2](std::unique_ptr<FixedChannel> channel) { - channel_2 = std::move(channel); - promise_2.set_value(); - }); - hci_callback_handler->Post( - common::BindOnce(&hci::acl_manager::LeConnectionCallbacks::OnLeConnectSuccess, - common::Unretained(hci_le_connection_callbacks), address_with_type, - std::move(acl_connection))); - SyncHandler(hci_callback_handler); - connection_management_handler->Post(common::BindOnce( - &hci::acl_manager::LeConnectionManagementCallbacks:: - OnReadRemoteVersionInformationComplete, - common::Unretained(connection_management_callbacks), hci::ErrorCode::SUCCESS, 0, 0, 0)); - auto future_1_status = future_1.wait_for(kTestIdleDisconnectTimeoutShort); - EXPECT_EQ(future_1_status, std::future_status::ready); - EXPECT_NE(channel_1, nullptr); - auto future_2_status = future_2.wait_for(kTestIdleDisconnectTimeoutShort); - EXPECT_EQ(future_2_status, std::future_status::ready); - EXPECT_NE(channel_2, nullptr); - hci::ErrorCode status_1 = hci::ErrorCode::SUCCESS; - channel_1->RegisterOnCloseCallback( - user_handler_, - common::testing::BindLambdaForTesting([&](hci::ErrorCode status) { status_1 = status; })); - hci::ErrorCode status_2 = hci::ErrorCode::SUCCESS; - channel_2->RegisterOnCloseCallback( - user_handler_, - common::testing::BindLambdaForTesting([&](hci::ErrorCode status) { status_2 = status; })); - - channel_1->Acquire(); - - // Step 4: ave channel IDLE, it won't disconnect to due acquired channel 1 - EXPECT_CALL(*raw_acl_connection, - Disconnect(hci::DisconnectReason::REMOTE_USER_TERMINATED_CONNECTION)) - .Times(0); - std::this_thread::sleep_for(kTestIdleDisconnectTimeoutShort * 2); - - // Step 5: ave channel IDLE long enough, they will disconnect - channel_1->Release(); - EXPECT_CALL(*raw_acl_connection, - Disconnect(hci::DisconnectReason::REMOTE_USER_TERMINATED_CONNECTION)) - .Times(1); - std::this_thread::sleep_for(kTestIdleDisconnectTimeoutShort * 1.2); - - // Step 6: Link disconnect will trigger all callbacks - connection_management_handler->Post( - common::BindOnce(&hci::acl_manager::LeConnectionManagementCallbacks::OnDisconnection, - common::Unretained(connection_management_callbacks), - hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST)); - SyncHandler(connection_management_handler); - SyncHandler(user_handler_); - EXPECT_EQ(hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST, status_1); - EXPECT_EQ(hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST, status_2); -} - -} // namespace -} // namespace internal -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/internal/link_mock.h b/system/gd/l2cap/le/internal/link_mock.h deleted file mode 100644 index 3caac2ac38..0000000000 --- a/system/gd/l2cap/le/internal/link_mock.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2019 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. - */ -#pragma once - -#include <gmock/gmock.h> - -#include "hci/acl_manager_mock.h" -#include "hci/address_with_type.h" -#include "l2cap/internal/scheduler_mock.h" -#include "l2cap/le/internal/link.h" - -// Unit test interfaces -namespace bluetooth { -namespace l2cap { -namespace le { -namespace internal { -namespace testing { - -using hci::testing::MockLeAclConnection; - -class MockLink : public Link { -public: - explicit MockLink(os::Handler* handler, l2cap::internal::ParameterProvider* parameter_provider, - std::unique_ptr<MockLeAclConnection> mock_acl_connection, - LinkManager* link_manager) - : Link(handler, std::move(mock_acl_connection), parameter_provider, nullptr, nullptr, - link_manager) {} - - MOCK_METHOD(hci::AddressWithType, GetDevice, (), (const, override)); - MOCK_METHOD(hci::Role, GetRole, (), (override)); - MOCK_METHOD(void, OnAclDisconnected, (hci::ErrorCode status), (override)); - MOCK_METHOD(void, Disconnect, (), (override)); - MOCK_METHOD(std::shared_ptr<FixedChannelImpl>, AllocateFixedChannel, - (Cid cid, SecurityPolicy security_policy), (override)); - MOCK_METHOD(bool, IsFixedChannelAllocated, (Cid cid), (override)); - MOCK_METHOD(void, RefreshRefCount, (), (override)); -}; - -} // namespace testing -} // namespace internal -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/internal/signalling_manager.cc b/system/gd/l2cap/le/internal/signalling_manager.cc deleted file mode 100644 index e1b480935d..0000000000 --- a/system/gd/l2cap/le/internal/signalling_manager.cc +++ /dev/null @@ -1,594 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/le/internal/signalling_manager.h" - -#include <bluetooth/log.h> - -#include <chrono> - -#include "common/bind.h" -#include "l2cap/internal/data_pipeline_manager.h" -#include "l2cap/internal/dynamic_channel_impl.h" -#include "l2cap/internal/le_credit_based_channel_data_controller.h" -#include "l2cap/l2cap_packets.h" -#include "l2cap/le/internal/link.h" -#include "os/log.h" -#include "packet/raw_builder.h" - -namespace bluetooth { -namespace l2cap { -namespace le { -namespace internal { - -static constexpr auto kTimeout = std::chrono::seconds(3); - -LeSignallingManager::LeSignallingManager( - os::Handler* handler, Link* link, - l2cap::internal::DataPipelineManager* data_pipeline_manager, - DynamicChannelServiceManagerImpl* dynamic_service_manager, - l2cap::internal::DynamicChannelAllocator* channel_allocator) - : handler_(handler), - link_(link), - data_pipeline_manager_(data_pipeline_manager), - dynamic_service_manager_(dynamic_service_manager), - channel_allocator_(channel_allocator), - alarm_(handler) { - log::assert_that(handler_ != nullptr, "assert failed: handler_ != nullptr"); - log::assert_that(link_ != nullptr, "assert failed: link_ != nullptr"); - signalling_channel_ = link_->AllocateFixedChannel( - kLeSignallingCid, SecurityPolicy::NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK); - signalling_channel_->GetQueueUpEnd()->RegisterDequeue( - handler_, - common::Bind(&LeSignallingManager::on_incoming_packet, common::Unretained(this))); - enqueue_buffer_ = std::make_unique<os::EnqueueBuffer<packet::BasePacketBuilder>>( - signalling_channel_->GetQueueUpEnd()); -} - -LeSignallingManager::~LeSignallingManager() { - enqueue_buffer_.reset(); - signalling_channel_->GetQueueUpEnd()->UnregisterDequeue(); - signalling_channel_ = nullptr; -} - -void LeSignallingManager::SendConnectionRequest(Psm psm, Cid local_cid, Mtu mtu) { - dynamic_service_manager_->GetSecurityEnforcementInterface()->Enforce( - link_->GetDevice(), dynamic_service_manager_->GetService(psm)->GetSecurityPolicy(), - handler_->BindOnceOn(this, &LeSignallingManager::on_security_result_for_outgoing, psm, - local_cid, mtu)); -} - -void LeSignallingManager::on_security_result_for_outgoing(Psm psm, Cid local_cid, Mtu mtu, - bool result) { - if (!result) { - log::warn("Security requirement can't be satisfied. Dropping connection request"); - return; - } - - PendingCommand pending_command = PendingCommand::CreditBasedConnectionRequest( - next_signal_id_, psm, local_cid, mtu, link_->GetMps(), link_->GetInitialCredit()); - next_signal_id_++; - pending_commands_.push(pending_command); - if (pending_commands_.size() == 1) { - handle_send_next_command(); - } -} - -void LeSignallingManager::SendDisconnectRequest(Cid scid, Cid dcid) { - PendingCommand pending_command = - PendingCommand::DisconnectionRequest(next_signal_id_, scid, dcid); - next_signal_id_++; - pending_commands_.push(pending_command); - if (pending_commands_.size() == 1) { - handle_send_next_command(); - } -} - -void LeSignallingManager::SendConnectionParameterUpdateRequest(uint16_t interval_min, - uint16_t interval_max, - uint16_t peripheral_latency, - uint16_t timeout_multiplier) { - PendingCommand pending_command = PendingCommand::ConnectionParameterUpdate( - next_signal_id_, interval_min, interval_max, peripheral_latency, timeout_multiplier); - next_signal_id_++; - pending_commands_.push(pending_command); - if (pending_commands_.size() == 1) { - handle_send_next_command(); - } -} - -void LeSignallingManager::SendConnectionParameterUpdateResponse( - SignalId signal_id, ConnectionParameterUpdateResponseResult result) { - auto builder = ConnectionParameterUpdateResponseBuilder::Create(signal_id.Value(), result); - enqueue_buffer_->Enqueue(std::move(builder), handler_); -} - -void LeSignallingManager::SendCredit(Cid local_cid, uint16_t credits) { - auto builder = LeFlowControlCreditBuilder::Create(next_signal_id_.Value(), local_cid, credits); - next_signal_id_++; - enqueue_buffer_->Enqueue(std::move(builder), handler_); -} - -void LeSignallingManager::SendEnhancedConnectionRequest(Psm /* psm */, - std::vector<Cid> /* local_cid */, - Mtu /* mtu */) {} - -void LeSignallingManager::SendEnhancedReconfigureRequest(std::vector<Cid> /* local_cid */, - Mtu /* mtu */) {} - -void LeSignallingManager::CancelAlarm() { alarm_.Cancel(); } - -void LeSignallingManager::OnCommandReject(LeCommandRejectView command_reject_view) { - auto signal_id = command_reject_view.GetIdentifier(); - if (signal_id != command_just_sent_.signal_id_) { - log::warn("Unexpected response: no pending request"); - return; - } - alarm_.Cancel(); - if (command_just_sent_.command_code_ == LeCommandCode::LE_CREDIT_BASED_CONNECTION_REQUEST) { - link_->OnOutgoingConnectionRequestFail( - command_just_sent_.source_cid_, - LeCreditBasedConnectionResponseResult::NO_RESOURCES_AVAILABLE); - } - handle_send_next_command(); - - log::warn("Command rejected"); -} - -void LeSignallingManager::OnConnectionParameterUpdateRequest(SignalId signal_id, - uint16_t interval_min, - uint16_t interval_max, - uint16_t peripheral_latency, - uint16_t timeout_multiplier) { - if (link_->GetRole() == hci::Role::PERIPHERAL) { - log::warn("Received request from LL central"); - auto builder = LeCommandRejectNotUnderstoodBuilder::Create(signal_id.Value()); - enqueue_buffer_->Enqueue(std::move(builder), handler_); - return; - } - - if (!link_->CheckConnectionParameters(interval_min, interval_max, peripheral_latency, - timeout_multiplier)) { - log::warn("Received invalid connection parameter update request from LL central"); - auto builder = ConnectionParameterUpdateResponseBuilder::Create( - signal_id.Value(), ConnectionParameterUpdateResponseResult::REJECTED); - enqueue_buffer_->Enqueue(std::move(builder), handler_); - return; - } - link_->UpdateConnectionParameterFromRemote(signal_id, interval_min, interval_max, - peripheral_latency, timeout_multiplier); -} - -void LeSignallingManager::OnConnectionParameterUpdateResponse( - SignalId signal_id, ConnectionParameterUpdateResponseResult result) { - if (signal_id != command_just_sent_.signal_id_) { - log::warn("Unexpected response: no pending request"); - return; - } - if (command_just_sent_.command_code_ != LeCommandCode::CONNECTION_PARAMETER_UPDATE_REQUEST) { - log::warn("Unexpected response: no pending request"); - return; - } - alarm_.Cancel(); - command_just_sent_.signal_id_ = kInitialSignalId; - if (result != ConnectionParameterUpdateResponseResult::ACCEPTED) { - log::error("Connection parameter update is not accepted"); - } -} - -void LeSignallingManager::OnConnectionRequest(SignalId signal_id, Psm psm, Cid remote_cid, Mtu mtu, - uint16_t mps, uint16_t initial_credits) { - if (remote_cid == kInvalidCid) { - log::warn("Invalid remote cid received from remote psm:{} remote_cid:{}", psm, remote_cid); - send_connection_response(signal_id, kInvalidCid, 0, 0, 0, - LeCreditBasedConnectionResponseResult::INVALID_SOURCE_CID); - return; - } - - if (channel_allocator_->IsPsmUsed(psm)) { - log::warn("Psm already exists"); - send_connection_response(signal_id, kInvalidCid, 0, 0, 0, - LeCreditBasedConnectionResponseResult::LE_PSM_NOT_SUPPORTED); - return; - } - - if (!dynamic_service_manager_->IsServiceRegistered(psm)) { - log::info("Service for this psm ({}) is not registered", psm); - send_connection_response(signal_id, kInvalidCid, 0, 0, 0, - LeCreditBasedConnectionResponseResult::LE_PSM_NOT_SUPPORTED); - return; - } - - PendingConnection pending{ - .remote_cid = remote_cid, - .mtu = mtu, - .max_pdu_size = mps, - .initial_credits = initial_credits, - .incoming_signal_id = signal_id, - }; - dynamic_service_manager_->GetSecurityEnforcementInterface()->Enforce( - link_->GetDevice(), dynamic_service_manager_->GetService(psm)->GetSecurityPolicy(), - handler_->BindOnceOn(this, &LeSignallingManager::on_security_result_for_incoming, psm, - pending)); -} - -void LeSignallingManager::on_security_result_for_incoming(Psm psm, PendingConnection request, - bool result) { - auto signal_id = request.incoming_signal_id; - auto* service = dynamic_service_manager_->GetService(psm); - if (!result) { - auto security_policy = service->GetSecurityPolicy(); - switch (security_policy) { - case SecurityPolicy::NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK: - log::error("If no security requirement, we should never fail"); - break; - case SecurityPolicy::ENCRYPTED_TRANSPORT: - send_connection_response( - signal_id, kInvalidCid, 0, 0, 0, - LeCreditBasedConnectionResponseResult::INSUFFICIENT_AUTHENTICATION); - return; - case SecurityPolicy::AUTHENTICATED_ENCRYPTED_TRANSPORT: - case SecurityPolicy::BEST: - send_connection_response( - signal_id, kInvalidCid, 0, 0, 0, - LeCreditBasedConnectionResponseResult::INSUFFICIENT_AUTHENTICATION); - return; - case SecurityPolicy::_NOT_FOR_YOU__AUTHENTICATED_PAIRING_WITH_128_BIT_KEY: - send_connection_response( - signal_id, kInvalidCid, 0, 0, 0, - LeCreditBasedConnectionResponseResult::INSUFFICIENT_ENCRYPTION_KEY_SIZE); - return; - case SecurityPolicy::_NOT_FOR_YOU__AUTHORIZATION: - send_connection_response(signal_id, kInvalidCid, 0, 0, 0, - LeCreditBasedConnectionResponseResult::INSUFFICIENT_AUTHORIZATION); - return; - } - } - auto config = service->GetConfigOption(); - auto local_mtu = config.mtu; - auto local_mps = link_->GetMps(); - - auto new_channel = link_->AllocateDynamicChannel(psm, request.remote_cid); - if (new_channel == nullptr) { - log::warn("Can't allocate dynamic channel"); - // TODO: We need to respond with the correct reason - send_connection_response(signal_id, kInvalidCid, 0, 0, 0, - LeCreditBasedConnectionResponseResult::SOURCE_CID_ALREADY_ALLOCATED); - return; - } - - send_connection_response(signal_id, new_channel->GetCid(), local_mtu, local_mps, - link_->GetInitialCredit(), - LeCreditBasedConnectionResponseResult::SUCCESS); - auto* data_controller = reinterpret_cast<l2cap::internal::LeCreditBasedDataController*>( - data_pipeline_manager_->GetDataController(new_channel->GetCid())); - auto actual_mtu = std::min(request.mtu, local_mtu); - data_controller->SetMtu(actual_mtu); - data_controller->SetMps(std::min(request.max_pdu_size, local_mps)); - data_controller->OnCredit(request.initial_credits); - auto user_channel = std::make_unique<DynamicChannel>(new_channel, handler_, link_, actual_mtu); - dynamic_service_manager_->GetService(psm)->NotifyChannelCreation(std::move(user_channel)); -} - -void LeSignallingManager::OnConnectionResponse(SignalId signal_id, Cid remote_cid, Mtu mtu, - uint16_t mps, uint16_t initial_credits, - LeCreditBasedConnectionResponseResult result) { - if (signal_id != command_just_sent_.signal_id_) { - log::warn("Unexpected response: no pending request"); - return; - } - if (command_just_sent_.command_code_ != LeCommandCode::LE_CREDIT_BASED_CONNECTION_REQUEST) { - log::warn("Unexpected response: no pending request"); - return; - } - alarm_.Cancel(); - command_just_sent_.signal_id_ = kInitialSignalId; - if (result != LeCreditBasedConnectionResponseResult::SUCCESS) { - log::warn("Connection failed: {}", LeCreditBasedConnectionResponseResultText(result).data()); - link_->OnOutgoingConnectionRequestFail(command_just_sent_.source_cid_, result); - handle_send_next_command(); - return; - } - auto new_channel = link_->AllocateReservedDynamicChannel(command_just_sent_.source_cid_, - command_just_sent_.psm_, remote_cid); - if (new_channel == nullptr) { - log::warn("Can't allocate dynamic channel"); - link_->OnOutgoingConnectionRequestFail( - command_just_sent_.source_cid_, - LeCreditBasedConnectionResponseResult::NO_RESOURCES_AVAILABLE); - handle_send_next_command(); - return; - } - auto* data_controller = reinterpret_cast<l2cap::internal::LeCreditBasedDataController*>( - data_pipeline_manager_->GetDataController(new_channel->GetCid())); - auto actual_mtu = std::min(mtu, command_just_sent_.mtu_); - data_controller->SetMtu(actual_mtu); - data_controller->SetMps(std::min(mps, command_just_sent_.mps_)); - data_controller->OnCredit(initial_credits); - std::unique_ptr<DynamicChannel> user_channel = - std::make_unique<DynamicChannel>(new_channel, handler_, link_, actual_mtu); - link_->NotifyChannelCreation(new_channel->GetCid(), std::move(user_channel)); -} - -void LeSignallingManager::OnDisconnectionRequest(SignalId signal_id, Cid cid, Cid remote_cid) { - auto channel = channel_allocator_->FindChannelByCid(cid); - if (channel == nullptr) { - log::warn("Disconnect request for an unknown channel"); - return; - } - if (channel->GetRemoteCid() != remote_cid) { - log::warn("Disconnect request for an unmatching channel"); - return; - } - auto builder = LeDisconnectionResponseBuilder::Create(signal_id.Value(), cid, remote_cid); - enqueue_buffer_->Enqueue(std::move(builder), handler_); - channel->OnClosed(hci::ErrorCode::SUCCESS); - link_->FreeDynamicChannel(cid); -} - -void LeSignallingManager::OnDisconnectionResponse(SignalId signal_id, Cid remote_cid, Cid cid) { - if (signal_id != command_just_sent_.signal_id_ || - command_just_sent_.command_code_ != LeCommandCode::DISCONNECTION_REQUEST) { - log::warn("Unexpected response: no pending request"); - return; - } - if (command_just_sent_.source_cid_ != cid || command_just_sent_.destination_cid_ != remote_cid) { - log::warn( - "Unexpected response: cid doesn't match. Expected scid {} dcid {}, got scid {} dcid {}", - command_just_sent_.source_cid_, command_just_sent_.destination_cid_, cid, remote_cid); - handle_send_next_command(); - return; - } - alarm_.Cancel(); - command_just_sent_.signal_id_ = kInitialSignalId; - auto channel = channel_allocator_->FindChannelByCid(cid); - if (channel == nullptr) { - log::warn("Disconnect response for an unknown channel"); - handle_send_next_command(); - return; - } - - channel->OnClosed(hci::ErrorCode::SUCCESS); - link_->FreeDynamicChannel(cid); - handle_send_next_command(); -} - -void LeSignallingManager::OnCredit(Cid remote_cid, uint16_t credits) { - auto channel = channel_allocator_->FindChannelByRemoteCid(remote_cid); - if (channel == nullptr) { - log::warn("Received credit for invalid cid {}", channel->GetCid()); - return; - } - auto* data_controller = reinterpret_cast<l2cap::internal::LeCreditBasedDataController*>( - data_pipeline_manager_->GetDataController(channel->GetCid())); - data_controller->OnCredit(credits); -} - -void LeSignallingManager::on_incoming_packet() { - auto packet = signalling_channel_->GetQueueUpEnd()->TryDequeue(); - LeControlView control_packet_view = LeControlView::Create(*packet); - if (!control_packet_view.IsValid()) { - log::warn("Invalid signalling packet received"); - return; - } - auto code = control_packet_view.GetCode(); - switch (code) { - case LeCommandCode::COMMAND_REJECT: { - LeCommandRejectView command_reject_view = LeCommandRejectView::Create(control_packet_view); - if (!command_reject_view.IsValid()) { - return; - } - OnCommandReject(command_reject_view); - return; - } - - case LeCommandCode::CONNECTION_PARAMETER_UPDATE_REQUEST: { - ConnectionParameterUpdateRequestView parameter_update_req_view = - ConnectionParameterUpdateRequestView::Create(control_packet_view); - if (!parameter_update_req_view.IsValid()) { - return; - } - OnConnectionParameterUpdateRequest(parameter_update_req_view.GetIdentifier(), - parameter_update_req_view.GetIntervalMin(), - parameter_update_req_view.GetIntervalMax(), - parameter_update_req_view.GetPeripheralLatency(), - parameter_update_req_view.GetTimeoutMultiplier()); - return; - } - case LeCommandCode::CONNECTION_PARAMETER_UPDATE_RESPONSE: { - ConnectionParameterUpdateResponseView parameter_update_rsp_view = - ConnectionParameterUpdateResponseView::Create(control_packet_view); - if (!parameter_update_rsp_view.IsValid()) { - return; - } - OnConnectionParameterUpdateResponse(parameter_update_rsp_view.GetIdentifier(), - parameter_update_rsp_view.GetResult()); - return; - } - case LeCommandCode::LE_CREDIT_BASED_CONNECTION_REQUEST: { - LeCreditBasedConnectionRequestView connection_request_view = - LeCreditBasedConnectionRequestView::Create(control_packet_view); - if (!connection_request_view.IsValid()) { - return; - } - OnConnectionRequest( - connection_request_view.GetIdentifier(), connection_request_view.GetLePsm(), - connection_request_view.GetSourceCid(), connection_request_view.GetMtu(), - connection_request_view.GetMps(), connection_request_view.GetInitialCredits()); - return; - } - case LeCommandCode::LE_CREDIT_BASED_CONNECTION_RESPONSE: { - LeCreditBasedConnectionResponseView connection_response_view = - LeCreditBasedConnectionResponseView::Create(control_packet_view); - if (!connection_response_view.IsValid()) { - return; - } - OnConnectionResponse(connection_response_view.GetIdentifier(), - connection_response_view.GetDestinationCid(), - connection_response_view.GetMtu(), connection_response_view.GetMps(), - connection_response_view.GetInitialCredits(), - connection_response_view.GetResult()); - return; - } - case LeCommandCode::LE_FLOW_CONTROL_CREDIT: { - LeFlowControlCreditView credit_view = LeFlowControlCreditView::Create(control_packet_view); - if (!credit_view.IsValid()) { - return; - } - OnCredit(credit_view.GetCid(), credit_view.GetCredits()); - return; - } - case LeCommandCode::DISCONNECTION_REQUEST: { - LeDisconnectionRequestView disconnection_request_view = - LeDisconnectionRequestView::Create(control_packet_view); - if (!disconnection_request_view.IsValid()) { - return; - } - OnDisconnectionRequest(disconnection_request_view.GetIdentifier(), - disconnection_request_view.GetDestinationCid(), - disconnection_request_view.GetSourceCid()); - return; - } - case LeCommandCode::DISCONNECTION_RESPONSE: { - LeDisconnectionResponseView disconnection_response_view = - LeDisconnectionResponseView::Create(control_packet_view); - if (!disconnection_response_view.IsValid()) { - return; - } - OnDisconnectionResponse(disconnection_response_view.GetIdentifier(), - disconnection_response_view.GetDestinationCid(), - disconnection_response_view.GetSourceCid()); - return; - } - case LeCommandCode::CREDIT_BASED_CONNECTION_REQUEST: { - LeEnhancedCreditBasedConnectionRequestView request_view = - LeEnhancedCreditBasedConnectionRequestView::Create(control_packet_view); - if (!request_view.IsValid()) { - return; - } - return; - } - case LeCommandCode::CREDIT_BASED_CONNECTION_RESPONSE: { - LeEnhancedCreditBasedConnectionResponseView response_view = - LeEnhancedCreditBasedConnectionResponseView::Create(control_packet_view); - if (!response_view.IsValid()) { - return; - } - return; - } - case LeCommandCode::CREDIT_BASED_RECONFIGURE_REQUEST: { - LeEnhancedCreditBasedReconfigureRequestView request_view = - LeEnhancedCreditBasedReconfigureRequestView::Create(control_packet_view); - if (!request_view.IsValid()) { - return; - } - return; - } - case LeCommandCode::CREDIT_BASED_RECONFIGURE_RESPONSE: { - LeEnhancedCreditBasedReconfigureResponseView response_view = - LeEnhancedCreditBasedReconfigureResponseView::Create(control_packet_view); - if (!response_view.IsValid()) { - return; - } - return; - } - default: - log::warn("Unhandled event 0x{:x}", static_cast<int>(code)); - auto builder = - LeCommandRejectNotUnderstoodBuilder::Create(control_packet_view.GetIdentifier()); - enqueue_buffer_->Enqueue(std::move(builder), handler_); - return; - } -} - -void LeSignallingManager::send_connection_response(SignalId signal_id, Cid local_cid, Mtu mtu, - uint16_t mps, uint16_t initial_credit, - LeCreditBasedConnectionResponseResult result) { - auto builder = LeCreditBasedConnectionResponseBuilder::Create(signal_id.Value(), local_cid, mtu, - mps, initial_credit, result); - enqueue_buffer_->Enqueue(std::move(builder), handler_); -} - -void LeSignallingManager::on_command_timeout() { - log::warn("Response time out"); - if (command_just_sent_.signal_id_ == kInvalidSignalId) { - log::error("No pending command"); - return; - } - switch (command_just_sent_.command_code_) { - case LeCommandCode::CONNECTION_PARAMETER_UPDATE_REQUEST: { - link_->OnOutgoingConnectionRequestFail( - command_just_sent_.source_cid_, - LeCreditBasedConnectionResponseResult::NO_RESOURCES_AVAILABLE); - break; - } - default: - break; - } - handle_send_next_command(); -} - -void LeSignallingManager::handle_send_next_command() { - command_just_sent_.signal_id_ = kInvalidSignalId; - if (pending_commands_.empty()) { - return; - } - - command_just_sent_ = pending_commands_.front(); - pending_commands_.pop(); - switch (command_just_sent_.command_code_) { - case LeCommandCode::LE_CREDIT_BASED_CONNECTION_REQUEST: { - auto builder = LeCreditBasedConnectionRequestBuilder::Create( - command_just_sent_.signal_id_.Value(), command_just_sent_.psm_, - command_just_sent_.source_cid_, command_just_sent_.mtu_, command_just_sent_.mps_, - command_just_sent_.credits_); - enqueue_buffer_->Enqueue(std::move(builder), handler_); - alarm_.Schedule( - common::BindOnce(&LeSignallingManager::on_command_timeout, common::Unretained(this)), - kTimeout); - break; - } - case LeCommandCode::DISCONNECTION_REQUEST: { - auto builder = LeDisconnectionRequestBuilder::Create(command_just_sent_.signal_id_.Value(), - command_just_sent_.destination_cid_, - command_just_sent_.source_cid_); - enqueue_buffer_->Enqueue(std::move(builder), handler_); - alarm_.Schedule( - common::BindOnce(&LeSignallingManager::on_command_timeout, common::Unretained(this)), - kTimeout); - break; - } - case LeCommandCode::CONNECTION_PARAMETER_UPDATE_REQUEST: { - auto builder = ConnectionParameterUpdateRequestBuilder::Create( - command_just_sent_.signal_id_.Value(), command_just_sent_.interval_min_, - command_just_sent_.interval_max_, command_just_sent_.peripheral_latency_, - command_just_sent_.timeout_multiplier_); - enqueue_buffer_->Enqueue(std::move(builder), handler_); - alarm_.Schedule( - common::BindOnce(&LeSignallingManager::on_command_timeout, common::Unretained(this)), - kTimeout); - break; - } - default: { - log::warn("Unsupported command code 0x{:x}", - static_cast<int>(command_just_sent_.command_code_)); - } - } -} -} // namespace internal -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/internal/signalling_manager.h b/system/gd/l2cap/le/internal/signalling_manager.h deleted file mode 100644 index 0fa6a992f4..0000000000 --- a/system/gd/l2cap/le/internal/signalling_manager.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <cstdint> -#include <queue> -#include <vector> - -#include "l2cap/cid.h" -#include "l2cap/internal/data_pipeline_manager.h" -#include "l2cap/internal/dynamic_channel_allocator.h" -#include "l2cap/l2cap_packets.h" -#include "l2cap/le/internal/dynamic_channel_service_manager_impl.h" -#include "l2cap/le/internal/fixed_channel_impl.h" -#include "l2cap/le/internal/fixed_channel_service_manager_impl.h" -#include "l2cap/mtu.h" -#include "l2cap/psm.h" -#include "l2cap/signal_id.h" -#include "os/alarm.h" -#include "os/handler.h" -#include "os/queue.h" -#include "packet/raw_builder.h" - -namespace bluetooth { -namespace l2cap { -namespace le { -namespace internal { - -struct PendingCommand { - SignalId signal_id_ = kInvalidSignalId; - LeCommandCode command_code_; - Psm psm_; - Cid source_cid_; - Cid destination_cid_; - Mtu mtu_; - uint16_t mps_; - uint16_t credits_; - uint16_t interval_min_; - uint16_t interval_max_; - uint16_t peripheral_latency_; - uint16_t timeout_multiplier_; - - static PendingCommand CreditBasedConnectionRequest(SignalId signal_id, Psm psm, Cid scid, Mtu mtu, - uint16_t mps, uint16_t initial_credits) { - PendingCommand pending_command; - pending_command.signal_id_ = signal_id; - pending_command.command_code_ = LeCommandCode::LE_CREDIT_BASED_CONNECTION_REQUEST; - pending_command.psm_ = psm; - pending_command.source_cid_ = scid; - pending_command.mtu_ = mtu; - pending_command.mps_ = mps; - pending_command.credits_ = initial_credits; - return pending_command; - } - - static PendingCommand DisconnectionRequest(SignalId signal_id, Cid scid, Cid dcid) { - PendingCommand pending_command; - pending_command.signal_id_ = signal_id; - pending_command.command_code_ = LeCommandCode::DISCONNECTION_REQUEST; - pending_command.source_cid_ = scid; - pending_command.destination_cid_ = dcid; - return pending_command; - } - - static PendingCommand ConnectionParameterUpdate(SignalId signal_id, uint16_t interval_min, - uint16_t interval_max, - uint16_t peripheral_latency, - uint16_t timeout_multiplier) { - PendingCommand pending_command; - pending_command.signal_id_ = signal_id; - pending_command.command_code_ = LeCommandCode::CONNECTION_PARAMETER_UPDATE_REQUEST; - pending_command.interval_min_ = interval_min; - pending_command.interval_max_ = interval_max; - pending_command.peripheral_latency_ = peripheral_latency; - pending_command.timeout_multiplier_ = timeout_multiplier; - return pending_command; - } -}; - -class Link; - -class LeSignallingManager { -public: - LeSignallingManager(os::Handler* handler, Link* link, - l2cap::internal::DataPipelineManager* data_pipeline_manager, - DynamicChannelServiceManagerImpl* dynamic_service_manager, - l2cap::internal::DynamicChannelAllocator* channel_allocator); - - virtual ~LeSignallingManager(); - - void SendConnectionRequest(Psm psm, Cid local_cid, Mtu mtu); - - void SendDisconnectRequest(Cid local_cid, Cid remote_cid); - - // Note: Since Core 4.1, LL peripheral can send this through HCI command. - void SendConnectionParameterUpdateRequest(uint16_t interval_min, uint16_t interval_max, - uint16_t peripheral_latency, - uint16_t timeout_multiplier); - - void SendConnectionParameterUpdateResponse(SignalId signal_id, - ConnectionParameterUpdateResponseResult result); - - void SendCredit(Cid local_cid, uint16_t credits); - - void SendEnhancedConnectionRequest(Psm psm, std::vector<Cid> local_cid, Mtu mtu); - - void SendEnhancedReconfigureRequest(std::vector<Cid> local_cid, Mtu mtu); - - void CancelAlarm(); - - void OnCommandReject(LeCommandRejectView command_reject_view); - - void OnConnectionParameterUpdateRequest(SignalId signal_id, uint16_t interval_min, - uint16_t interval_max, uint16_t peripheral_latency, - uint16_t timeout_multiplier); - void OnConnectionParameterUpdateResponse(SignalId signal_id, - ConnectionParameterUpdateResponseResult result); - - void OnConnectionRequest(SignalId signal_id, Psm psm, Cid remote_cid, Mtu mtu, uint16_t mps, - uint16_t initial_credits); - - void OnConnectionResponse(SignalId signal_id, Cid remote_cid, Mtu mtu, uint16_t mps, - uint16_t initial_credits, LeCreditBasedConnectionResponseResult result); - - void OnDisconnectionRequest(SignalId signal_id, Cid cid, Cid remote_cid); - - void OnDisconnectionResponse(SignalId signal_id, Cid cid, Cid remote_cid); - - void OnCredit(Cid remote_cid, uint16_t credits); - -private: - struct PendingConnection { - Cid remote_cid; - Mtu mtu; - uint16_t max_pdu_size; - uint16_t initial_credits; - SignalId incoming_signal_id; - }; - - void on_incoming_packet(); - void send_connection_response(SignalId signal_id, Cid local_cid, Mtu mtu, uint16_t mps, - uint16_t initial_credit, - LeCreditBasedConnectionResponseResult result); - void on_command_timeout(); - void handle_send_next_command(); - void on_security_result_for_incoming(Psm psm, PendingConnection request, bool result); - void on_security_result_for_outgoing(Psm psm, Cid local_cid, Mtu mtu, bool result); - - os::Handler* handler_; - Link* link_; - l2cap::internal::DataPipelineManager* data_pipeline_manager_; - std::shared_ptr<le::internal::FixedChannelImpl> signalling_channel_; - DynamicChannelServiceManagerImpl* dynamic_service_manager_; - l2cap::internal::DynamicChannelAllocator* channel_allocator_; - std::unique_ptr<os::EnqueueBuffer<packet::BasePacketBuilder>> enqueue_buffer_; - std::queue<PendingCommand> pending_commands_; - PendingCommand command_just_sent_; - os::Alarm alarm_; - SignalId next_signal_id_ = kInitialSignalId; -}; - -} // namespace internal -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/l2cap_le_module.cc b/system/gd/l2cap/le/l2cap_le_module.cc deleted file mode 100644 index a6f5462b08..0000000000 --- a/system/gd/l2cap/le/l2cap_le_module.cc +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/le/l2cap_le_module.h" - -#include <memory> - -#include "hci/acl_manager.h" -#include "l2cap/internal/parameter_provider.h" -#include "l2cap/le/internal/dynamic_channel_service_manager_impl.h" -#include "l2cap/le/internal/fixed_channel_service_manager_impl.h" -#include "l2cap/le/internal/link_manager.h" -#include "l2cap/le/security_enforcement_interface.h" -#include "module.h" -#include "os/handler.h" - -namespace bluetooth { -namespace l2cap { -namespace le { - -const ModuleFactory L2capLeModule::Factory = ModuleFactory([]() { return new L2capLeModule(); }); - -/** - * A default implementation which cannot satisfy any security level except - * NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK. - */ -class SecurityEnforcementRejectAllImpl : public SecurityEnforcementInterface { -public: - void Enforce(hci::AddressWithType /* remote */, SecurityPolicy policy, - ResultCallback result_callback) override { - if (policy == SecurityPolicy::NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK) { - result_callback(true); - } else { - result_callback(false); - } - } -}; -static SecurityEnforcementRejectAllImpl default_security_module_impl_; - -struct L2capLeModule::impl { - impl(os::Handler* l2cap_handler, hci::AclManager* acl_manager) - : l2cap_handler_(l2cap_handler), acl_manager_(acl_manager) { - dynamic_channel_service_manager_impl_.SetSecurityEnforcementInterface( - &default_security_module_impl_); - } - os::Handler* l2cap_handler_; - hci::AclManager* acl_manager_; - l2cap::internal::ParameterProvider parameter_provider_; - internal::FixedChannelServiceManagerImpl fixed_channel_service_manager_impl_{l2cap_handler_}; - internal::DynamicChannelServiceManagerImpl dynamic_channel_service_manager_impl_{l2cap_handler_}; - internal::LinkManager link_manager_{l2cap_handler_, acl_manager_, - &fixed_channel_service_manager_impl_, - &dynamic_channel_service_manager_impl_, ¶meter_provider_}; -}; - -L2capLeModule::L2capLeModule() {} -L2capLeModule::~L2capLeModule() {} - -void L2capLeModule::ListDependencies(ModuleList* list) const { list->add<hci::AclManager>(); } - -void L2capLeModule::Start() { - pimpl_ = std::make_unique<impl>(GetHandler(), GetDependency<hci::AclManager>()); -} - -void L2capLeModule::Stop() { pimpl_.reset(); } - -std::string L2capLeModule::ToString() const { return "L2cap Le Module"; } - -std::unique_ptr<FixedChannelManager> L2capLeModule::GetFixedChannelManager() { - return std::unique_ptr<FixedChannelManager>( - new FixedChannelManager(&pimpl_->fixed_channel_service_manager_impl_, - &pimpl_->link_manager_, pimpl_->l2cap_handler_)); -} - -std::unique_ptr<DynamicChannelManager> L2capLeModule::GetDynamicChannelManager() { - return std::unique_ptr<DynamicChannelManager>( - new DynamicChannelManager(&pimpl_->dynamic_channel_service_manager_impl_, - &pimpl_->link_manager_, pimpl_->l2cap_handler_)); -} - -void L2capLeModule::InjectSecurityEnforcementInterface( - SecurityEnforcementInterface* security_enforcement_interface) { - if (security_enforcement_interface != nullptr) { - pimpl_->dynamic_channel_service_manager_impl_.SetSecurityEnforcementInterface( - security_enforcement_interface); - } else { - pimpl_->dynamic_channel_service_manager_impl_.SetSecurityEnforcementInterface( - &default_security_module_impl_); - } -} - -void L2capLeModule::SetLinkPropertyListener(os::Handler* handler, LinkPropertyListener* listener) { - pimpl_->link_manager_.RegisterLinkPropertyListener(handler, listener); -} - -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/l2cap_le_module.h b/system/gd/l2cap/le/l2cap_le_module.h deleted file mode 100644 index 816538345d..0000000000 --- a/system/gd/l2cap/le/l2cap_le_module.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2019 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. - */ -#pragma once - -#include <memory> - -#include "l2cap/le/dynamic_channel_manager.h" -#include "l2cap/le/fixed_channel_manager.h" -#include "l2cap/le/link_property_listener.h" -#include "l2cap/le/security_enforcement_interface.h" -#include "module.h" - -namespace bluetooth { - -namespace security { -class SecurityModule; -} - -namespace l2cap { -namespace le { - -class L2capLeModule : public bluetooth::Module { -public: - L2capLeModule(); - L2capLeModule(const L2capLeModule&) = delete; - L2capLeModule& operator=(const L2capLeModule&) = delete; - - virtual ~L2capLeModule(); - - /** - * Get the api to the LE fixed channel l2cap module - */ - virtual std::unique_ptr<FixedChannelManager> GetFixedChannelManager(); - - /** - * Get the api to the LE dynamic channel l2cap module - */ - virtual std::unique_ptr<DynamicChannelManager> GetDynamicChannelManager(); - - static const ModuleFactory Factory; - -protected: - void ListDependencies(ModuleList* list) const override; - - void Start() override; - - void Stop() override; - - std::string ToString() const override; - -private: - struct impl; - std::unique_ptr<impl> pimpl_; - - friend security::SecurityModule; - - /** - * Only for the LE security module to inject functionality to enforce security level for a - * connection. When LE security module is stopping, inject nullptr. Note: We expect this only to - * be called during stack startup. This is not synchronized. - */ - virtual void InjectSecurityEnforcementInterface( - SecurityEnforcementInterface* security_enforcement_interface); - - /** - * Set the link property listener. - * This is not synchronized. - */ - virtual void SetLinkPropertyListener(os::Handler* handler, LinkPropertyListener* listener); -}; - -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/l2cap_le_module_mock.h b/system/gd/l2cap/le/l2cap_le_module_mock.h deleted file mode 100644 index 0585546eaf..0000000000 --- a/system/gd/l2cap/le/l2cap_le_module_mock.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2019 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. - */ -#pragma once - -#include <gmock/gmock.h> - -#include "l2cap/le/l2cap_le_module.h" - -// Unit test interfaces -namespace bluetooth { -namespace l2cap { -namespace le { -namespace testing { - -class MockL2capLeModule : public L2capLeModule { -public: - MOCK_METHOD(std::unique_ptr<FixedChannelManager>, GetFixedChannelManager, (), (override)); -}; - -} // namespace testing -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/link_options.cc b/system/gd/l2cap/le/link_options.cc deleted file mode 100644 index 9cf5a04419..0000000000 --- a/system/gd/l2cap/le/link_options.cc +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2020 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 "l2cap/le/link_options.h" - -#include <bluetooth/log.h> - -#include <cstdint> - -#include "hci/hci_packets.h" -#include "l2cap/le/internal/link.h" - -namespace bluetooth { -namespace l2cap { -namespace le { - -LinkOptions::LinkOptions(hci::acl_manager::LeAclConnection* acl_connection, internal::Link* link, - os::Handler* l2cap_handler) - : acl_connection_(acl_connection), link_(link), l2cap_handler_(l2cap_handler) {} - -hci::Role LinkOptions::GetRole() const { return acl_connection_->GetRole(); } - -uint16_t LinkOptions::GetHandle() const { return acl_connection_->GetHandle(); } - -hci::AddressWithType LinkOptions::GetLocalAddress() const { - return acl_connection_->GetLocalAddress(); -} - -bool LinkOptions::UpdateConnectionParameter(uint16_t conn_interval_min, uint16_t conn_interval_max, - uint16_t conn_latency, uint16_t supervision_timeout, - uint16_t min_ce_length, uint16_t max_ce_length) { - if (conn_interval_min < 0x0006 || conn_interval_min > 0x0C80 || conn_interval_max < 0x0006 || - conn_interval_max > 0x0C80 || conn_latency > 0x01F3 || supervision_timeout < 0x000A || - supervision_timeout > 0x0C80) { - log::error("Invalid parameter"); - return false; - } - - l2cap_handler_->Post(common::BindOnce(&internal::Link::SendConnectionParameterUpdate, - common::Unretained(link_), conn_interval_min, - conn_interval_max, conn_latency, supervision_timeout, - min_ce_length, max_ce_length)); - - return true; -} - -bool LinkOptions::SetPhy(uint8_t /* all_phys */, uint8_t /* tx_phys */, uint8_t /* rx_phys */, - uint16_t /* phy_options */) { - log::error("Not implemented"); - return false; -} - -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/link_options.h b/system/gd/l2cap/le/link_options.h deleted file mode 100644 index a001519ad5..0000000000 --- a/system/gd/l2cap/le/link_options.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2020 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. - */ - -#pragma once - -#include <cstdint> - -#include "hci/acl_manager/le_acl_connection.h" -#include "hci/hci_packets.h" -#include "os/handler.h" - -namespace bluetooth { -namespace l2cap { -namespace le { -namespace internal { -class Link; -} - -/** - * Proxy for L2CAP user to get some link layer properties (connection handle, role), and set link - * layer options (connection parameter update, set PHY). Only few special L2CAP users need to use - * it, including Security Manager, Hearing Aid Profile, HID Profile, and Java API. Note: Setting - * link layer options applies to the LINK, not single CHANNEL. - */ -class LinkOptions { -public: - /** - * Get LL Role. Most applications should NOT know its LL role. - */ - hci::Role GetRole() const; - - /** - * Get ACL Handle. Most applications should NOT know its ACL handle. - */ - uint16_t GetHandle() const; - - /** - * Return Local address used for initiation of this connection. - */ - hci::AddressWithType GetLocalAddress() const; - - /** - * Update the LE link layer connection parameters. - * Depending on the link role and supported features, may directly send HCI command to update - * link, or send L2CAP request to advise the remote. The updated connection parameters are still - * determined by controller. It's a link layer change for performance tuning, and no host layer - * change should be observable by user. Parameters are defined in Core spec HCI 7.8.18. - * @return true iff the request is sent to controller through HCI or remote through L2CAP - * (Use it only if you know what you are doing!) - */ - bool UpdateConnectionParameter(uint16_t conn_interval_min, uint16_t conn_interval_max, - uint16_t conn_latency, uint16_t supervision_timeout, - uint16_t min_ce_length, uint16_t max_ce_length); - - /** - * Set PHY preference. The PHY is determined by the controller. - * No host layer change should be observable by user. - * Parameters are defined in Core spec HCI 7.8.49. - * @return true iff the request is sent to controller through HCI - * (Use it only if you know what you are doing!) - */ - bool SetPhy(uint8_t all_phys, uint8_t tx_phys, uint8_t rx_phys, uint16_t phy_options); - - LinkOptions(hci::acl_manager::LeAclConnection* acl_connection, internal::Link* link, - os::Handler* l2cap_handler); - -private: - hci::acl_manager::LeAclConnection* acl_connection_ = nullptr; - internal::Link* link_ = nullptr; - os::Handler* l2cap_handler_ = nullptr; -}; - -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/link_property_listener.h b/system/gd/l2cap/le/link_property_listener.h deleted file mode 100644 index 11ae0d7ca9..0000000000 --- a/system/gd/l2cap/le/link_property_listener.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2021 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. - */ - -#pragma once - -#include <memory> - -#include "hci/address_with_type.h" -#include "hci/hci_packets.h" - -namespace bluetooth { -namespace l2cap { -namespace le { - -/** - * This is the listener interface for link property callbacks. - */ -class LinkPropertyListener { -public: - virtual ~LinkPropertyListener() = default; - - /** - * Invoked when an ACL link is connected. - */ - virtual void OnLinkConnected(hci::AddressWithType /* remote */, uint16_t /* handle */, - hci::Role /* my_role */) {} - - /** - * Invoked when an ACL link is disconnected. - */ - virtual void OnLinkDisconnected(hci::AddressWithType /* remote */) {} - - /** - * Invoked when received remote version information for a given link - */ - virtual void OnReadRemoteVersionInformation(hci::ErrorCode /* hci_status */, - hci::AddressWithType /* remote */, - uint8_t /* lmp_version */, - uint16_t /* manufacturer_name */, - uint16_t /* sub_version */) {} - - /** - * Invoked when received connection update for a given link - */ - virtual void OnConnectionUpdate(hci::AddressWithType /* remote */, - uint16_t /* connection_interval */, - uint16_t /* connection_latency */, - uint16_t /* supervision_timeout */) {} - - /** - * Invoked when received PHY update for a given link - */ - virtual void OnPhyUpdate(hci::AddressWithType /* remote */, uint8_t /* tx_phy */, - uint8_t /* rx_phy */) {} - - /** - * Invoked when received data length exchange for a given link - */ - virtual void OnDataLengthChange(hci::AddressWithType /* remote */, uint16_t /* tx_octets */, - uint16_t /* tx_time */, uint16_t /* rx_octets */, - uint16_t /* rx_time */) {} -}; - -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/security_enforcement_interface.h b/system/gd/l2cap/le/security_enforcement_interface.h deleted file mode 100644 index ccbd9b91c4..0000000000 --- a/system/gd/l2cap/le/security_enforcement_interface.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2020 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. - */ - -#pragma once - -#include "common/contextual_callback.h" -#include "hci/address_with_type.h" -#include "l2cap/le/security_policy.h" - -namespace bluetooth { -namespace l2cap { -namespace le { - -/** - * The interface for Security Module to implement. - */ -class SecurityEnforcementInterface { -public: - virtual ~SecurityEnforcementInterface() = default; - - using ResultCallback = common::ContextualOnceCallback<void(bool)>; - - /** - * Invoked when L2CAP needs to open a channel with given security requirement. When the Security - * Module satisfies the required security level, or cannot satisfy at all, invoke the - * result_callback. - */ - virtual void Enforce(hci::AddressWithType remote, SecurityPolicy policy, - ResultCallback result_callback) = 0; -}; - -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/le/security_policy.h b/system/gd/l2cap/le/security_policy.h deleted file mode 100644 index d3f7b57f32..0000000000 --- a/system/gd/l2cap/le/security_policy.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2020 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. - */ - -#pragma once - -#include <cstdint> - -namespace bluetooth { -namespace l2cap { -namespace le { - -enum class SecurityPolicy { - // Predefined security policies for user to pick - - // No security enforced - NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK, - - // Just encryption, but no MITM - ENCRYPTED_TRANSPORT, - - // Implicitly MITM protected - AUTHENTICATED_ENCRYPTED_TRANSPORT, - - // Same as AUTHENTICATED_ENCRYPTED_TRANSPORT - BEST, - - _NOT_FOR_YOU__AUTHENTICATED_PAIRING_WITH_128_BIT_KEY, - _NOT_FOR_YOU__AUTHORIZATION, -}; - -} // namespace le -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/mtu.h b/system/gd/l2cap/mtu.h deleted file mode 100644 index fa9bc645bf..0000000000 --- a/system/gd/l2cap/mtu.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2019 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. - */ -#pragma once - -#include <cstdint> - -namespace bluetooth { -namespace l2cap { - -using Mtu = uint16_t; - -constexpr Mtu kMinimumClassicMtu = 48; -constexpr Mtu kMinimumLeMtu = 23; -constexpr Mtu kDefaultClassicMtu = 672; - -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/psm.h b/system/gd/l2cap/psm.h deleted file mode 100644 index 0e89e62cfd..0000000000 --- a/system/gd/l2cap/psm.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <cstdint> - -namespace bluetooth { -namespace l2cap { - -using Psm = uint16_t; -constexpr Psm kDefaultPsm = 0; // Invalid Psm as a default value - -constexpr bool IsPsmValid(Psm psm) { - // See Core spec 5.1 Vol 3 Part A 4.2 for definition - return (psm & 0x0101u) == 0x0001u; -} - -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/signal_id.h b/system/gd/l2cap/signal_id.h deleted file mode 100644 index 15227d36e5..0000000000 --- a/system/gd/l2cap/signal_id.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <cstdint> - -namespace bluetooth { -namespace l2cap { - -struct SignalId { -public: - constexpr SignalId(uint8_t value) : value_(value) {} - constexpr SignalId() : value_(1) {} - ~SignalId() = default; - - uint8_t Value() const { return value_; } - - bool IsValid() const { return value_ != 0; } - - friend bool operator==(const SignalId& lhs, const SignalId& rhs); - friend bool operator!=(const SignalId& lhs, const SignalId& rhs); - - struct SignalId& operator++(); // Prefix increment operator. - struct SignalId operator++(int); // Postfix increment operator. - struct SignalId& operator--(); // Prefix decrement operator. - struct SignalId operator--(int); // Postfix decrement operator. - -private: - uint8_t value_; -}; - -constexpr SignalId kInvalidSignalId{0}; -constexpr SignalId kInitialSignalId{1}; - -inline bool operator==(const SignalId& lhs, const SignalId& rhs) { - return lhs.value_ == rhs.value_; -} - -inline bool operator!=(const SignalId& lhs, const SignalId& rhs) { return !(lhs == rhs); } - -inline struct SignalId& SignalId::operator++() { - value_++; - if (value_ == 0) { - value_++; - } - return *this; -} - -inline struct SignalId SignalId::operator++(int) { - struct SignalId tmp = *this; - ++*this; - return tmp; -} - -inline struct SignalId& SignalId::operator--() { - value_--; - if (value_ == 0) { - value_ = 0xff; - } - return *this; -} - -inline struct SignalId SignalId::operator--(int) { - struct SignalId tmp = *this; - --*this; - return tmp; -} - -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/l2cap/signal_id_test.cc b/system/gd/l2cap/signal_id_test.cc deleted file mode 100644 index 5060a88de8..0000000000 --- a/system/gd/l2cap/signal_id_test.cc +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright 2019 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 "l2cap/signal_id.h" - -#include <gtest/gtest.h> - -#include <cstdint> - -namespace bluetooth { -namespace l2cap { - -TEST(L2capSignalIdTest, valid_values) { - int valid = 0; - uint8_t i = 0; - while (++i != 0) { - SignalId signal_id(i); - if (signal_id.IsValid()) { - valid++; - } - } - ASSERT_TRUE(valid == 255); -} - -TEST(L2capSignalIdTest, zero_invalid) { - SignalId signal_id(0); - ASSERT_FALSE(signal_id.IsValid()); -} - -TEST(L2capSignalIdTest, pre_increment) { - SignalId signal_id(0); - ASSERT_FALSE(signal_id.IsValid()); - - for (uint8_t i = 0; i != 0xff; ++i, ++signal_id) { - ASSERT_TRUE(i == signal_id.Value()); - } -} - -TEST(L2capSignalIdTest, post_increment) { - SignalId signal_id(0); - ASSERT_FALSE(signal_id.IsValid()); - - for (uint8_t i = 0; i != 0xff; i++, signal_id++) { - ASSERT_TRUE(i == signal_id.Value()); - } -} - -TEST(L2capSignalIdTest, almost_wrap_up) { - SignalId signal_id(0); - ASSERT_FALSE(signal_id.IsValid()); - - for (int i = 0; i < 255; i++) { - signal_id++; - } - ASSERT_EQ(0xff, signal_id.Value()); -} - -TEST(L2capSignalIdTest, wrap_up) { - SignalId signal_id(0); - ASSERT_FALSE(signal_id.IsValid()); - - for (int i = 0; i < 256; i++) { - signal_id++; - } - ASSERT_EQ(1, signal_id.Value()); -} - -TEST(L2capSignalIdTest, pre_decrement) { - SignalId signal_id(0); - ASSERT_FALSE(signal_id.IsValid()); - - for (uint8_t i = 0; i != 0xff; --i, --signal_id) { - ASSERT_TRUE(i == signal_id.Value()); - } -} - -TEST(L2capSignalIdTest, post_decrement) { - SignalId signal_id(0); - ASSERT_FALSE(signal_id.IsValid()); - - for (uint8_t i = 0; i != 0xff; i--, signal_id--) { - ASSERT_TRUE(i == signal_id.Value()); - } -} - -TEST(L2capSignalIdTest, almost_wrap_down) { - SignalId signal_id(0); - ASSERT_FALSE(signal_id.IsValid()); - - for (int i = 0; i < 255; i++) { - signal_id--; - } - ASSERT_EQ(1, signal_id.Value()); -} - -TEST(L2capSignalIdTest, wrap_down) { - SignalId signal_id(0); - ASSERT_FALSE(signal_id.IsValid()); - - for (int i = 0; i < 256; i++) { - signal_id--; - } - ASSERT_EQ(0xff, signal_id.Value()); -} - -} // namespace l2cap -} // namespace bluetooth diff --git a/system/gd/security/Android.bp b/system/gd/security/Android.bp deleted file mode 100644 index b5ee059ea3..0000000000 --- a/system/gd/security/Android.bp +++ /dev/null @@ -1,48 +0,0 @@ -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "system_bt_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["system_bt_license"], -} - -filegroup { - name: "BluetoothSecuritySources", - srcs: [ - ":BluetoothSecurityChannelSources", - ":BluetoothSecurityPairingSources", - ":BluetoothSecurityRecordSources", - "ecc/multprecision.cc", - "ecc/p_256_ecc_pp.cc", - "ecdh_keys.cc", - "facade_configuration_api.cc", - "internal/security_manager_impl.cc", - "l2cap_security_module_interface.cc", - "pairing_handler_le.cc", - "pairing_handler_le_legacy.cc", - "pairing_handler_le_secure_connections.cc", - "security_manager.cc", - "security_module.cc", - ], -} - -filegroup { - name: "BluetoothSecurityUnitTestSources", - srcs: [ - "ecc/multipoint_test.cc", - "test/ecdh_keys_test.cc", - ], -} - -filegroup { - name: "BluetoothSecurityTestSources", - srcs: [ - ":BluetoothSecurityChannelTestSources", - ":BluetoothSecurityPairingTestSources", - ":BluetoothSecurityRecordTestSources", - "pairing_handler_le_unittest.cc", - "test/fake_l2cap_test.cc", - "test/pairing_handler_le_pair_test.cc", - ], -} diff --git a/system/gd/security/BUILD.gn b/system/gd/security/BUILD.gn deleted file mode 100644 index cfdd2b685b..0000000000 --- a/system/gd/security/BUILD.gn +++ /dev/null @@ -1,70 +0,0 @@ -# -# Copyright 2021 Google, Inc. -# -# 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. - -source_set("BluetoothSecurityChannelSources") { - sources = [ "channel/security_manager_channel.cc" ] - configs += [ - "//bt/system/gd:gd_defaults", - "//bt/system/log:log_defaults", - ] - deps = [ "//bt/system/gd:gd_default_deps" ] -} - -source_set("BluetoothSecurityPairingSources") { - sources = [ "pairing/classic_pairing_handler.cc" ] - configs += [ - "//bt/system/gd:gd_defaults", - "//bt/system/log:log_defaults", - ] - deps = [ "//bt/system/gd:gd_default_deps" ] -} - -source_set("BluetoothSecurityRecordSources") { - sources = [ "record/security_record_storage.cc" ] - configs += [ - "//bt/system/gd:gd_defaults", - "//bt/system/log:log_defaults", - ] - deps = [ "//bt/system/gd:gd_default_deps" ] -} - -source_set("BluetoothSecuritySources") { - sources = [ - "ecc/multprecision.cc", - "ecc/p_256_ecc_pp.cc", - "ecdh_keys.cc", - "facade_configuration_api.cc", - "internal/security_manager_impl.cc", - "l2cap_security_module_interface.cc", - "pairing_handler_le.cc", - "pairing_handler_le_legacy.cc", - "pairing_handler_le_secure_connections.cc", - "security_manager.cc", - "security_module.cc", - ] - - deps = [ - ":BluetoothSecurityChannelSources", - ":BluetoothSecurityPairingSources", - ":BluetoothSecurityRecordSources", - "//bt/sysprop:libcom.android.sysprop.bluetooth", - "//bt/system/gd:gd_default_deps", - ] - - configs += [ - "//bt/system/gd:gd_defaults", - "//bt/system/log:log_defaults", - ] -} diff --git a/system/gd/security/channel/Android.bp b/system/gd/security/channel/Android.bp deleted file mode 100644 index d005b22dd0..0000000000 --- a/system/gd/security/channel/Android.bp +++ /dev/null @@ -1,22 +0,0 @@ -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "system_bt_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["system_bt_license"], -} - -filegroup { - name: "BluetoothSecurityChannelSources", - srcs: [ - "security_manager_channel.cc", - ], -} - -filegroup { - name: "BluetoothSecurityChannelTestSources", - srcs: [ - "security_manager_channel_unittest.cc", - ], -} diff --git a/system/gd/security/channel/security_manager_channel.cc b/system/gd/security/channel/security_manager_channel.cc deleted file mode 100644 index c4cf1780cd..0000000000 --- a/system/gd/security/channel/security_manager_channel.cc +++ /dev/null @@ -1,135 +0,0 @@ -/* - * - * Copyright 2019 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 "security/channel/security_manager_channel.h" - -#include <bluetooth/log.h> - -#include "hci/address.h" - -namespace bluetooth { -namespace security { -namespace channel { - -/** - * Main Constructor - */ -SecurityManagerChannel::SecurityManagerChannel(os::Handler* handler, hci::HciLayer* hci_layer) - : listener_(nullptr), - hci_security_interface_(hci_layer->GetSecurityInterface( - handler->BindOn(this, &SecurityManagerChannel::OnHciEventReceived))), - handler_(handler), - l2cap_security_interface_(nullptr) {} - -SecurityManagerChannel::~SecurityManagerChannel() { - l2cap_security_interface_->Unregister(); - l2cap_security_interface_ = nullptr; -} - -void SecurityManagerChannel::Connect(hci::Address address) { - log::assert_that(l2cap_security_interface_ != nullptr, "L2cap Security Interface is null!"); - auto entry = link_map_.find(address); - if (entry != link_map_.end()) { - log::warn("Already connected to '{}'", address); - entry->second->Hold(); - entry->second->EnsureAuthenticated(); - return; - } - l2cap_security_interface_->InitiateConnectionForSecurity(address); - outgoing_pairing_remote_devices_.insert(address); -} - -void SecurityManagerChannel::Release(hci::Address address) { - auto entry = link_map_.find(address); - if (entry == link_map_.end()) { - log::warn("Unknown address '{}'", address); - return; - } - entry->second->Release(); -} - -void SecurityManagerChannel::Disconnect(hci::Address address) { - outgoing_pairing_remote_devices_.erase(address); - auto entry = link_map_.find(address); - if (entry == link_map_.end()) { - log::warn("Unknown address '{}'", address); - return; - } - entry->second->Disconnect(); -} - -void SecurityManagerChannel::OnCommandComplete(hci::CommandCompleteView packet) { - log::assert_that(packet.IsValid(), "Bad command response"); -} - -void SecurityManagerChannel::SendCommand(std::unique_ptr<hci::SecurityCommandBuilder> command) { - hci_security_interface_->EnqueueCommand( - std::move(command), - handler_->BindOnceOn(this, &SecurityManagerChannel::OnCommandComplete)); -} - -void SecurityManagerChannel::SendCommand(std::unique_ptr<hci::SecurityCommandBuilder> command, - SecurityCommandStatusCallback callback) { - hci_security_interface_->EnqueueCommand(std::move(command), - std::forward<SecurityCommandStatusCallback>(callback)); -} - -void SecurityManagerChannel::OnHciEventReceived(hci::EventView packet) { - log::assert_that(listener_ != nullptr, "No listener set!"); - log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()"); - listener_->OnHciEventReceived(packet); -} - -void SecurityManagerChannel::OnLinkConnected( - std::unique_ptr<l2cap::classic::LinkSecurityInterface> link) { - // Multiple links possible? - auto remote = link->GetRemoteAddress(); - if (outgoing_pairing_remote_devices_.count(remote) == 1) { - link->Hold(); - link->EnsureAuthenticated(); - outgoing_pairing_remote_devices_.erase(remote); - } - link_map_.emplace(remote, std::move(link)); -} - -void SecurityManagerChannel::OnLinkDisconnected(hci::Address address) { - auto entry = link_map_.find(address); - if (entry == link_map_.end()) { - log::warn("Unknown address '{}'", address); - return; - } - entry->second.reset(); - link_map_.erase(entry); - log::assert_that(listener_ != nullptr, "Set listener!"); - listener_->OnConnectionClosed(address); -} - -void SecurityManagerChannel::OnAuthenticationComplete(hci::ErrorCode /* hci_status */, - hci::Address remote) { - log::assert_that(l2cap_security_interface_ != nullptr, "L2cap Security Interface is null!"); - auto entry = link_map_.find(remote); - if (entry != link_map_.end()) { - entry->second->EnsureEncrypted(); - return; - } -} - -void SecurityManagerChannel::OnEncryptionChange(hci::Address /* remote */, bool /* encrypted */) {} - -} // namespace channel -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/channel/security_manager_channel.h b/system/gd/security/channel/security_manager_channel.h deleted file mode 100644 index 9a59e7ad78..0000000000 --- a/system/gd/security/channel/security_manager_channel.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * - * Copyright 2019 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. - * - */ -#pragma once - -#include <memory> -#include <unordered_map> - -#include "common/contextual_callback.h" -#include "hci/hci_layer.h" -#include "hci/hci_packets.h" -#include "hci/security_interface.h" -#include "l2cap/classic/link_security_interface.h" - -namespace bluetooth { -namespace security { -namespace channel { - -using SecurityCommandStatusCallback = - common::ContextualOnceCallback<void(hci::CommandCompleteView)>; - -/** - * Interface for listening to the channel for SMP commands. - */ -class ISecurityManagerChannelListener { -public: - virtual ~ISecurityManagerChannelListener() = default; - virtual void OnHciEventReceived(hci::EventView packet) = 0; - virtual void OnConnectionClosed(hci::Address) = 0; -}; - -/** - * Channel for consolidating traffic and making the transport agnostic. - */ -class SecurityManagerChannel : public l2cap::classic::LinkSecurityInterfaceListener { -public: - SecurityManagerChannel(os::Handler* handler, hci::HciLayer* hci_layer); - - virtual ~SecurityManagerChannel(); - - /** - * Creates a connection to the device which triggers pairing - * - * @param address remote address of device to pair with - */ - void Connect(hci::Address address); - - /** - * Releases link hold so it can disconnect as normally - * - * i.e. signals we no longer need this if acl manager wants to clean it up - * - * @param address remote address to disconnect - */ - void Release(hci::Address address); - - /** - * Immediately disconnects currently connected channel - * - * i.e. force disconnect - * - * @param address remote address to disconnect - */ - void Disconnect(hci::Address address); - - /** - * Send a given SMP command over the SecurityManagerChannel - * - * @param command smp command to send - */ - void SendCommand(std::unique_ptr<hci::SecurityCommandBuilder> command); - - /** - * Send a given SMP command over the SecurityManagerChannel - * - * @param command smp command to send - * @param callback listener to call when command status complete - */ - void SendCommand(std::unique_ptr<hci::SecurityCommandBuilder> command, - SecurityCommandStatusCallback callback); - - /** - * Sets the listener to listen for channel events - * - * @param listener the caller interested in events - */ - void SetChannelListener(ISecurityManagerChannelListener* listener) { listener_ = listener; } - - void SetSecurityInterface(l2cap::classic::SecurityInterface* security_interface) { - l2cap_security_interface_ = security_interface; - } - - /** - * Called when an incoming HCI event happens - * - * @param event_packet - */ - void OnHciEventReceived(hci::EventView packet); - - /** - * Called when an HCI command is completed - * - * @param on_complete - */ - void OnCommandComplete(hci::CommandCompleteView packet); - - // Interface overrides - void OnLinkConnected(std::unique_ptr<l2cap::classic::LinkSecurityInterface> link) override; - void OnLinkDisconnected(hci::Address address) override; - void OnAuthenticationComplete(hci::ErrorCode hci_status, hci::Address remote) override; - void OnEncryptionChange(hci::Address, bool encrypted) override; - -private: - ISecurityManagerChannelListener* listener_{nullptr}; - hci::SecurityInterface* hci_security_interface_{nullptr}; - os::Handler* handler_{nullptr}; - l2cap::classic::SecurityInterface* l2cap_security_interface_{nullptr}; - std::unordered_map<hci::Address, std::unique_ptr<l2cap::classic::LinkSecurityInterface>> - link_map_; - std::set<hci::Address> outgoing_pairing_remote_devices_; -}; - -} // namespace channel -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/channel/security_manager_channel_unittest.cc b/system/gd/security/channel/security_manager_channel_unittest.cc deleted file mode 100644 index c1680c3760..0000000000 --- a/system/gd/security/channel/security_manager_channel_unittest.cc +++ /dev/null @@ -1,722 +0,0 @@ -/* - * - * Copyright 2019 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 "security/channel/security_manager_channel.h" - -#include <bluetooth/log.h> -#include <gtest/gtest.h> - -#include "hci/address.h" -#include "hci/hci_packets.h" -#include "packet/raw_builder.h" -#include "security/test/fake_hci_layer.h" -#include "security/test/fake_security_interface.h" - -namespace bluetooth { -namespace security { -namespace channel { -namespace { - -using bluetooth::security::channel::SecurityManagerChannel; -using hci::Address; -using hci::AuthenticationRequirements; -using hci::CommandCompleteBuilder; -using hci::IoCapabilityRequestReplyBuilder; -using hci::IoCapabilityRequestView; -using hci::OobDataPresent; -using hci::OpCode; -using os::Handler; -using os::Thread; -using packet::RawBuilder; - -static bool on_link_connected_called = false; -static bool on_link_disconnected_called = false; - -class FakeSecurityManagerChannel : public SecurityManagerChannel { -public: - FakeSecurityManagerChannel(os::Handler* handler, hci::HciLayer* hci_layer) - : SecurityManagerChannel(handler, hci_layer) {} - ~FakeSecurityManagerChannel() {} - - void OnLinkConnected(std::unique_ptr<l2cap::classic::LinkSecurityInterface> link) { - on_link_connected_called = true; - } - - void OnLinkDisconnected(hci::Address address) { on_link_disconnected_called = true; } - - void OnAuthenticationComplete(hci::ErrorCode hci_status, hci::Address remote) override {} - - void OnEncryptionChange(hci::Address address, bool encrypted) override {} -}; - -class SecurityManagerChannelCallback : public ISecurityManagerChannelListener { -public: - // HCI - bool receivedChangeConnectionLinkKeyComplete = false; - bool receivedCentralLinkKeyComplete = false; - bool receivedPinCodeRequest = false; - bool receivedLinkKeyRequest = false; - bool receivedLinkKeyNotification = false; - bool receivedIoCapabilityRequest = false; - bool receivedIoCapabilityResponse = false; - bool receivedSimplePairingComplete = false; - bool receivedReturnLinkKeys = false; - bool receivedEncryptionChange = false; - bool receivedEncryptionKeyRefreshComplete = false; - bool receivedRemoteOobDataRequest = false; - bool receivedUserPasskeyNotification = false; - bool receivedUserPasskeyRequest = false; - bool receivedKeypressNotification = false; - bool receivedUserConfirmationRequest = false; - bool receivedEncryptionChangeV2 = false; - - void OnReceive(hci::AddressWithType device, hci::ChangeConnectionLinkKeyCompleteView packet) { - ASSERT_TRUE(packet.IsValid()); - receivedChangeConnectionLinkKeyComplete = true; - } - void OnReceive(hci::AddressWithType device, hci::CentralLinkKeyCompleteView packet) { - ASSERT_TRUE(packet.IsValid()); - receivedCentralLinkKeyComplete = true; - } - void OnReceive(hci::AddressWithType device, hci::PinCodeRequestView packet) { - ASSERT_TRUE(packet.IsValid()); - receivedPinCodeRequest = true; - } - void OnReceive(hci::AddressWithType device, hci::LinkKeyRequestView packet) { - ASSERT_TRUE(packet.IsValid()); - receivedLinkKeyRequest = true; - } - void OnReceive(hci::AddressWithType device, hci::LinkKeyNotificationView packet) { - ASSERT_TRUE(packet.IsValid()); - receivedLinkKeyNotification = true; - } - void OnReceive(hci::AddressWithType device, hci::IoCapabilityRequestView packet) { - ASSERT_TRUE(packet.IsValid()); - receivedIoCapabilityRequest = true; - } - void OnReceive(hci::AddressWithType device, hci::IoCapabilityResponseView packet) { - ASSERT_TRUE(packet.IsValid()); - receivedIoCapabilityResponse = true; - } - void OnReceive(hci::AddressWithType device, hci::SimplePairingCompleteView packet) { - ASSERT_TRUE(packet.IsValid()); - receivedSimplePairingComplete = true; - } - void OnReceive(hci::AddressWithType device, hci::ReturnLinkKeysView packet) { - ASSERT_TRUE(packet.IsValid()); - receivedReturnLinkKeys = true; - } - void OnReceive(hci::AddressWithType device, hci::EncryptionChangeView packet) { - ASSERT_TRUE(packet.IsValid()); - receivedEncryptionChange = true; - } - void OnReceive(hci::AddressWithType device, hci::EncryptionKeyRefreshCompleteView packet) { - ASSERT_TRUE(packet.IsValid()); - receivedEncryptionKeyRefreshComplete = true; - } - void OnReceive(hci::AddressWithType device, hci::RemoteOobDataRequestView packet) { - ASSERT_TRUE(packet.IsValid()); - receivedRemoteOobDataRequest = true; - } - void OnReceive(hci::AddressWithType device, hci::UserPasskeyNotificationView packet) { - ASSERT_TRUE(packet.IsValid()); - receivedUserPasskeyNotification = true; - } - void OnReceive(hci::AddressWithType device, hci::KeypressNotificationView packet) { - ASSERT_TRUE(packet.IsValid()); - receivedKeypressNotification = true; - } - void OnReceive(hci::AddressWithType device, hci::UserConfirmationRequestView packet) { - ASSERT_TRUE(packet.IsValid()); - receivedUserConfirmationRequest = true; - } - void OnReceive(hci::AddressWithType device, hci::UserPasskeyRequestView packet) { - ASSERT_TRUE(packet.IsValid()); - receivedUserPasskeyRequest = true; - } - void OnReceive(hci::AddressWithType device, hci::EncryptionChangeV2View packet) { - ASSERT_TRUE(packet.IsValid()); - receivedEncryptionChangeV2 = true; - } - - void OnHciEventReceived(EventView packet) override { - auto event = EventView::Create(packet); - log::assert_that(event.IsValid(), "Received invalid packet"); - const hci::EventCode code = event.GetEventCode(); - switch (code) { - case hci::EventCode::CHANGE_CONNECTION_LINK_KEY_COMPLETE: - OnReceive(hci::AddressWithType(), hci::ChangeConnectionLinkKeyCompleteView::Create(event)); - break; - case hci::EventCode::CENTRAL_LINK_KEY_COMPLETE: - OnReceive(hci::AddressWithType(), hci::CentralLinkKeyCompleteView::Create(event)); - break; - case hci::EventCode::PIN_CODE_REQUEST: - OnReceive(hci::AddressWithType(), hci::PinCodeRequestView::Create(event)); - break; - case hci::EventCode::LINK_KEY_REQUEST: - OnReceive(hci::AddressWithType(), hci::LinkKeyRequestView::Create(event)); - break; - case hci::EventCode::LINK_KEY_NOTIFICATION: - OnReceive(hci::AddressWithType(), hci::LinkKeyNotificationView::Create(event)); - break; - case hci::EventCode::IO_CAPABILITY_REQUEST: - OnReceive(hci::AddressWithType(), hci::IoCapabilityRequestView::Create(event)); - break; - case hci::EventCode::IO_CAPABILITY_RESPONSE: - OnReceive(hci::AddressWithType(), hci::IoCapabilityResponseView::Create(event)); - break; - case hci::EventCode::SIMPLE_PAIRING_COMPLETE: - OnReceive(hci::AddressWithType(), hci::SimplePairingCompleteView::Create(event)); - break; - case hci::EventCode::RETURN_LINK_KEYS: - OnReceive(hci::AddressWithType(), hci::ReturnLinkKeysView::Create(event)); - break; - case hci::EventCode::ENCRYPTION_CHANGE: - OnReceive(hci::AddressWithType(), hci::EncryptionChangeView::Create(event)); - break; - case hci::EventCode::ENCRYPTION_KEY_REFRESH_COMPLETE: - OnReceive(hci::AddressWithType(), hci::EncryptionKeyRefreshCompleteView::Create(event)); - break; - case hci::EventCode::REMOTE_OOB_DATA_REQUEST: - OnReceive(hci::AddressWithType(), hci::RemoteOobDataRequestView::Create(event)); - break; - case hci::EventCode::USER_PASSKEY_NOTIFICATION: - OnReceive(hci::AddressWithType(), hci::UserPasskeyNotificationView::Create(event)); - break; - case hci::EventCode::KEYPRESS_NOTIFICATION: - OnReceive(hci::AddressWithType(), hci::KeypressNotificationView::Create(event)); - break; - case hci::EventCode::USER_CONFIRMATION_REQUEST: - OnReceive(hci::AddressWithType(), hci::UserConfirmationRequestView::Create(event)); - break; - case hci::EventCode::USER_PASSKEY_REQUEST: - OnReceive(hci::AddressWithType(), hci::UserPasskeyRequestView::Create(event)); - break; - case hci::EventCode::ENCRYPTION_CHANGE_V2: - OnReceive(hci::AddressWithType(), hci::EncryptionChangeV2View::Create(event)); - break; - default: - log::fatal("Cannot handle received packet: {}", hci::EventCodeText(code)); - break; - } - } - - void OnConnectionClosed(hci::Address address) override { log::info("Called"); } -}; - -class SecurityManagerChannelTest : public ::testing::Test { -protected: - void SetUp() override { - hci::Address address; - hci::Address::FromString("01:23:45:67:89:AB:CD", address); - device_ = hci::AddressWithType(address, hci::AddressType::PUBLIC_DEVICE_ADDRESS); - on_link_connected_called = false; - on_link_disconnected_called = false; - handler_ = new Handler(&thread_); - callback_ = new SecurityManagerChannelCallback(); - hci_layer_ = new FakeHciLayer(); - fake_registry_.InjectTestModule(&FakeHciLayer::Factory, hci_layer_); - fake_registry_.Start<FakeHciLayer>(&thread_); - channel_ = new FakeSecurityManagerChannel(handler_, hci_layer_); - channel_->SetChannelListener(callback_); - security_interface_ = new FakeSecurityInterface(handler_, channel_); - channel_->SetSecurityInterface(security_interface_); - } - - void TearDown() override { - channel_->SetChannelListener(nullptr); - handler_->Clear(); - synchronize(); - fake_registry_.StopAll(); - delete handler_; - delete channel_; - delete callback_; - delete security_interface_; - } - - void synchronize() { - fake_registry_.SynchronizeModuleHandler(&FakeHciLayer::Factory, std::chrono::milliseconds(20)); - } - - TestModuleRegistry fake_registry_; - Thread& thread_ = fake_registry_.GetTestThread(); - Handler* handler_ = nullptr; - FakeHciLayer* hci_layer_ = nullptr; - l2cap::classic::SecurityInterface* security_interface_ = nullptr; - SecurityManagerChannel* channel_ = nullptr; - SecurityManagerChannelCallback* callback_ = nullptr; - hci::AddressWithType device_; -}; - -TEST_F(SecurityManagerChannelTest, setup_teardown) {} - -TEST_F(SecurityManagerChannelTest, recv_io_cap_request) { - hci_layer_->IncomingEvent(hci::IoCapabilityRequestBuilder::Create(device_.GetAddress())); - synchronize(); - ASSERT_TRUE(callback_->receivedIoCapabilityRequest); -} - -TEST_F(SecurityManagerChannelTest, send_io_cap_request_reply) { - // Arrange - hci::IoCapability io_capability = (hci::IoCapability)0x00; - OobDataPresent oob_present = (OobDataPresent)0x00; - AuthenticationRequirements authentication_requirements = (AuthenticationRequirements)0x00; - auto packet = hci::IoCapabilityRequestReplyBuilder::Create( - device_.GetAddress(), io_capability, oob_present, authentication_requirements); - - // Act - channel_->SendCommand(std::move(packet)); - auto last_command = std::move(hci_layer_->GetLastCommand()->command); - auto command_packet = GetPacketView(std::move(last_command)); - hci::CommandView packet_view = hci::CommandView::Create(command_packet); - - // Assert - ASSERT_TRUE(packet_view.IsValid()); - ASSERT_EQ(OpCode::IO_CAPABILITY_REQUEST_REPLY, packet_view.GetOpCode()); -} - -TEST_F(SecurityManagerChannelTest, send_io_cap_request_neg_reply) { - // Arrange - auto packet = hci::IoCapabilityRequestNegativeReplyBuilder::Create( - device_.GetAddress(), hci::ErrorCode::COMMAND_DISALLOWED); - - // Act - channel_->SendCommand(std::move(packet)); - auto last_command = std::move(hci_layer_->GetLastCommand()->command); - auto command_packet = GetPacketView(std::move(last_command)); - hci::CommandView packet_view = hci::CommandView::Create(command_packet); - - // Assert - ASSERT_TRUE(packet_view.IsValid()); - ASSERT_EQ(OpCode::IO_CAPABILITY_REQUEST_NEGATIVE_REPLY, packet_view.GetOpCode()); -} - -TEST_F(SecurityManagerChannelTest, recv_io_cap_response) { - hci::IoCapability io_capability = (hci::IoCapability)0x00; - OobDataPresent oob_present = (OobDataPresent)0x00; - AuthenticationRequirements authentication_requirements = (AuthenticationRequirements)0x00; - hci_layer_->IncomingEvent(hci::IoCapabilityResponseBuilder::Create( - device_.GetAddress(), io_capability, oob_present, authentication_requirements)); - synchronize(); - ASSERT_TRUE(callback_->receivedIoCapabilityResponse); -} - -TEST_F(SecurityManagerChannelTest, recv_pin_code_request) { - hci_layer_->IncomingEvent(hci::PinCodeRequestBuilder::Create(device_.GetAddress())); - synchronize(); - ASSERT_TRUE(callback_->receivedPinCodeRequest); -} - -TEST_F(SecurityManagerChannelTest, send_pin_code_request_reply) { - // Arrange - uint8_t pin_code_length = 6; - std::array<uint8_t, 16> pin_code = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5}; - auto packet = - hci::PinCodeRequestReplyBuilder::Create(device_.GetAddress(), pin_code_length, pin_code); - - // Act - channel_->SendCommand(std::move(packet)); - auto last_command = std::move(hci_layer_->GetLastCommand()->command); - auto command_packet = GetPacketView(std::move(last_command)); - hci::CommandView packet_view = hci::CommandView::Create(command_packet); - - // Assert - ASSERT_TRUE(packet_view.IsValid()); - ASSERT_EQ(OpCode::PIN_CODE_REQUEST_REPLY, packet_view.GetOpCode()); -} - -TEST_F(SecurityManagerChannelTest, send_pin_code_request_neg_reply) { - // Arrange - auto packet = hci::PinCodeRequestNegativeReplyBuilder::Create(device_.GetAddress()); - - // Act - channel_->SendCommand(std::move(packet)); - auto last_command = std::move(hci_layer_->GetLastCommand()->command); - auto command_packet = GetPacketView(std::move(last_command)); - hci::CommandView packet_view = hci::CommandView::Create(command_packet); - - // Assert - ASSERT_TRUE(packet_view.IsValid()); - ASSERT_EQ(OpCode::PIN_CODE_REQUEST_NEGATIVE_REPLY, packet_view.GetOpCode()); -} - -TEST_F(SecurityManagerChannelTest, recv_user_passkey_notification) { - uint32_t passkey = 0x00; - hci_layer_->IncomingEvent( - hci::UserPasskeyNotificationBuilder::Create(device_.GetAddress(), passkey)); - synchronize(); - ASSERT_TRUE(callback_->receivedUserPasskeyNotification); -} - -TEST_F(SecurityManagerChannelTest, recv_user_confirmation_request) { - uint32_t numeric_value = 0x0; - hci_layer_->IncomingEvent( - hci::UserConfirmationRequestBuilder::Create(device_.GetAddress(), numeric_value)); - synchronize(); - ASSERT_TRUE(callback_->receivedUserConfirmationRequest); -} - -TEST_F(SecurityManagerChannelTest, send_user_confirmation_request_reply) { - // Arrange - auto packet = hci::UserConfirmationRequestReplyBuilder::Create(device_.GetAddress()); - - // Act - channel_->SendCommand(std::move(packet)); - auto last_command = std::move(hci_layer_->GetLastCommand()->command); - auto command_packet = GetPacketView(std::move(last_command)); - hci::CommandView packet_view = hci::CommandView::Create(command_packet); - - // Assert - ASSERT_TRUE(packet_view.IsValid()); - ASSERT_EQ(OpCode::USER_CONFIRMATION_REQUEST_REPLY, packet_view.GetOpCode()); -} - -TEST_F(SecurityManagerChannelTest, send_user_confirmation_request_negative_reply) { - // Arrange - auto packet = hci::UserConfirmationRequestNegativeReplyBuilder::Create(device_.GetAddress()); - - // Act - channel_->SendCommand(std::move(packet)); - auto last_command = std::move(hci_layer_->GetLastCommand()->command); - auto command_packet = GetPacketView(std::move(last_command)); - hci::CommandView packet_view = hci::CommandView::Create(command_packet); - - // Assert - ASSERT_TRUE(packet_view.IsValid()); - ASSERT_EQ(OpCode::USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY, packet_view.GetOpCode()); -} - -TEST_F(SecurityManagerChannelTest, recv_remote_oob_data_request) { - hci_layer_->IncomingEvent(hci::RemoteOobDataRequestBuilder::Create(device_.GetAddress())); - synchronize(); - ASSERT_TRUE(callback_->receivedRemoteOobDataRequest); -} - -TEST_F(SecurityManagerChannelTest, send_remote_oob_data_request_reply) { - // Arrange - std::array<uint8_t, 16> c = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5}; - std::array<uint8_t, 16> r = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5}; - auto packet = hci::RemoteOobDataRequestReplyBuilder::Create(device_.GetAddress(), c, r); - - // Act - channel_->SendCommand(std::move(packet)); - auto last_command = std::move(hci_layer_->GetLastCommand()->command); - auto command_packet = GetPacketView(std::move(last_command)); - hci::CommandView packet_view = hci::CommandView::Create(command_packet); - - // Assert - ASSERT_TRUE(packet_view.IsValid()); - ASSERT_EQ(OpCode::REMOTE_OOB_DATA_REQUEST_REPLY, packet_view.GetOpCode()); -} - -TEST_F(SecurityManagerChannelTest, send_remote_oob_data_request_neg_reply) { - // Arrange - auto packet = hci::RemoteOobDataRequestNegativeReplyBuilder::Create(device_.GetAddress()); - - // Act - channel_->SendCommand(std::move(packet)); - auto last_command = std::move(hci_layer_->GetLastCommand()->command); - auto command_packet = GetPacketView(std::move(last_command)); - hci::CommandView packet_view = hci::CommandView::Create(command_packet); - - // Assert - ASSERT_TRUE(packet_view.IsValid()); - ASSERT_EQ(OpCode::REMOTE_OOB_DATA_REQUEST_NEGATIVE_REPLY, packet_view.GetOpCode()); -} - -TEST_F(SecurityManagerChannelTest, send_read_local_oob_data) { - // Arrange - auto packet = hci::ReadLocalOobDataBuilder::Create(); - - // Act - channel_->SendCommand(std::move(packet)); - auto last_command = std::move(hci_layer_->GetLastCommand()->command); - auto command_packet = GetPacketView(std::move(last_command)); - hci::CommandView packet_view = hci::CommandView::Create(command_packet); - - // Assert - ASSERT_TRUE(packet_view.IsValid()); - ASSERT_EQ(OpCode::READ_LOCAL_OOB_DATA, packet_view.GetOpCode()); -} - -TEST_F(SecurityManagerChannelTest, send_read_local_oob_extended_data) { - // Arrange - auto packet = hci::ReadLocalOobExtendedDataBuilder::Create(); - - // Act - channel_->SendCommand(std::move(packet)); - auto last_command = std::move(hci_layer_->GetLastCommand()->command); - auto command_packet = GetPacketView(std::move(last_command)); - hci::CommandView packet_view = hci::CommandView::Create(command_packet); - - // Assert - ASSERT_TRUE(packet_view.IsValid()); - ASSERT_EQ(OpCode::READ_LOCAL_OOB_EXTENDED_DATA, packet_view.GetOpCode()); -} - -TEST_F(SecurityManagerChannelTest, recv_link_key_request) { - hci_layer_->IncomingEvent(hci::LinkKeyRequestBuilder::Create(device_.GetAddress())); - synchronize(); - ASSERT_TRUE(callback_->receivedLinkKeyRequest); -} - -TEST_F(SecurityManagerChannelTest, recv_link_key_notification) { - std::array<uint8_t, 16> link_key = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5}; - hci_layer_->IncomingEvent(hci::LinkKeyNotificationBuilder::Create( - device_.GetAddress(), link_key, hci::KeyType::DEBUG_COMBINATION)); - synchronize(); - ASSERT_TRUE(callback_->receivedLinkKeyNotification); -} - -TEST_F(SecurityManagerChannelTest, recv_central_link_key_complete) { - uint16_t connection_handle = 0x0; - hci_layer_->IncomingEvent(hci::CentralLinkKeyCompleteBuilder::Create( - hci::ErrorCode::SUCCESS, connection_handle, hci::KeyFlag::TEMPORARY)); - synchronize(); - ASSERT_TRUE(callback_->receivedCentralLinkKeyComplete); -} - -TEST_F(SecurityManagerChannelTest, recv_change_connection_link_key_complete) { - uint16_t connection_handle = 0x0; - hci_layer_->IncomingEvent(hci::ChangeConnectionLinkKeyCompleteBuilder::Create( - hci::ErrorCode::SUCCESS, connection_handle)); - synchronize(); - ASSERT_TRUE(callback_->receivedChangeConnectionLinkKeyComplete); -} - -TEST_F(SecurityManagerChannelTest, recv_return_link_keys) { - std::vector<hci::ZeroKeyAndAddress> keys; - hci_layer_->IncomingEvent(hci::ReturnLinkKeysBuilder::Create(keys)); - synchronize(); - ASSERT_TRUE(callback_->receivedReturnLinkKeys); -} - -TEST_F(SecurityManagerChannelTest, send_link_key_request_reply) { - // Arrange - std::array<uint8_t, 16> link_key = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5}; - auto packet = hci::LinkKeyRequestReplyBuilder::Create(device_.GetAddress(), link_key); - - // Act - channel_->SendCommand(std::move(packet)); - auto last_command = std::move(hci_layer_->GetLastCommand()->command); - auto command_packet = GetPacketView(std::move(last_command)); - hci::CommandView packet_view = hci::CommandView::Create(command_packet); - - // Assert - ASSERT_TRUE(packet_view.IsValid()); - ASSERT_EQ(OpCode::LINK_KEY_REQUEST_REPLY, packet_view.GetOpCode()); -} - -TEST_F(SecurityManagerChannelTest, send_link_key_request_neg_reply) { - // Arrange - auto packet = hci::LinkKeyRequestNegativeReplyBuilder::Create(device_.GetAddress()); - - // Act - channel_->SendCommand(std::move(packet)); - auto last_command = std::move(hci_layer_->GetLastCommand()->command); - auto command_packet = GetPacketView(std::move(last_command)); - hci::CommandView packet_view = hci::CommandView::Create(command_packet); - - // Assert - ASSERT_TRUE(packet_view.IsValid()); - ASSERT_EQ(OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, packet_view.GetOpCode()); -} - -TEST_F(SecurityManagerChannelTest, send_read_stored_link_key) { - // Arrange - auto packet = hci::ReadStoredLinkKeyBuilder::Create(device_.GetAddress(), - hci::ReadStoredLinkKeyReadAllFlag::ALL); - - // Act - channel_->SendCommand(std::move(packet)); - auto last_command = std::move(hci_layer_->GetLastCommand()->command); - auto command_packet = GetPacketView(std::move(last_command)); - hci::CommandView packet_view = hci::CommandView::Create(command_packet); - - // Assert - ASSERT_TRUE(packet_view.IsValid()); - ASSERT_EQ(OpCode::READ_STORED_LINK_KEY, packet_view.GetOpCode()); -} - -TEST_F(SecurityManagerChannelTest, send_write_stored_link_key) { - // Arrange - std::vector<hci::KeyAndAddress> keys_to_write; - auto packet = hci::WriteStoredLinkKeyBuilder::Create(keys_to_write); - - // Act - channel_->SendCommand(std::move(packet)); - auto last_command = std::move(hci_layer_->GetLastCommand()->command); - auto command_packet = GetPacketView(std::move(last_command)); - hci::CommandView packet_view = hci::CommandView::Create(command_packet); - - // Assert - ASSERT_TRUE(packet_view.IsValid()); - ASSERT_EQ(OpCode::WRITE_STORED_LINK_KEY, packet_view.GetOpCode()); -} - -TEST_F(SecurityManagerChannelTest, send_delete_stored_link_key) { - // Arrange - auto packet = hci::DeleteStoredLinkKeyBuilder::Create(device_.GetAddress(), - hci::DeleteStoredLinkKeyDeleteAllFlag::ALL); - - // Act - channel_->SendCommand(std::move(packet)); - auto last_command = std::move(hci_layer_->GetLastCommand()->command); - auto command_packet = GetPacketView(std::move(last_command)); - hci::CommandView packet_view = hci::CommandView::Create(command_packet); - - // Assert - ASSERT_TRUE(packet_view.IsValid()); - ASSERT_EQ(OpCode::DELETE_STORED_LINK_KEY, packet_view.GetOpCode()); -} - -TEST_F(SecurityManagerChannelTest, recv_encryption_change) { - uint16_t connection_handle = 0x0; - hci_layer_->IncomingEvent(hci::EncryptionChangeBuilder::Create( - hci::ErrorCode::SUCCESS, connection_handle, hci::EncryptionEnabled::ON)); - synchronize(); - ASSERT_TRUE(callback_->receivedEncryptionChange); -} - -TEST_F(SecurityManagerChannelTest, recv_encryption_change_v2) { - uint16_t connection_handle = 0x0; - hci_layer_->IncomingEvent(hci::EncryptionChangeV2Builder::Create( - hci::ErrorCode::SUCCESS, connection_handle, hci::EncryptionEnabled::ON, 0x10)); - synchronize(); - ASSERT_TRUE(callback_->receivedEncryptionChangeV2); -} - -TEST_F(SecurityManagerChannelTest, recv_encryption_key_refresh) { - uint16_t connection_handle = 0x0; - hci_layer_->IncomingEvent(hci::EncryptionKeyRefreshCompleteBuilder::Create( - hci::ErrorCode::SUCCESS, connection_handle)); - synchronize(); - ASSERT_TRUE(callback_->receivedEncryptionKeyRefreshComplete); -} - -TEST_F(SecurityManagerChannelTest, send_refresh_encryption_key) { - // Arrange - uint16_t connection_handle = 0x0; - auto packet = hci::RefreshEncryptionKeyBuilder::Create(connection_handle); - - // Act - channel_->SendCommand(std::move(packet)); - auto last_command = std::move(hci_layer_->GetLastCommand()->command); - auto command_packet = GetPacketView(std::move(last_command)); - hci::CommandView packet_view = hci::CommandView::Create(command_packet); - - // Assert - ASSERT_TRUE(packet_view.IsValid()); - ASSERT_EQ(OpCode::REFRESH_ENCRYPTION_KEY, packet_view.GetOpCode()); -} - -TEST_F(SecurityManagerChannelTest, send_read_encryption_key_size) { - // Arrange - uint16_t connection_handle = 0x0; - auto packet = hci::ReadEncryptionKeySizeBuilder::Create(connection_handle); - - // Act - channel_->SendCommand(std::move(packet)); - auto last_command = std::move(hci_layer_->GetLastCommand()->command); - auto command_packet = GetPacketView(std::move(last_command)); - hci::CommandView packet_view = hci::CommandView::Create(command_packet); - - // Assert - ASSERT_TRUE(packet_view.IsValid()); - ASSERT_EQ(OpCode::READ_ENCRYPTION_KEY_SIZE, packet_view.GetOpCode()); -} - -TEST_F(SecurityManagerChannelTest, recv_simple_pairing_complete) { - hci_layer_->IncomingEvent( - hci::SimplePairingCompleteBuilder::Create(hci::ErrorCode::SUCCESS, device_.GetAddress())); - synchronize(); - ASSERT_TRUE(callback_->receivedSimplePairingComplete); -} - -TEST_F(SecurityManagerChannelTest, send_read_simple_pairing_mode) { - // Arrange - auto packet = hci::ReadSimplePairingModeBuilder::Create(); - - // Act - channel_->SendCommand(std::move(packet)); - auto last_command = std::move(hci_layer_->GetLastCommand()->command); - auto command_packet = GetPacketView(std::move(last_command)); - hci::CommandView packet_view = hci::CommandView::Create(command_packet); - - // Assert - ASSERT_TRUE(packet_view.IsValid()); - ASSERT_EQ(OpCode::READ_SIMPLE_PAIRING_MODE, packet_view.GetOpCode()); -} - -TEST_F(SecurityManagerChannelTest, send_write_simple_pairing_mode) { - // Arrange - auto packet = hci::WriteSimplePairingModeBuilder::Create(hci::Enable::ENABLED); - - // Act - channel_->SendCommand(std::move(packet)); - auto last_command = std::move(hci_layer_->GetLastCommand()->command); - auto command_packet = GetPacketView(std::move(last_command)); - hci::CommandView packet_view = hci::CommandView::Create(command_packet); - - // Assert - ASSERT_TRUE(packet_view.IsValid()); - ASSERT_EQ(OpCode::WRITE_SIMPLE_PAIRING_MODE, packet_view.GetOpCode()); -} - -TEST_F(SecurityManagerChannelTest, recv_keypress_notification) { - hci_layer_->IncomingEvent(hci::KeypressNotificationBuilder::Create( - device_.GetAddress(), hci::KeypressNotificationType::ENTRY_COMPLETED)); - synchronize(); - ASSERT_TRUE(callback_->receivedKeypressNotification); -} - -TEST_F(SecurityManagerChannelTest, send_keypress_notification) { - // Arrange - auto packet = hci::SendKeypressNotificationBuilder::Create( - device_.GetAddress(), hci::KeypressNotificationType::ENTRY_STARTED); - - // Act - channel_->SendCommand(std::move(packet)); - auto last_command = std::move(hci_layer_->GetLastCommand()->command); - auto command_packet = GetPacketView(std::move(last_command)); - hci::CommandView packet_view = hci::CommandView::Create(command_packet); - - // Assert - ASSERT_TRUE(packet_view.IsValid()); - ASSERT_EQ(OpCode::SEND_KEYPRESS_NOTIFICATION, packet_view.GetOpCode()); -} - -TEST_F(SecurityManagerChannelTest, recv_user_passkey_request) { - hci_layer_->IncomingEvent(hci::UserPasskeyRequestBuilder::Create(device_.GetAddress())); - synchronize(); - ASSERT_TRUE(callback_->receivedUserPasskeyRequest); -} - -TEST_F(SecurityManagerChannelTest, test_l2cap_security_interface_api) { - ASSERT_FALSE(on_link_connected_called); - channel_->Connect(device_.GetAddress()); - ASSERT_TRUE(on_link_connected_called); - ASSERT_FALSE(on_link_disconnected_called); - channel_->Release(device_.GetAddress()); - // TODO(optedoblivion): Lock and wait - // ASSERT_TRUE(on_link_disconnected_called); -} - -} // namespace -} // namespace channel -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/ecc/multipoint_test.cc b/system/gd/security/ecc/multipoint_test.cc deleted file mode 100644 index 95e43d4c3b..0000000000 --- a/system/gd/security/ecc/multipoint_test.cc +++ /dev/null @@ -1,112 +0,0 @@ -/****************************************************************************** - * - * Copyright 2019 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 "security/ecc/p_256_ecc_pp.h" - -namespace bluetooth { -namespace security { -namespace ecc { - -// Test ECC point validation -TEST(SmpEccValidationTest, test_valid_points) { - Point p; - - // Test data from Bluetooth Core Specification - // Version 5.0 | Vol 2, Part G | 7.1.2 - - // Sample 1 - p.x[7] = 0x20b003d2; - p.x[6] = 0xf297be2c; - p.x[5] = 0x5e2c83a7; - p.x[4] = 0xe9f9a5b9; - p.x[3] = 0xeff49111; - p.x[2] = 0xacf4fddb; - p.x[1] = 0xcc030148; - p.x[0] = 0x0e359de6; - - p.y[7] = 0xdc809c49; - p.y[6] = 0x652aeb6d; - p.y[5] = 0x63329abf; - p.y[4] = 0x5a52155c; - p.y[3] = 0x766345c2; - p.y[2] = 0x8fed3024; - p.y[1] = 0x741c8ed0; - p.y[0] = 0x1589d28b; - - EXPECT_TRUE(ECC_ValidatePoint(p)); - - // Sample 2 - p.x[7] = 0x2c31a47b; - p.x[6] = 0x5779809e; - p.x[5] = 0xf44cb5ea; - p.x[4] = 0xaf5c3e43; - p.x[3] = 0xd5f8faad; - p.x[2] = 0x4a8794cb; - p.x[1] = 0x987e9b03; - p.x[0] = 0x745c78dd; - - p.y[7] = 0x91951218; - p.y[6] = 0x3898dfbe; - p.y[5] = 0xcd52e240; - p.y[4] = 0x8e43871f; - p.y[3] = 0xd0211091; - p.y[2] = 0x17bd3ed4; - p.y[1] = 0xeaf84377; - p.y[0] = 0x43715d4f; - - EXPECT_TRUE(ECC_ValidatePoint(p)); -} - -TEST(SmpEccValidationTest, test_invalid_points) { - Point p; - multiprecision_init(p.x); - multiprecision_init(p.y); - - EXPECT_FALSE(ECC_ValidatePoint(p)); - - // Sample 1 - p.x[7] = 0x20b003d2; - p.x[6] = 0xf297be2c; - p.x[5] = 0x5e2c83a7; - p.x[4] = 0xe9f9a5b9; - p.x[3] = 0xeff49111; - p.x[2] = 0xacf4fddb; - p.x[1] = 0xcc030148; - p.x[0] = 0x0e359de6; - - EXPECT_FALSE(ECC_ValidatePoint(p)); - - p.y[7] = 0xdc809c49; - p.y[6] = 0x652aeb6d; - p.y[5] = 0x63329abf; - p.y[4] = 0x5a52155c; - p.y[3] = 0x766345c2; - p.y[2] = 0x8fed3024; - p.y[1] = 0x741c8ed0; - p.y[0] = 0x1589d28b; - - p.y[0]--; - - EXPECT_FALSE(ECC_ValidatePoint(p)); -} - -} // namespace ecc -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/ecc/multprecision.cc b/system/gd/security/ecc/multprecision.cc deleted file mode 100644 index 9f5153ed47..0000000000 --- a/system/gd/security/ecc/multprecision.cc +++ /dev/null @@ -1,531 +0,0 @@ -/****************************************************************************** - * - * Copyright 2006-2015 Broadcom Corporation - * - * 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. - * - ******************************************************************************/ - -/******************************************************************************* - * - * This file contains simple pairing algorithms - * - ******************************************************************************/ - -#include "security/ecc/multprecision.h" - -namespace bluetooth { -namespace security { -namespace ecc { - -#define DWORD_BITS 32 -#define DWORD_BYTES 4 -#define DWORD_BITS_SHIFT 5 - -void multiprecision_init(uint32_t* c) { - for (uint32_t i = 0; i < KEY_LENGTH_DWORDS_P256; i++) { - c[i] = 0; - } -} - -void multiprecision_copy(uint32_t* c, const uint32_t* a) { - for (uint32_t i = 0; i < KEY_LENGTH_DWORDS_P256; i++) { - c[i] = a[i]; - } -} - -int multiprecision_compare(const uint32_t* a, const uint32_t* b) { - for (int i = KEY_LENGTH_DWORDS_P256 - 1; i >= 0; i--) { - if (a[i] > b[i]) { - return 1; - } - if (a[i] < b[i]) { - return -1; - } - } - return 0; -} - -int multiprecision_iszero(const uint32_t* a) { - for (uint32_t i = 0; i < KEY_LENGTH_DWORDS_P256; i++) { - if (a[i]) { - return 0; - } - } - - return 1; -} - -uint32_t multiprecision_dword_bits(uint32_t a) { - uint32_t i; - for (i = 0; i < DWORD_BITS; i++, a >>= 1) { - if (a == 0) { - break; - } - } - - return i; -} - -uint32_t multiprecision_most_signdwords(const uint32_t* a) { - int i; - for (i = KEY_LENGTH_DWORDS_P256 - 1; i >= 0; i--) { - if (a[i]) { - break; - } - } - return i + 1; -} - -uint32_t multiprecision_most_signbits(const uint32_t* a) { - int aMostSignDWORDs; - - aMostSignDWORDs = multiprecision_most_signdwords(a); - if (aMostSignDWORDs == 0) { - return 0; - } - - return ((aMostSignDWORDs - 1) << DWORD_BITS_SHIFT) + - multiprecision_dword_bits(a[aMostSignDWORDs - 1]); -} - -uint32_t multiprecision_add(uint32_t* c, const uint32_t* a, const uint32_t* b) { - uint32_t carrier; - uint32_t temp; - - carrier = 0; - for (uint32_t i = 0; i < KEY_LENGTH_DWORDS_P256; i++) { - temp = a[i] + carrier; - carrier = (temp < carrier); - temp += b[i]; - carrier |= (temp < b[i]); - c[i] = temp; - } - - return carrier; -} - -// c=a-b -uint32_t multiprecision_sub(uint32_t* c, const uint32_t* a, const uint32_t* b) { - uint32_t borrow; - uint32_t temp; - - borrow = 0; - for (uint32_t i = 0; i < KEY_LENGTH_DWORDS_P256; i++) { - temp = a[i] - borrow; - borrow = (temp > a[i]); - c[i] = temp - b[i]; - borrow |= (c[i] > temp); - } - - return borrow; -} - -// c = a << 1 -void multiprecision_lshift_mod(uint32_t* c, const uint32_t* a, const uint32_t* modp) { - uint32_t carrier = multiprecision_lshift(c, a); - if (carrier) { - multiprecision_sub(c, c, modp); - } else if (multiprecision_compare(c, modp) >= 0) { - multiprecision_sub(c, c, modp); - } -} - -// c=a>>1 -void multiprecision_rshift(uint32_t* c, const uint32_t* a) { - int j; - uint32_t b = 1; - - j = DWORD_BITS - b; - - uint32_t carrier = 0; - uint32_t temp; - for (int i = KEY_LENGTH_DWORDS_P256 - 1; i >= 0; i--) { - temp = a[i]; // in case of c==a - c[i] = (temp >> b) | carrier; - carrier = temp << j; - } -} - -// Curve specific optimization when p is a pseudo-Mersenns prime, -// p=2^(KEY_LENGTH_BITS)-omega -void multiprecision_mersenns_mult_mod(uint32_t* c, const uint32_t* a, const uint32_t* b, - const uint32_t* modp) { - uint32_t cc[2 * KEY_LENGTH_DWORDS_P256]; - - multiprecision_mult(cc, a, b); - multiprecision_fast_mod_P256(c, cc, modp); -} - -// Curve specific optimization when p is a pseudo-Mersenns prime -void multiprecision_mersenns_squa_mod(uint32_t* c, const uint32_t* a, const uint32_t* modp) { - multiprecision_mersenns_mult_mod(c, a, a, modp); -} - -// c=(a+b) mod p, b<p, a<p -void multiprecision_add_mod(uint32_t* c, const uint32_t* a, const uint32_t* b, - const uint32_t* modp) { - uint32_t carrier = multiprecision_add(c, a, b); - if (carrier) { - multiprecision_sub(c, c, modp); - } else if (multiprecision_compare(c, modp) >= 0) { - multiprecision_sub(c, c, modp); - } -} - -// c=(a-b) mod p, a<p, b<p -void multiprecision_sub_mod(uint32_t* c, const uint32_t* a, const uint32_t* b, - const uint32_t* modp) { - uint32_t borrow; - - borrow = multiprecision_sub(c, a, b); - if (borrow) { - multiprecision_add(c, c, modp); - } -} - -// c=a<<b, b<DWORD_BITS, c has a buffer size of Numuint32_ts+1 -uint32_t multiprecision_lshift(uint32_t* c, const uint32_t* a) { - int j; - uint32_t b = 1; - j = DWORD_BITS - b; - - uint32_t carrier = 0; - uint32_t temp; - - for (uint32_t i = 0; i < KEY_LENGTH_DWORDS_P256; i++) { - temp = a[i]; // in case c==a - c[i] = (temp << b) | carrier; - carrier = temp >> j; - } - - return carrier; -} - -// c=a*b; c must have a buffer of 2*Key_LENGTH_uint32_tS, c != a != b -void multiprecision_mult(uint32_t* c, const uint32_t* a, const uint32_t* b) { - uint32_t W; - uint32_t U; - uint32_t V; - - U = V = W = 0; - multiprecision_init(c); - - // assume little endian right now - for (uint32_t i = 0; i < KEY_LENGTH_DWORDS_P256; i++) { - U = 0; - for (uint32_t j = 0; j < KEY_LENGTH_DWORDS_P256; j++) { - uint64_t result; - result = ((uint64_t)a[i]) * ((uint64_t)b[j]); - W = result >> 32; - V = a[i] * b[j]; - V = V + U; - U = (V < U); - U += W; - V = V + c[i + j]; - U += (V < c[i + j]); - c[i + j] = V; - } - c[i + KEY_LENGTH_DWORDS_P256] = U; - } -} - -void multiprecision_fast_mod_P256(uint32_t* c, const uint32_t* a, const uint32_t* modp) { - uint32_t A; - uint32_t B; - uint32_t C; - uint32_t D; - uint32_t E; - uint32_t F; - uint32_t G; - uint8_t UA; - uint8_t UB; - uint8_t UC; - uint8_t UD; - uint8_t UE; - uint8_t UF; - uint8_t UG; - uint32_t U; - - // C = a[13] + a[14] + a[15]; - C = a[13]; - C += a[14]; - UC = (C < a[14]); - C += a[15]; - UC += (C < a[15]); - - // E = a[8] + a[9]; - E = a[8]; - E += a[9]; - UE = (E < a[9]); - - // F = a[9] + a[10]; - F = a[9]; - F += a[10]; - UF = (F < a[10]); - - // G = a[10] + a[11] - G = a[10]; - G += a[11]; - UG = (G < a[11]); - - // B = a[12] + a[13] + a[14] + a[15] == C + a[12] - B = C; - UB = UC; - B += a[12]; - UB += (B < a[12]); - - // A = a[11] + a[12] + a[13] + a[14] == B + a[11] - a[15] - A = B; - UA = UB; - A += a[11]; - UA += (A < a[11]); - UA -= (A < a[15]); - A -= a[15]; - - // D = a[10] + a[11] + a[12] + a[13] == A + a[10] - a[14] - D = A; - UD = UA; - D += a[10]; - UD += (D < a[10]); - UD -= (D < a[14]); - D -= a[14]; - - c[0] = a[0]; - c[0] += E; - U = (c[0] < E); - U += UE; - U -= (c[0] < A); - U -= UA; - c[0] -= A; - - if (U & 0x80000000) { - uint32_t UU; - UU = 0 - U; - U = (a[1] < UU); - c[1] = a[1] - UU; - } else { - c[1] = a[1] + U; - U = (c[1] < a[1]); - } - - c[1] += F; - U += (c[1] < F); - U += UF; - U -= (c[1] < B); - U -= UB; - c[1] -= B; - - if (U & 0x80000000) { - uint32_t UU; - UU = 0 - U; - U = (a[2] < UU); - c[2] = a[2] - UU; - } else { - c[2] = a[2] + U; - U = (c[2] < a[2]); - } - - c[2] += G; - U += (c[2] < G); - U += UG; - U -= (c[2] < C); - U -= UC; - c[2] -= C; - - if (U & 0x80000000) { - uint32_t UU; - UU = 0 - U; - U = (a[3] < UU); - c[3] = a[3] - UU; - } else { - c[3] = a[3] + U; - U = (c[3] < a[3]); - } - - c[3] += A; - U += (c[3] < A); - U += UA; - c[3] += a[11]; - U += (c[3] < a[11]); - c[3] += a[12]; - U += (c[3] < a[12]); - U -= (c[3] < a[14]); - c[3] -= a[14]; - U -= (c[3] < a[15]); - c[3] -= a[15]; - U -= (c[3] < E); - U -= UE; - c[3] -= E; - - if (U & 0x80000000) { - uint32_t UU; - UU = 0 - U; - U = (a[4] < UU); - c[4] = a[4] - UU; - } else { - c[4] = a[4] + U; - U = (c[4] < a[4]); - } - - c[4] += B; - U += (c[4] < B); - U += UB; - U -= (c[4] < a[15]); - c[4] -= a[15]; - c[4] += a[12]; - U += (c[4] < a[12]); - c[4] += a[13]; - U += (c[4] < a[13]); - U -= (c[4] < F); - U -= UF; - c[4] -= F; - - if (U & 0x80000000) { - uint32_t UU; - UU = 0 - U; - U = (a[5] < UU); - c[5] = a[5] - UU; - } else { - c[5] = a[5] + U; - U = (c[5] < a[5]); - } - - c[5] += C; - U += (c[5] < C); - U += UC; - c[5] += a[13]; - U += (c[5] < a[13]); - c[5] += a[14]; - U += (c[5] < a[14]); - U -= (c[5] < G); - U -= UG; - c[5] -= G; - - if (U & 0x80000000) { - uint32_t UU; - UU = 0 - U; - U = (a[6] < UU); - c[6] = a[6] - UU; - } else { - c[6] = a[6] + U; - U = (c[6] < a[6]); - } - - c[6] += C; - U += (c[6] < C); - U += UC; - c[6] += a[14]; - U += (c[6] < a[14]); - c[6] += a[14]; - U += (c[6] < a[14]); - c[6] += a[15]; - U += (c[6] < a[15]); - U -= (c[6] < E); - U -= UE; - c[6] -= E; - - if (U & 0x80000000) { - uint32_t UU; - UU = 0 - U; - U = (a[7] < UU); - c[7] = a[7] - UU; - } else { - c[7] = a[7] + U; - U = (c[7] < a[7]); - } - - c[7] += a[15]; - U += (c[7] < a[15]); - c[7] += a[15]; - U += (c[7] < a[15]); - c[7] += a[15]; - U += (c[7] < a[15]); - c[7] += a[8]; - U += (c[7] < a[8]); - U -= (c[7] < D); - U -= UD; - c[7] -= D; - - if (U & 0x80000000) { - while (U) { - multiprecision_add(c, c, modp); - U++; - } - } else if (U) { - while (U) { - multiprecision_sub(c, c, modp); - U--; - } - } - - if (multiprecision_compare(c, modp) >= 0) { - multiprecision_sub(c, c, modp); - } -} - -void multiprecision_inv_mod(uint32_t* aminus, uint32_t* u, const uint32_t* modp) { - uint32_t v[KEY_LENGTH_DWORDS_P256]; - uint32_t A[KEY_LENGTH_DWORDS_P256 + 1]; - uint32_t C[KEY_LENGTH_DWORDS_P256 + 1]; - - multiprecision_copy(v, modp); - multiprecision_init(A); - multiprecision_init(C); - A[0] = 1; - - while (!multiprecision_iszero(u)) { - while (!(u[0] & 0x01)) // u is even - { - multiprecision_rshift(u, u); - if (!(A[0] & 0x01)) { // A is even - multiprecision_rshift(A, A); - } else { - A[KEY_LENGTH_DWORDS_P256] = multiprecision_add(A, A, modp); // A =A+p - multiprecision_rshift(A, A); - A[KEY_LENGTH_DWORDS_P256 - 1] |= (A[KEY_LENGTH_DWORDS_P256] << 31); - } - } - - while (!(v[0] & 0x01)) // v is even - { - multiprecision_rshift(v, v); - if (!(C[0] & 0x01)) // C is even - { - multiprecision_rshift(C, C); - } else { - C[KEY_LENGTH_DWORDS_P256] = multiprecision_add(C, C, modp); // C =C+p - multiprecision_rshift(C, C); - C[KEY_LENGTH_DWORDS_P256 - 1] |= (C[KEY_LENGTH_DWORDS_P256] << 31); - } - } - - if (multiprecision_compare(u, v) >= 0) { - multiprecision_sub(u, u, v); - multiprecision_sub_mod(A, A, C, modp); - } else { - multiprecision_sub(v, v, u); - multiprecision_sub_mod(C, C, A, modp); - } - } - - if (multiprecision_compare(C, modp) >= 0) { - multiprecision_sub(aminus, C, modp); - } else { - multiprecision_copy(aminus, C); - } -} - -} // namespace ecc -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/ecc/multprecision.h b/system/gd/security/ecc/multprecision.h deleted file mode 100644 index 7bb3f2de40..0000000000 --- a/system/gd/security/ecc/multprecision.h +++ /dev/null @@ -1,60 +0,0 @@ -/****************************************************************************** - * - * Copyright 2006-2015 Broadcom Corporation - * - * 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. - * - ******************************************************************************/ - -/******************************************************************************* - * - * This file contains simple pairing algorithms - * - ******************************************************************************/ -#pragma once - -#include <cstdint> - -namespace bluetooth { -namespace security { -namespace ecc { - -#define KEY_LENGTH_DWORDS_P256 8 -/* Arithmetic Operations*/ -int multiprecision_compare(const uint32_t* a, const uint32_t* b); -int multiprecision_iszero(const uint32_t* a); -void multiprecision_init(uint32_t* c); -void multiprecision_copy(uint32_t* c, const uint32_t* a); -uint32_t multiprecision_dword_bits(uint32_t a); -uint32_t multiprecision_most_signdwords(const uint32_t* a); -uint32_t multiprecision_most_signbits(const uint32_t* a); -void multiprecision_inv_mod(uint32_t* aminus, uint32_t* a, const uint32_t* modp); -uint32_t multiprecision_add(uint32_t* c, const uint32_t* a, const uint32_t* b); // c=a+b -void multiprecision_add_mod(uint32_t* c, const uint32_t* a, const uint32_t* b, - const uint32_t* modp); -uint32_t multiprecision_sub(uint32_t* c, const uint32_t* a, const uint32_t* b); // c=a-b -void multiprecision_sub_mod(uint32_t* c, const uint32_t* a, const uint32_t* b, - const uint32_t* modp); -void multiprecision_rshift(uint32_t* c, const uint32_t* a); // c=a>>1, return carrier -void multiprecision_lshift_mod(uint32_t* c, const uint32_t* a, - const uint32_t* modp); // c=a<<b, return carrier -uint32_t multiprecision_lshift(uint32_t* c, const uint32_t* a); -void multiprecision_mult(uint32_t* c, const uint32_t* a, const uint32_t* b); // c=a*b -void multiprecision_mersenns_mult_mod(uint32_t* c, const uint32_t* a, const uint32_t* b, - const uint32_t* modp); -void multiprecision_mersenns_squa_mod(uint32_t* c, const uint32_t* a, const uint32_t* modp); -void multiprecision_fast_mod_P256(uint32_t* c, const uint32_t* a, const uint32_t* modp); - -} // namespace ecc -} // namespace security -} // namespace bluetooth
\ No newline at end of file diff --git a/system/gd/security/ecc/p_256_ecc_pp.cc b/system/gd/security/ecc/p_256_ecc_pp.cc deleted file mode 100644 index 3451af7462..0000000000 --- a/system/gd/security/ecc/p_256_ecc_pp.cc +++ /dev/null @@ -1,262 +0,0 @@ -/****************************************************************************** - * - * Copyright 2006-2015 Broadcom Corporation - * - * 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. - * - ******************************************************************************/ - -/******************************************************************************* - * - * This file contains simple pairing algorithms using Elliptic Curve - * Cryptography for private public key - * - ******************************************************************************/ -#include "security/ecc/p_256_ecc_pp.h" - -#include <stdlib.h> -#include <string.h> - -#include "security/ecc/multprecision.h" - -namespace bluetooth { -namespace security { -namespace ecc { - -const uint32_t* modp = curve_p256.p; - -static void p_256_init_point(Point* q) { memset(q, 0, sizeof(Point)); } - -static void p_256_copy_point(Point* q, const Point* p) { memcpy(q, p, sizeof(Point)); } - -// q=2q -static void ECC_Double(Point* q, const Point* p) { - uint32_t t1[KEY_LENGTH_DWORDS_P256]; - uint32_t t2[KEY_LENGTH_DWORDS_P256]; - uint32_t t3[KEY_LENGTH_DWORDS_P256]; - const uint32_t* x1; - uint32_t* x3; - const uint32_t* y1; - uint32_t* y3; - const uint32_t* z1; - uint32_t* z3; - - if (multiprecision_iszero(p->z)) { - multiprecision_init(q->z); - return; // return infinity - } - - x1 = p->x; - y1 = p->y; - z1 = p->z; - x3 = q->x; - y3 = q->y; - z3 = q->z; - - multiprecision_mersenns_squa_mod(t1, z1, modp); // t1=z1^2 - multiprecision_sub_mod(t2, x1, t1, modp); // t2=x1-t1 - multiprecision_add_mod(t1, x1, t1, modp); // t1=x1+t1 - multiprecision_mersenns_mult_mod(t2, t1, t2, modp); // t2=t2*t1 - multiprecision_lshift_mod(t3, t2, modp); - multiprecision_add_mod(t2, t3, t2, modp); // t2=3t2 - - multiprecision_mersenns_mult_mod(z3, y1, z1, modp); // z3=y1*z1 - multiprecision_lshift_mod(z3, z3, modp); - - multiprecision_mersenns_squa_mod(y3, y1, modp); // y3=y1^2 - multiprecision_lshift_mod(y3, y3, modp); - multiprecision_mersenns_mult_mod(t3, y3, x1, modp); // t3=y3*x1=x1*y1^2 - multiprecision_lshift_mod(t3, t3, modp); - multiprecision_mersenns_squa_mod(y3, y3, modp); // y3=y3^2=y1^4 - multiprecision_lshift_mod(y3, y3, modp); - - multiprecision_mersenns_squa_mod(x3, t2, modp); // x3=t2^2 - multiprecision_lshift_mod(t1, t3, modp); // t1=2t3 - multiprecision_sub_mod(x3, x3, t1, modp); // x3=x3-t1 - multiprecision_sub_mod(t1, t3, x3, modp); // t1=t3-x3 - multiprecision_mersenns_mult_mod(t1, t1, t2, modp); // t1=t1*t2 - multiprecision_sub_mod(y3, t1, y3, modp); // y3=t1-y3 -} - -// q=q+p, zp must be 1 -static void ECC_Add(Point* r, Point* p, const Point* q) { - uint32_t t1[KEY_LENGTH_DWORDS_P256]; - uint32_t t2[KEY_LENGTH_DWORDS_P256]; - uint32_t* x1; - const uint32_t* x2; - uint32_t* x3; - uint32_t* y1; - const uint32_t* y2; - uint32_t* y3; - uint32_t* z1; - const uint32_t* z2; - uint32_t* z3; - - x1 = p->x; - y1 = p->y; - z1 = p->z; - x2 = q->x; - y2 = q->y; - z2 = q->z; - x3 = r->x; - y3 = r->y; - z3 = r->z; - - // if Q=infinity, return p - if (multiprecision_iszero(z2)) { - p_256_copy_point(r, p); - return; - } - - // if P=infinity, return q - if (multiprecision_iszero(z1)) { - p_256_copy_point(r, q); - return; - } - - multiprecision_mersenns_squa_mod(t1, z1, modp); // t1=z1^2 - multiprecision_mersenns_mult_mod(t2, z1, t1, modp); // t2=t1*z1 - multiprecision_mersenns_mult_mod(t1, x2, t1, modp); // t1=t1*x2 - multiprecision_mersenns_mult_mod(t2, y2, t2, modp); // t2=t2*y2 - - multiprecision_sub_mod(t1, t1, x1, modp); // t1=t1-x1 - multiprecision_sub_mod(t2, t2, y1, modp); // t2=t2-y1 - - if (multiprecision_iszero(t1)) { - if (multiprecision_iszero(t2)) { - ECC_Double(r, q); - return; - } else { - multiprecision_init(z3); - return; // return infinity - } - } - - multiprecision_mersenns_mult_mod(z3, z1, t1, modp); // z3=z1*t1 - multiprecision_mersenns_squa_mod(y3, t1, modp); // t3=t1^2 - multiprecision_mersenns_mult_mod(z1, y3, t1, modp); // t4=t3*t1 - multiprecision_mersenns_mult_mod(y3, y3, x1, modp); // t3=t3*x1 - multiprecision_lshift_mod(t1, y3, modp); // t1=2*t3 - multiprecision_mersenns_squa_mod(x3, t2, modp); // x3=t2^2 - multiprecision_sub_mod(x3, x3, t1, modp); // x3=x3-t1 - multiprecision_sub_mod(x3, x3, z1, modp); // x3=x3-t4 - multiprecision_sub_mod(y3, y3, x3, modp); // t3=t3-x3 - multiprecision_mersenns_mult_mod(y3, y3, t2, modp); // t3=t3*t2 - multiprecision_mersenns_mult_mod(z1, z1, y1, modp); // t4=t4*t1 - multiprecision_sub_mod(y3, y3, z1, modp); -} - -// Computing the Non-Adjacent Form of a positive integer -static void ECC_NAF(uint8_t* naf, uint32_t* NumNAF, uint32_t* k) { - uint32_t sign; - int i = 0; - int j; - uint32_t var; - - while ((var = multiprecision_most_signbits(k)) >= 1) { - if (k[0] & 0x01) // k is odd - { - sign = (k[0] & 0x03); // 1 or 3 - - // k = k-naf[i] - if (sign == 1) { - k[0] = k[0] & 0xFFFFFFFE; - } else { - k[0] = k[0] + 1; - if (k[0] == 0) // overflow - { - j = 1; - do { - k[j]++; - } while (k[j++] == 0); // overflow - } - } - } else { - sign = 0; - } - - multiprecision_rshift(k, k); - naf[i / 4] |= (sign) << ((i % 4) * 2); - i++; - } - - *NumNAF = i; -} - -// Binary Non-Adjacent Form for point multiplication -void ECC_PointMult_Bin_NAF(Point* q, const Point* p, uint32_t* n) { - uint32_t sign; - uint8_t naf[256 / 4 + 1]; - uint32_t NumNaf; - Point minus_p; - Point r; - - p_256_init_point(&r); - - // initialization - p_256_init_point(q); - - // -p - multiprecision_copy(minus_p.x, p->x); - multiprecision_sub(minus_p.y, modp, p->y); - - multiprecision_init(minus_p.z); - minus_p.z[0] = 1; - - // NAF - memset(naf, 0, sizeof(naf)); - ECC_NAF(naf, &NumNaf, n); - - for (int i = NumNaf - 1; i >= 0; i--) { - p_256_copy_point(&r, q); - ECC_Double(q, &r); - sign = (naf[i / 4] >> ((i % 4) * 2)) & 0x03; - - if (sign == 1) { - p_256_copy_point(&r, q); - ECC_Add(q, &r, p); - } else if (sign == 3) { - p_256_copy_point(&r, q); - ECC_Add(q, &r, &minus_p); - } - } - - multiprecision_inv_mod(minus_p.x, q->z, modp); - multiprecision_mersenns_squa_mod(q->z, minus_p.x, modp); - multiprecision_mersenns_mult_mod(q->x, q->x, q->z, modp); - multiprecision_mersenns_mult_mod(q->z, q->z, minus_p.x, modp); - multiprecision_mersenns_mult_mod(q->y, q->y, q->z, modp); -} - -bool ECC_ValidatePoint(const Point& pt) { - // Ensure y^2 = x^3 + a*x + b (mod p); a = -3 - - // y^2 mod p - uint32_t y2_mod[KEY_LENGTH_DWORDS_P256] = {0}; - multiprecision_mersenns_squa_mod(y2_mod, (uint32_t*)pt.y, modp); - - // Right hand side calculation - uint32_t rhs[KEY_LENGTH_DWORDS_P256] = {0}; - multiprecision_mersenns_squa_mod(rhs, (uint32_t*)pt.x, modp); - uint32_t three[KEY_LENGTH_DWORDS_P256] = {0}; - three[0] = 3; - multiprecision_sub_mod(rhs, rhs, three, modp); - multiprecision_mersenns_mult_mod(rhs, rhs, (uint32_t*)pt.x, modp); - multiprecision_add_mod(rhs, rhs, curve_p256.b, modp); - - return multiprecision_compare(rhs, y2_mod) == 0; -} - -} // namespace ecc -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/ecc/p_256_ecc_pp.h b/system/gd/security/ecc/p_256_ecc_pp.h deleted file mode 100644 index 2303bfb62e..0000000000 --- a/system/gd/security/ecc/p_256_ecc_pp.h +++ /dev/null @@ -1,80 +0,0 @@ -/****************************************************************************** - * - * Copyright 2006-2015 Broadcom Corporation - * - * 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. - * - ******************************************************************************/ - -/****************************************************************************** - * - * This file contains simple pairing algorithms using Elliptic Curve - *Cryptography for private public key - * - ******************************************************************************/ - -#pragma once - -#include "security/ecc/multprecision.h" - -namespace bluetooth { -namespace security { -namespace ecc { - -struct Point { - uint32_t x[KEY_LENGTH_DWORDS_P256]; - uint32_t y[KEY_LENGTH_DWORDS_P256]; - uint32_t z[KEY_LENGTH_DWORDS_P256]; -}; - -struct elliptic_curve_t { - // curve's coefficients - uint32_t a[KEY_LENGTH_DWORDS_P256]; - uint32_t b[KEY_LENGTH_DWORDS_P256]; - - // prime modulus - uint32_t p[KEY_LENGTH_DWORDS_P256]; - - // Omega, p = 2^m -omega - uint32_t omega[KEY_LENGTH_DWORDS_P256]; - - // base point, a point on E of order r - Point G; -}; - -// P-256 elliptic curve, as per BT Spec 5.1 Vol 2, Part H 7.6 -static constexpr elliptic_curve_t curve_p256{ - .a = {0}, - .b = {0x27d2604b, 0x3bce3c3e, 0xcc53b0f6, 0x651d06b0, 0x769886bc, 0xb3ebbd55, 0xaa3a93e7, - 0x5ac635d8}, - .p = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x00000001, 0xFFFFFFFF}, - .omega = {0}, - - .G = {.x = {0xd898c296, 0xf4a13945, 0x2deb33a0, 0x77037d81, 0x63a440f2, 0xf8bce6e5, - 0xe12c4247, 0x6b17d1f2}, - .y = {0x37bf51f5, 0xcbb64068, 0x6b315ece, 0x2bce3357, 0x7c0f9e16, 0x8ee7eb4a, - 0xfe1a7f9b, 0x4fe342e2}, - .z = {0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000}}, -}; - -/* This function checks that point is on the elliptic curve*/ -bool ECC_ValidatePoint(const Point& point); - -void ECC_PointMult_Bin_NAF(Point* q, const Point* p, uint32_t* n); - -#define ECC_PointMult(q, p, n) ECC_PointMult_Bin_NAF(q, p, n) - -} // namespace ecc -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/ecdh_keys.cc b/system/gd/security/ecdh_keys.cc deleted file mode 100644 index a54e3e7bff..0000000000 --- a/system/gd/security/ecdh_keys.cc +++ /dev/null @@ -1,99 +0,0 @@ -/****************************************************************************** - * - * Copyright 2019 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 "security/ecdh_keys.h" - -/********************************************************************************************************************** - TODO: We should have random number management in separate file, and we - should honour all the random number requirements from the spec!! -**********************************************************************************************************************/ -#include <string.h> - -#include <cstdlib> -#include <ctime> - -#include "security/ecc/p_256_ecc_pp.h" - -namespace { - -static bool srand_initiated = false; - -template <size_t SIZE> -static std::array<uint8_t, SIZE> GenerateRandom() { - if (!srand_initiated) { - srand_initiated = true; - // TODO: We need a proper random number generator here. - // use current time as seed for random generator - std::srand(std::time(nullptr)); - } - - std::array<uint8_t, SIZE> r; - for (size_t i = 0; i < SIZE; i++) { - r[i] = std::rand(); - } - return r; -} -} // namespace -/*********************************************************************************************************************/ - -namespace bluetooth { -namespace security { - -std::pair<std::array<uint8_t, 32>, EcdhPublicKey> GenerateECDHKeyPair() { - std::array<uint8_t, 32> private_key = GenerateRandom<32>(); - std::array<uint8_t, 32> private_key_copy = private_key; - ecc::Point public_key; - - ECC_PointMult(&public_key, &(ecc::curve_p256.G), (uint32_t*)private_key_copy.data()); - - EcdhPublicKey pk; - memcpy(pk.x.data(), public_key.x, 32); - memcpy(pk.y.data(), public_key.y, 32); - - /* private_key, public key pair */ - return std::make_pair<std::array<uint8_t, 32>, EcdhPublicKey>(std::move(private_key), - std::move(pk)); -} - -bool ValidateECDHPoint(EcdhPublicKey pk) { - ecc::Point public_key; - memcpy(public_key.x, pk.x.data(), 32); - memcpy(public_key.y, pk.y.data(), 32); - memset(public_key.z, 0, 32); - return ECC_ValidatePoint(public_key); -} - -std::array<uint8_t, 32> ComputeDHKey(std::array<uint8_t, 32> my_private_key, - EcdhPublicKey remote_public_key) { - ecc::Point peer_publ_key, new_publ_key; - uint32_t private_key[8]; - memcpy(private_key, my_private_key.data(), 32); - memcpy(peer_publ_key.x, remote_public_key.x.data(), 32); - memcpy(peer_publ_key.y, remote_public_key.y.data(), 32); - memset(peer_publ_key.z, 0, 32); - peer_publ_key.z[0] = 1; - - ECC_PointMult(&new_publ_key, &peer_publ_key, (uint32_t*)private_key); - - std::array<uint8_t, 32> dhkey; - memcpy(dhkey.data(), new_publ_key.x, 32); - return dhkey; -} - -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/ecdh_keys.h b/system/gd/security/ecdh_keys.h deleted file mode 100644 index 64ef63be0e..0000000000 --- a/system/gd/security/ecdh_keys.h +++ /dev/null @@ -1,43 +0,0 @@ -/****************************************************************************** - * - * Copyright 2019 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. - * - ******************************************************************************/ -#pragma once - -#include <stdint.h> - -#include <array> - -namespace bluetooth { -namespace security { - -struct EcdhPublicKey { - std::array<uint8_t, 32> x; - std::array<uint8_t, 32> y; -}; - -/* this generates private and public Eliptic Curve Diffie Helman keys */ -std::pair<std::array<uint8_t, 32>, EcdhPublicKey> GenerateECDHKeyPair(); - -/* This function validates that the given public key (point) lays on the special - * Bluetooth curve */ -bool ValidateECDHPoint(EcdhPublicKey pk); - -std::array<uint8_t, 32> ComputeDHKey(std::array<uint8_t, 32> my_private_key, - EcdhPublicKey remote_public_key); - -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/facade_configuration_api.cc b/system/gd/security/facade_configuration_api.cc deleted file mode 100644 index f9ea395a33..0000000000 --- a/system/gd/security/facade_configuration_api.cc +++ /dev/null @@ -1,88 +0,0 @@ -/* - * - * Copyright 2019 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 "facade_configuration_api.h" - -#include "common/bind.h" -#include "l2cap/classic/security_enforcement_interface.h" -#include "os/log.h" - -namespace bluetooth { -namespace security { - -void FacadeConfigurationApi::SetDisconnectCallback( - internal::SecurityManagerImpl::FacadeDisconnectCallback callback) { - security_handler_->CallOn(security_manager_impl_, - &internal::SecurityManagerImpl::SetDisconnectCallback, callback); -} - -void FacadeConfigurationApi::SetIoCapability(hci::IoCapability io_capability) { - security_handler_->CallOn(security_manager_impl_, &internal::SecurityManagerImpl::SetIoCapability, - io_capability); -} - -void FacadeConfigurationApi::SetAuthenticationRequirements( - hci::AuthenticationRequirements authentication_requirement) { - security_handler_->CallOn(security_manager_impl_, - &internal::SecurityManagerImpl::SetAuthenticationRequirements, - authentication_requirement); -} - -void FacadeConfigurationApi::SetLeIoCapability(security::IoCapability io_capability) { - security_handler_->CallOn(security_manager_impl_, - &internal::SecurityManagerImpl::SetLeIoCapability, io_capability); -} - -void FacadeConfigurationApi::SetLeAuthRequirements(uint8_t auth_req) { - security_handler_->CallOn(security_manager_impl_, - &internal::SecurityManagerImpl::SetLeAuthRequirements, auth_req); -} - -void FacadeConfigurationApi::SetLeMaximumEncryptionKeySize(uint8_t maximum_encryption_key_size) { - security_handler_->CallOn(security_manager_impl_, - &internal::SecurityManagerImpl::SetLeMaximumEncryptionKeySize, - maximum_encryption_key_size); -} - -void FacadeConfigurationApi::SetLeOobDataPresent(OobDataFlag oob_present) { - security_handler_->CallOn(security_manager_impl_, - &internal::SecurityManagerImpl::SetLeOobDataPresent, oob_present); -} - -void FacadeConfigurationApi::GetLeOutOfBandData(std::array<uint8_t, 16>* confirmation_value, - std::array<uint8_t, 16>* random_value) { - security_manager_impl_->GetLeOutOfBandData(confirmation_value, random_value); -} - -void FacadeConfigurationApi::SetOutOfBandData(hci::AddressWithType remote_address, - std::array<uint8_t, 16> confirmation_value, - std::array<uint8_t, 16> random_value) { - security_handler_->CallOn(security_manager_impl_, - &internal::SecurityManagerImpl::SetOutOfBandData, remote_address, - confirmation_value, random_value); -} - -void FacadeConfigurationApi::EnforceSecurityPolicy( - hci::AddressWithType remote, l2cap::classic::SecurityPolicy policy, - l2cap::classic::SecurityEnforcementInterface::ResultCallback callback) { - security_handler_->CallOn(security_manager_impl_, - &internal::SecurityManagerImpl::EnforceSecurityPolicy, remote, policy, - std::move(callback)); -} - -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/facade_configuration_api.h b/system/gd/security/facade_configuration_api.h deleted file mode 100644 index b3da40557f..0000000000 --- a/system/gd/security/facade_configuration_api.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * - * Copyright 2020 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. - * - */ - -#pragma once - -#include "hci/address_with_type.h" -#include "hci/hci_packets.h" -#include "security/internal/security_manager_impl.h" -#include "security/smp_packets.h" - -namespace bluetooth { -namespace security { - -/** - * Manages the security attributes, pairing, bonding of devices, and the - * encryption/decryption of communications. - */ -class FacadeConfigurationApi { -public: - FacadeConfigurationApi(const FacadeConfigurationApi&) = delete; - FacadeConfigurationApi& operator=(const FacadeConfigurationApi&) = delete; - - friend class internal::SecurityManagerImpl; - friend class SecurityModule; - - void SetDisconnectCallback(internal::SecurityManagerImpl::FacadeDisconnectCallback callback); - void SetIoCapability(hci::IoCapability io_capability); - void SetAuthenticationRequirements(hci::AuthenticationRequirements authentication_requirement); - void EnforceSecurityPolicy(hci::AddressWithType remote, l2cap::classic::SecurityPolicy policy, - l2cap::classic::SecurityEnforcementInterface::ResultCallback callback); - - void SetLeIoCapability(security::IoCapability io_capability); - void SetLeAuthRequirements(uint8_t auth_req); - void SetLeMaximumEncryptionKeySize(uint8_t maximum_encryption_key_size); - void SetLeOobDataPresent(OobDataFlag oob_present); - void GetLeOutOfBandData(std::array<uint8_t, 16>* confirmation_value, - std::array<uint8_t, 16>* random_value); - void SetOutOfBandData(hci::AddressWithType remote_address, - std::array<uint8_t, 16> confirmation_value, - std::array<uint8_t, 16> random_value); - -protected: - FacadeConfigurationApi(os::Handler* security_handler, - internal::SecurityManagerImpl* security_manager_impl) - : security_handler_(security_handler), security_manager_impl_(security_manager_impl) {} - -private: - os::Handler* security_handler_ = nullptr; - internal::SecurityManagerImpl* security_manager_impl_; -}; - -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/initial_informations.h b/system/gd/security/initial_informations.h deleted file mode 100644 index 46c2af559b..0000000000 --- a/system/gd/security/initial_informations.h +++ /dev/null @@ -1,127 +0,0 @@ -/****************************************************************************** - * - * Copyright 2019 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. - * - ******************************************************************************/ - -#pragma once - -#include <optional> -#include <variant> - -#include "hci/address_with_type.h" -#include "hci/le_security_interface.h" -#include "os/handler.h" -#include "os/queue.h" -#include "security/ecdh_keys.h" -#include "security/pairing_failure.h" -#include "security/smp_packets.h" -#include "security/ui.h" - -namespace bluetooth { -namespace security { - -struct DistributedKeys { - /* LE Keys*/ - std::optional<hci::Octet16> remote_ltk; - std::optional<uint16_t> remote_ediv; - std::optional<std::array<uint8_t, 8>> remote_rand; - std::optional<hci::AddressWithType> remote_identity_address; - std::optional<hci::Octet16> remote_irk; - std::optional<hci::Octet16> remote_signature_key; - std::optional<hci::Octet16> remote_link_key; /* BR/EDR Keys */ - - std::optional<hci::Octet16> local_ltk; - std::optional<uint16_t> local_ediv; - std::optional<std::array<uint8_t, 8>> local_rand; - std::optional<hci::Octet16> local_signature_key; -}; - -/* This class represents the result of pairing, as returned from Pairing Handler */ -struct PairingResult { - hci::AddressWithType connection_address; - DistributedKeys distributed_keys; - uint8_t key_size; - uint8_t security_level; -}; - -using PairingResultOrFailure = std::variant<PairingResult, PairingFailure>; - -/* Data we use for Out Of Band Pairing */ -struct MyOobData { - /* private key is just for this single pairing only, so it might be safe to - * expose it to other parts of stack. It should not be exposed to upper - * layers though */ - std::array<uint8_t, 32> private_key; - EcdhPublicKey public_key; - hci::Octet16 c; - hci::Octet16 r; -}; - -/* This structure is filled and send to PairingHandlerLe to initiate the Pairing process with remote - * device */ -struct InitialInformations { - hci::Role my_role; - hci::AddressWithType my_connection_address; - - hci::AddressWithType my_identity_address; - hci::Octet16 my_identity_resolving_key; - - /* My capabilities, as in pairing request/response */ - struct { - IoCapability io_capability; - OobDataFlag oob_data_flag; - uint8_t auth_req; - uint8_t maximum_encryption_key_size; - uint8_t initiator_key_distribution; - uint8_t responder_key_distribution; - } myPairingCapabilities; - - /* was it remote device that initiated the Pairing ? */ - bool remotely_initiated; - uint16_t connection_handle; - hci::AddressWithType remote_connection_address; - std::string remote_name; - - /* contains pairing request, if the pairing was remotely initiated */ - std::optional<PairingRequestView> pairing_request; - - struct out_of_band_data { - hci::Octet16 le_sc_c; /* LE Secure Connections Confirmation Value */ - hci::Octet16 le_sc_r; /* LE Secure Connections Random Value */ - - hci::Octet16 security_manager_tk_value; /* OOB data for LE Legacy Pairing */ - }; - - // If we received OOB data from remote device, this field contains it. - std::optional<out_of_band_data> remote_oob_data; - std::optional<MyOobData> my_oob_data; - - /* Used by Pairing Handler to present user with requests*/ - UI* user_interface; - os::Handler* user_interface_handler; - - /* HCI interface to use */ - hci::LeSecurityInterface* le_security_interface; - - os::EnqueueBuffer<packet::BasePacketBuilder>* proper_l2cap_interface; - os::Handler* l2cap_handler; - - /* Callback to execute once the Pairing process is finished */ - std::function<void(PairingResultOrFailure)> OnPairingFinished; -}; - -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/internal/security_manager_impl.cc b/system/gd/security/internal/security_manager_impl.cc deleted file mode 100644 index 4a90031e12..0000000000 --- a/system/gd/security/internal/security_manager_impl.cc +++ /dev/null @@ -1,930 +0,0 @@ -/* - * - * Copyright 2019 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 "security_manager_impl.h" - -#include <android_bluetooth_sysprop.h> -#include <bluetooth/log.h> - -#include "common/bind.h" -#include "hci/address_with_type.h" -#include "hci/octets.h" -#include "os/log.h" -#include "os/rand.h" -#include "security/initial_informations.h" -#include "security/internal/security_manager_impl.h" -#include "security/pairing_handler_le.h" -#include "security/security_manager_listener.h" -#include "security/ui.h" -#include "storage/config_keys.h" - -namespace bluetooth { -namespace security { -namespace internal { - -void SecurityManagerImpl::DispatchPairingHandler(std::shared_ptr<record::SecurityRecord> record, - bool locally_initiated, - hci::IoCapability io_capability, - hci::AuthenticationRequirements auth_requirements, - pairing::OobData remote_p192_oob_data, - pairing::OobData remote_p256_oob_data) { - common::OnceCallback<void(hci::Address, PairingResultOrFailure)> callback = common::BindOnce( - &SecurityManagerImpl::OnPairingHandlerComplete, common::Unretained(this)); - auto entry = pairing_handler_map_.find(record->GetPseudoAddress()->GetAddress()); - if (entry != pairing_handler_map_.end()) { - log::warn("Device already has a pairing handler, and is in the middle of pairing!"); - return; - } - std::shared_ptr<pairing::PairingHandler> pairing_handler = nullptr; - switch (record->GetPseudoAddress()->GetAddressType()) { - case hci::AddressType::PUBLIC_DEVICE_ADDRESS: { - pairing_handler = std::make_shared<security::pairing::ClassicPairingHandler>( - security_manager_channel_, record, security_handler_, std::move(callback), - user_interface_, user_interface_handler_, record->GetPseudoAddress()->ToString(), - name_db_module_); - break; - } - default: - log::fatal("Pairing type {} not implemented!", - (uint8_t)record->GetPseudoAddress()->GetAddressType()); - } - auto new_entry = std::pair<hci::Address, std::shared_ptr<pairing::PairingHandler>>( - record->GetPseudoAddress()->GetAddress(), pairing_handler); - pairing_handler_map_.insert(std::move(new_entry)); - pairing_handler->Initiate(locally_initiated, io_capability, auth_requirements, - remote_p192_oob_data, remote_p256_oob_data); -} - -void SecurityManagerImpl::Init() { - security_manager_channel_->SetChannelListener(this); - security_manager_channel_->SendCommand( - hci::WriteSimplePairingModeBuilder::Create(hci::Enable::ENABLED)); - security_manager_channel_->SendCommand( - hci::WriteSecureConnectionsHostSupportBuilder::Create(hci::Enable::ENABLED)); - - log::assert_that(storage_module_ != nullptr, "Storage module must not be null!"); - security_database_.LoadRecordsFromStorage(); - - auto irk_prop = - storage_module_->GetBin(BTIF_STORAGE_SECTION_ADAPTER, BTIF_STORAGE_KEY_LE_LOCAL_KEY_IRK); - if (!irk_prop.has_value()) { - auto rand16 = bluetooth::os::GenerateRandom<16>(); - std::vector<uint8_t> new_irk{rand16.begin(), rand16.end()}; - storage_module_->SetBin(BTIF_STORAGE_SECTION_ADAPTER, BTIF_STORAGE_KEY_LE_LOCAL_KEY_IRK, - new_irk); - irk_prop = storage_module_->GetBin(BTIF_STORAGE_SECTION_ADAPTER, - BTIF_STORAGE_KEY_LE_LOCAL_KEY_IRK); - } - - Address controllerAddress = controller_->GetMacAddress(); - auto address_prop = - storage_module_->GetProperty(BTIF_STORAGE_SECTION_ADAPTER, BTIF_STORAGE_KEY_ADDRESS); - if (!address_prop || address_prop.value() != controllerAddress.ToString()) { - storage_module_->SetProperty(BTIF_STORAGE_SECTION_ADAPTER, BTIF_STORAGE_KEY_ADDRESS, - controllerAddress.ToString()); - } - - local_identity_address_ = - hci::AddressWithType(controllerAddress, hci::AddressType::PUBLIC_DEVICE_ADDRESS); - irk_prop = - storage_module_->GetBin(BTIF_STORAGE_SECTION_ADAPTER, BTIF_STORAGE_KEY_LE_LOCAL_KEY_IRK); - log::assert_that(irk_prop.has_value(), "Irk not found in storage"); - log::assert_that(irk_prop->size() == 16, "Irk corrupted in storage"); - std::copy(irk_prop->begin(), irk_prop->end(), local_identity_resolving_key_.data()); - - hci::LeAddressManager::AddressPolicy address_policy = - hci::LeAddressManager::AddressPolicy::USE_RESOLVABLE_ADDRESS; - hci::AddressWithType address_with_type(hci::Address{}, hci::AddressType::RANDOM_DEVICE_ADDRESS); - - /* Default to 7 minutes minimum, 15 minutes maximum for random address refreshing; - * device can override. */ - auto minimum_rotation_time = std::chrono::minutes( - android::sysprop::bluetooth::Ble::random_address_rotation_interval_min().value_or(7)); - auto maximum_rotation_time = std::chrono::minutes( - android::sysprop::bluetooth::Ble::random_address_rotation_interval_max().value_or(15)); - - acl_manager_->SetPrivacyPolicyForInitiatorAddress(address_policy, address_with_type, - minimum_rotation_time, maximum_rotation_time); -} - -void SecurityManagerImpl::CreateBond(hci::AddressWithType device) { - this->CreateBondOutOfBand(device, pairing::OobData(), pairing::OobData()); -} - -void SecurityManagerImpl::CreateBondOutOfBand(hci::AddressWithType device, - pairing::OobData remote_p192_oob_data, - pairing::OobData remote_p256_oob_data) { - auto record = security_database_.FindOrCreate(device); - if (record->IsPaired()) { - // Bonded means we saved it, but the caller doesn't care - // Bonded will always mean paired - NotifyDeviceBonded(device); - } else { - if (!record->IsPairing()) { - // Dispatch pairing handler, if we are calling create we are the initiator - log::warn("Dispatch #1"); - DispatchPairingHandler(record, true, this->local_io_capability_, - this->local_authentication_requirements_, remote_p192_oob_data, - remote_p256_oob_data); - } - } -} - -void SecurityManagerImpl::CreateBondLe(hci::AddressWithType address) { - auto record = security_database_.FindOrCreate(address); - if (record->IsPaired()) { - NotifyDeviceBondFailed(address, PairingFailure("Already bonded")); - return; - } - - pending_le_pairing_.address_ = address; - - LeFixedChannelEntry* stored_chan = FindStoredLeChannel(address); - if (stored_chan) { - // We are already connected - ConnectionIsReadyStartPairing(stored_chan); - return; - } - - l2cap_manager_le_->ConnectServices( - address, - common::BindOnce(&SecurityManagerImpl::OnConnectionFailureLe, common::Unretained(this)), - security_handler_); -} - -void SecurityManagerImpl::CancelBond(hci::AddressWithType device) { - auto entry = pairing_handler_map_.find(device.GetAddress()); - if (entry != pairing_handler_map_.end()) { - auto cancel_me = entry->second; - pairing_handler_map_.erase(entry); - cancel_me->Cancel(); - } - - auto record = security_database_.FindOrCreate(device); - record->CancelPairing(); - - WipeLePairingHandler(); -} - -void SecurityManagerImpl::RemoveBond(hci::AddressWithType device) { - CancelBond(device); - security_manager_channel_->Disconnect(device.GetAddress()); - security_database_.Remove(device); - security_manager_channel_->SendCommand(hci::DeleteStoredLinkKeyBuilder::Create( - device.GetAddress(), hci::DeleteStoredLinkKeyDeleteAllFlag::SPECIFIED_BD_ADDR)); - NotifyDeviceUnbonded(device); -} - -void SecurityManagerImpl::SetUserInterfaceHandler(UI* user_interface, os::Handler* handler) { - if (user_interface_ != nullptr || user_interface_handler_ != nullptr) { - log::fatal("Listener has already been registered!"); - } - user_interface_ = user_interface; - user_interface_handler_ = handler; -} - -// TODO(jpawlowski): remove once we have config file abstraction in cert tests -void SecurityManagerImpl::SetLeInitiatorAddressPolicyForTest( - hci::LeAddressManager::AddressPolicy address_policy, hci::AddressWithType fixed_address, - hci::Octet16 rotation_irk, std::chrono::milliseconds minimum_rotation_time, - std::chrono::milliseconds maximum_rotation_time) { - acl_manager_->SetPrivacyPolicyForInitiatorAddressForTest(address_policy, fixed_address, - rotation_irk, minimum_rotation_time, - maximum_rotation_time); -} - -void SecurityManagerImpl::RegisterCallbackListener(ISecurityManagerListener* listener, - os::Handler* handler) { - for (auto it = listeners_.begin(); it != listeners_.end(); ++it) { - if (it->first == listener) { - log::fatal("Listener has already been registered!"); - } - } - - listeners_.push_back({listener, handler}); -} - -void SecurityManagerImpl::UnregisterCallbackListener(ISecurityManagerListener* listener) { - for (auto it = listeners_.begin(); it != listeners_.end(); ++it) { - if (it->first == listener) { - listeners_.erase(it); - return; - } - } - - log::fatal("Listener has not been registered!"); -} - -void SecurityManagerImpl::NotifyDeviceBonded(hci::AddressWithType device) { - for (auto& iter : listeners_) { - iter.second->Post(common::Bind(&ISecurityManagerListener::OnDeviceBonded, - common::Unretained(iter.first), device)); - } -} - -void SecurityManagerImpl::NotifyDeviceBondFailed(hci::AddressWithType device, - PairingFailure status) { - for (auto& iter : listeners_) { - iter.second->Post(common::Bind(&ISecurityManagerListener::OnDeviceBondFailed, - common::Unretained(iter.first), device, status)); - } -} - -void SecurityManagerImpl::NotifyDeviceUnbonded(hci::AddressWithType device) { - for (auto& iter : listeners_) { - iter.second->Post(common::Bind(&ISecurityManagerListener::OnDeviceUnbonded, - common::Unretained(iter.first), device)); - } - acl_manager_->CancelLeConnect(device); -} - -void SecurityManagerImpl::NotifyEncryptionStateChanged( - hci::EncryptionChangeView encryption_change_view) { - for (auto& iter : listeners_) { - iter.second->Post(common::Bind(&ISecurityManagerListener::OnEncryptionStateChanged, - common::Unretained(iter.first), encryption_change_view)); - } -} - -template <class T> -void SecurityManagerImpl::HandleEvent(T packet) { - log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()"); - auto entry = pairing_handler_map_.find(packet.GetBdAddr()); - - if (entry == pairing_handler_map_.end()) { - auto bd_addr = packet.GetBdAddr(); - auto event_code = packet.GetEventCode(); - - if (event_code != hci::EventCode::LINK_KEY_REQUEST && - event_code != hci::EventCode::PIN_CODE_REQUEST && - event_code != hci::EventCode::IO_CAPABILITY_RESPONSE) { - log::error("No classic pairing handler for device '{}' ready for command {}", bd_addr, - hci::EventCodeText(event_code)); - return; - } - - auto device = storage_module_->GetDeviceByClassicMacAddress(bd_addr); - - auto record = security_database_.FindOrCreate( - hci::AddressWithType{bd_addr, hci::AddressType::PUBLIC_DEVICE_ADDRESS}); - log::warn("Dispatch #2"); - DispatchPairingHandler(record, false, this->local_io_capability_, - this->local_authentication_requirements_, pairing::OobData(), - pairing::OobData()); - entry = pairing_handler_map_.find(bd_addr); - } - entry->second->OnReceive(packet); -} - -void SecurityManagerImpl::OnHciEventReceived(hci::EventView packet) { - auto event = hci::EventView::Create(packet); - log::assert_that(event.IsValid(), "Received invalid packet"); - const hci::EventCode code = event.GetEventCode(); - switch (code) { - case hci::EventCode::PIN_CODE_REQUEST: - HandleEvent<hci::PinCodeRequestView>(hci::PinCodeRequestView::Create(event)); - break; - case hci::EventCode::LINK_KEY_REQUEST: - HandleEvent(hci::LinkKeyRequestView::Create(event)); - break; - case hci::EventCode::LINK_KEY_NOTIFICATION: - HandleEvent(hci::LinkKeyNotificationView::Create(event)); - break; - case hci::EventCode::IO_CAPABILITY_REQUEST: - HandleEvent(hci::IoCapabilityRequestView::Create(event)); - break; - case hci::EventCode::IO_CAPABILITY_RESPONSE: - HandleEvent(hci::IoCapabilityResponseView::Create(event)); - break; - case hci::EventCode::SIMPLE_PAIRING_COMPLETE: - HandleEvent(hci::SimplePairingCompleteView::Create(event)); - break; - case hci::EventCode::REMOTE_OOB_DATA_REQUEST: - HandleEvent(hci::RemoteOobDataRequestView::Create(event)); - break; - case hci::EventCode::USER_PASSKEY_NOTIFICATION: - HandleEvent(hci::UserPasskeyNotificationView::Create(event)); - break; - case hci::EventCode::KEYPRESS_NOTIFICATION: - HandleEvent(hci::KeypressNotificationView::Create(event)); - break; - case hci::EventCode::USER_CONFIRMATION_REQUEST: - HandleEvent(hci::UserConfirmationRequestView::Create(event)); - break; - case hci::EventCode::USER_PASSKEY_REQUEST: - HandleEvent(hci::UserPasskeyRequestView::Create(event)); - break; - - case hci::EventCode::ENCRYPTION_CHANGE: { - EncryptionChangeView encryption_change_view = EncryptionChangeView::Create(event); - if (!encryption_change_view.IsValid()) { - log::error("Invalid EncryptionChange packet received"); - return; - } - if (encryption_change_view.GetConnectionHandle() == pending_le_pairing_.connection_handle_) { - pending_le_pairing_.handler_->OnHciEvent(event); - return; - } - NotifyEncryptionStateChanged(encryption_change_view); - break; - } - - default: - log::fatal("Cannot handle received packet: {}", hci::EventCodeText(code)); - break; - } -} - -void SecurityManagerImpl::OnConnectionClosed(hci::Address address) { - auto entry = pairing_handler_map_.find(address); - if (entry != pairing_handler_map_.end()) { - log::info("Cancelling pairing handler for '{}'", address); - entry->second->Cancel(); - } - auto record = security_database_.FindOrCreate( - hci::AddressWithType(address, hci::AddressType::PUBLIC_DEVICE_ADDRESS)); - if (record->IsTemporary()) { - security_database_.Remove( - hci::AddressWithType(address, hci::AddressType::PUBLIC_DEVICE_ADDRESS)); - } - if (this->facade_disconnect_callback_) { - this->security_handler_->Call( - *this->facade_disconnect_callback_, - hci::AddressWithType(address, hci::AddressType::PUBLIC_DEVICE_ADDRESS)); - } -} - -void SecurityManagerImpl::OnHciLeEvent(hci::LeMetaEventView event) { - hci::SubeventCode code = event.GetSubeventCode(); - - if (code == hci::SubeventCode::LONG_TERM_KEY_REQUEST) { - hci::LeLongTermKeyRequestView le_long_term_key_request_view = - hci::LeLongTermKeyRequestView::Create(event); - if (!le_long_term_key_request_view.IsValid()) { - log::error("Invalid LeLongTermKeyRequestView packet received"); - return; - } - - if (le_long_term_key_request_view.GetConnectionHandle() == - pending_le_pairing_.connection_handle_) { - pending_le_pairing_.handler_->OnHciLeEvent(event); - return; - } - - log::info("Unhandled HCI LE security event, code {}", hci::SubeventCodeText(code)); - return; - } - - // hci::SubeventCode::READ_LOCAL_P256_PUBLIC_KEY_COMPLETE, - // hci::SubeventCode::GENERATE_DHKEY_COMPLETE, - log::error("Unhandled HCI LE security event, code {}", hci::SubeventCodeText(code)); -} - -void SecurityManagerImpl::OnPairingPromptAccepted(const bluetooth::hci::AddressWithType& address, - bool confirmed) { - auto entry = pairing_handler_map_.find(address.GetAddress()); - if (entry != pairing_handler_map_.end()) { - entry->second->OnPairingPromptAccepted(address, confirmed); - } else { - if (pending_le_pairing_.address_ == address) { - pending_le_pairing_.handler_->OnUiAction(PairingEvent::UI_ACTION_TYPE::PAIRING_ACCEPTED, - confirmed); - } - } -} - -void SecurityManagerImpl::OnConfirmYesNo(const bluetooth::hci::AddressWithType& address, - bool confirmed) { - auto entry = pairing_handler_map_.find(address.GetAddress()); - if (entry != pairing_handler_map_.end()) { - entry->second->OnConfirmYesNo(address, confirmed); - } else { - if (pending_le_pairing_.address_ == address) { - pending_le_pairing_.handler_->OnUiAction(PairingEvent::UI_ACTION_TYPE::CONFIRM_YESNO, - confirmed); - } - } -} - -void SecurityManagerImpl::OnPasskeyEntry(const bluetooth::hci::AddressWithType& address, - uint32_t passkey) { - auto entry = pairing_handler_map_.find(address.GetAddress()); - if (entry != pairing_handler_map_.end()) { - entry->second->OnPasskeyEntry(address, passkey); - } else { - if (pending_le_pairing_.address_ == address) { - pending_le_pairing_.handler_->OnUiAction(PairingEvent::UI_ACTION_TYPE::PASSKEY, passkey); - } - } -} - -void SecurityManagerImpl::OnPinEntry(const bluetooth::hci::AddressWithType& address, - std::vector<uint8_t> pin) { - auto entry = pairing_handler_map_.find(address.GetAddress()); - if (entry != pairing_handler_map_.end()) { - log::info("PIN for {}", address); - entry->second->OnPinEntry(address, pin); - } else { - log::warn("No handler found for PIN for {}", address); - // TODO(jpawlowski): Implement LE version - } -} - -void SecurityManagerImpl::OnPairingHandlerComplete(hci::Address address, - PairingResultOrFailure status) { - auto entry = pairing_handler_map_.find(address); - if (entry != pairing_handler_map_.end()) { - pairing_handler_map_.erase(entry); - security_manager_channel_->Release(address); - } - auto remote = hci::AddressWithType(address, hci::AddressType::PUBLIC_DEVICE_ADDRESS); - if (!std::holds_alternative<PairingFailure>(status)) { - NotifyDeviceBonded(remote); - } else { - NotifyDeviceBondFailed(remote, std::get<PairingFailure>(status)); - } - auto record = this->security_database_.FindOrCreate(remote); - record->CancelPairing(); - security_database_.SaveRecordsToStorage(); - // Only call update link if we need to - auto policy_callback_entry = enforce_security_policy_callback_map_.find(remote); - if (policy_callback_entry != enforce_security_policy_callback_map_.end()) { - UpdateLinkSecurityCondition(remote); - } -} - -void SecurityManagerImpl::OnL2capRegistrationCompleteLe( - l2cap::le::FixedChannelManager::RegistrationResult result, - [[maybe_unused]] std::unique_ptr<l2cap::le::FixedChannelService> le_smp_service) { - log::assert_that(result == bluetooth::l2cap::le::FixedChannelManager::RegistrationResult::SUCCESS, - "Failed to register to LE SMP Fixed Channel Service"); -} - -LeFixedChannelEntry* SecurityManagerImpl::FindStoredLeChannel(const hci::AddressWithType& device) { - for (LeFixedChannelEntry& storage : all_channels_) { - if (storage.channel_->GetDevice() == device) { - return &storage; - } - } - return nullptr; -} - -bool SecurityManagerImpl::EraseStoredLeChannel(const hci::AddressWithType& device) { - for (auto it = all_channels_.begin(); it != all_channels_.end(); it++) { - if (it->channel_->GetDevice() == device) { - all_channels_.erase(it); - return true; - } - } - return false; -} - -void SecurityManagerImpl::OnSmpCommandLe(hci::AddressWithType device) { - LeFixedChannelEntry* stored_chan = FindStoredLeChannel(device); - if (!stored_chan) { - log::fatal("Received SMP command for unknown channel"); - return; - } - - std::unique_ptr<l2cap::le::FixedChannel>& channel = stored_chan->channel_; - - auto packet = channel->GetQueueUpEnd()->TryDequeue(); - if (!packet) { - log::error("Received dequeue, but no data ready..."); - return; - } - - // Pending pairing - pass the data to the handler - auto temp_cmd_view = CommandView::Create(*packet); - if (pending_le_pairing_.address_ == device) { - pending_le_pairing_.handler_->OnCommandView(temp_cmd_view); - return; - } - - // no pending pairing attempt - if (!temp_cmd_view.IsValid()) { - log::error("Invalid Command packet"); - return; - } - - if (temp_cmd_view.GetCode() == Code::SECURITY_REQUEST) { - // TODO: either start encryption or pairing - log::warn("Unhandled security request!!!"); - return; - } - - auto my_role = channel->GetLinkOptions()->GetRole(); - if (temp_cmd_view.GetCode() == Code::PAIRING_REQUEST && my_role == hci::Role::PERIPHERAL) { - // TODO: if (pending_le_pairing_) { do not start another } - - log::info("start of security request handling!"); - - stored_chan->channel_->Acquire(); - - PairingRequestView pairing_request = PairingRequestView::Create(temp_cmd_view); - auto& enqueue_buffer = stored_chan->enqueue_buffer_; - - std::optional<InitialInformations::out_of_band_data> remote_oob_data = std::nullopt; - if (remote_oob_data_address_.has_value() && - remote_oob_data_address_.value() == channel->GetDevice()) { - remote_oob_data = - InitialInformations::out_of_band_data{.le_sc_c = remote_oob_data_le_sc_c_.value(), - .le_sc_r = remote_oob_data_le_sc_r_.value()}; - } - - // TODO: this doesn't have to be a unique ptr, if there is a way to properly std::move it into - // place where it's stored - pending_le_pairing_.connection_handle_ = channel->GetLinkOptions()->GetHandle(); - InitialInformations initial_informations{ - .my_role = my_role, - .my_connection_address = channel->GetLinkOptions()->GetLocalAddress(), - .my_identity_address = local_identity_address_, - .my_identity_resolving_key = local_identity_resolving_key_, - /*TODO: properly obtain capabilities from device-specific storage*/ - .myPairingCapabilities = {.io_capability = local_le_io_capability_, - .oob_data_flag = local_le_oob_data_present_, - .auth_req = local_le_auth_req_, - .maximum_encryption_key_size = - local_maximum_encryption_key_size_, - .initiator_key_distribution = 0x07, - .responder_key_distribution = 0x07}, - .remotely_initiated = true, - .connection_handle = channel->GetLinkOptions()->GetHandle(), - .remote_connection_address = channel->GetDevice(), - .remote_name = "TODO: grab proper device name in sec mgr", - /* contains pairing request, if the pairing was remotely initiated */ - .pairing_request = pairing_request, - .remote_oob_data = remote_oob_data, - .my_oob_data = local_le_oob_data_, - /* Used by Pairing Handler to present user with requests*/ - .user_interface = user_interface_, - .user_interface_handler = user_interface_handler_, - - /* HCI interface to use */ - .le_security_interface = hci_security_interface_le_, - .proper_l2cap_interface = enqueue_buffer.get(), - .l2cap_handler = security_handler_, - /* Callback to execute once the Pairing process is finished */ - // TODO: make it a common::OnceCallback ? - .OnPairingFinished = - std::bind(&SecurityManagerImpl::OnPairingFinished, this, std::placeholders::_1), - }; - pending_le_pairing_.address_ = device; - pending_le_pairing_.handler_ = - std::make_unique<PairingHandlerLe>(PairingHandlerLe::PHASE1, initial_informations); - } -} - -void SecurityManagerImpl::OnConnectionOpenLe( - std::unique_ptr<l2cap::le::FixedChannel> channel_param) { - auto enqueue_buffer_temp = std::make_unique<os::EnqueueBuffer<packet::BasePacketBuilder>>( - channel_param->GetQueueUpEnd()); - - all_channels_.push_back({std::move(channel_param), std::move(enqueue_buffer_temp)}); - auto& stored_channel = all_channels_.back(); - auto& channel = stored_channel.channel_; - - channel->RegisterOnCloseCallback( - security_handler_, common::BindOnce(&SecurityManagerImpl::OnConnectionClosedLe, - common::Unretained(this), channel->GetDevice())); - channel->GetQueueUpEnd()->RegisterDequeue( - security_handler_, common::Bind(&SecurityManagerImpl::OnSmpCommandLe, - common::Unretained(this), channel->GetDevice())); - - if (pending_le_pairing_.address_ != channel->GetDevice()) { - return; - } - - ConnectionIsReadyStartPairing(&stored_channel); -} - -void SecurityManagerImpl::ConnectionIsReadyStartPairing(LeFixedChannelEntry* stored_channel) { - auto& channel = stored_channel->channel_; - auto& enqueue_buffer = stored_channel->enqueue_buffer_; - - stored_channel->channel_->Acquire(); - - std::optional<InitialInformations::out_of_band_data> remote_oob_data = std::nullopt; - if (remote_oob_data_address_.has_value() && - remote_oob_data_address_.value() == channel->GetDevice()) { - remote_oob_data = - InitialInformations::out_of_band_data{.le_sc_c = remote_oob_data_le_sc_c_.value(), - .le_sc_r = remote_oob_data_le_sc_r_.value()}; - } - - // TODO: this doesn't have to be a unique ptr, if there is a way to properly std::move it into - // place where it's stored - pending_le_pairing_.connection_handle_ = channel->GetLinkOptions()->GetHandle(); - InitialInformations initial_informations{ - .my_role = channel->GetLinkOptions()->GetRole(), - .my_connection_address = channel->GetLinkOptions()->GetLocalAddress(), - .my_identity_address = local_identity_address_, - .my_identity_resolving_key = local_identity_resolving_key_, - /*TODO: properly obtain capabilities from device-specific storage*/ - .myPairingCapabilities = {.io_capability = local_le_io_capability_, - .oob_data_flag = local_le_oob_data_present_, - .auth_req = local_le_auth_req_, - .maximum_encryption_key_size = - local_maximum_encryption_key_size_, - .initiator_key_distribution = 0x07, - .responder_key_distribution = 0x07}, - .remotely_initiated = false, - .connection_handle = channel->GetLinkOptions()->GetHandle(), - .remote_connection_address = channel->GetDevice(), - .remote_name = "TODO: grab proper device name in sec mgr", - /* contains pairing request, if the pairing was remotely initiated */ - .pairing_request = std::nullopt, // TODO: handle remotely initiated pairing in - // SecurityManager properly - .remote_oob_data = remote_oob_data, - .my_oob_data = local_le_oob_data_, - /* Used by Pairing Handler to present user with requests*/ - .user_interface = user_interface_, - .user_interface_handler = user_interface_handler_, - - /* HCI interface to use */ - .le_security_interface = hci_security_interface_le_, - .proper_l2cap_interface = enqueue_buffer.get(), - .l2cap_handler = security_handler_, - /* Callback to execute once the Pairing process is finished */ - // TODO: make it a common::OnceCallback ? - .OnPairingFinished = - std::bind(&SecurityManagerImpl::OnPairingFinished, this, std::placeholders::_1), - }; - pending_le_pairing_.handler_ = - std::make_unique<PairingHandlerLe>(PairingHandlerLe::PHASE1, initial_informations); -} - -void SecurityManagerImpl::OnConnectionClosedLe(hci::AddressWithType address, - hci::ErrorCode /* error_code */) { - if (pending_le_pairing_.address_ != address) { - LeFixedChannelEntry* stored_chan = FindStoredLeChannel(address); - if (!stored_chan) { - log::fatal("Received connection closed for unknown channel"); - return; - } - stored_chan->channel_->GetQueueUpEnd()->UnregisterDequeue(); - stored_chan->enqueue_buffer_.reset(); - EraseStoredLeChannel(address); - return; - } - pending_le_pairing_.handler_->SendExitSignal(); - NotifyDeviceBondFailed(address, PairingFailure("Connection closed")); -} - -void SecurityManagerImpl::OnConnectionFailureLe( - bluetooth::l2cap::le::FixedChannelManager::ConnectionResult result) { - if (result.connection_result_code == - bluetooth::l2cap::le::FixedChannelManager::ConnectionResultCode:: - FAIL_ALL_SERVICES_HAVE_CHANNEL) { - // TODO: already connected - } - - // This callback is invoked only for devices we attempted to connect to. - NotifyDeviceBondFailed(pending_le_pairing_.address_, - PairingFailure("Connection establishment failed")); -} - -SecurityManagerImpl::SecurityManagerImpl(os::Handler* security_handler, - l2cap::le::L2capLeModule* l2cap_le_module, - channel::SecurityManagerChannel* security_manager_channel, - hci::HciLayer* hci_layer, hci::AclManager* acl_manager, - hci::Controller* controller, - storage::StorageModule* storage_module, - neighbor::NameDbModule* name_db_module) - : security_handler_(security_handler), - l2cap_le_module_(l2cap_le_module), - l2cap_manager_le_(l2cap_le_module_->GetFixedChannelManager()), - hci_security_interface_le_(hci_layer->GetLeSecurityInterface( - security_handler_->BindOn(this, &SecurityManagerImpl::OnHciLeEvent))), - security_manager_channel_(security_manager_channel), - acl_manager_(acl_manager), - controller_(controller), - storage_module_(storage_module), - security_record_storage_(storage_module, security_handler), - security_database_(security_record_storage_), - name_db_module_(name_db_module) { - Init(); - - l2cap_manager_le_->RegisterService( - bluetooth::l2cap::kSmpCid, - common::BindOnce(&SecurityManagerImpl::OnL2capRegistrationCompleteLe, - common::Unretained(this)), - common::Bind(&SecurityManagerImpl::OnConnectionOpenLe, common::Unretained(this)), - security_handler_); -} - -void SecurityManagerImpl::OnPairingFinished(security::PairingResultOrFailure pairing_result) { - log::info( - "■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ Received " - "pairing result"); - - LeFixedChannelEntry* stored_chan = FindStoredLeChannel(pending_le_pairing_.address_); - if (stored_chan) { - stored_chan->channel_->Release(); - } - - if (std::holds_alternative<PairingFailure>(pairing_result)) { - PairingFailure failure = std::get<PairingFailure>(pairing_result); - log::info( - "■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ failure " - "message: {}", - failure.message); - if (stored_chan) { - NotifyDeviceBondFailed(stored_chan->channel_->GetDevice(), failure); - } - return; - } - - auto result = std::get<PairingResult>(pairing_result); - log::info("Pairing with {} was successful", result.connection_address); - - // TODO: ensure that the security level is not weaker than what we already have. - auto record = this->security_database_.FindOrCreate(result.connection_address); - record->identity_address_ = result.distributed_keys.remote_identity_address; - record->remote_ltk = result.distributed_keys.remote_ltk; - record->key_size = result.key_size; - record->security_level = result.security_level; - record->remote_ediv = result.distributed_keys.remote_ediv; - record->remote_rand = result.distributed_keys.remote_rand; - record->remote_irk = result.distributed_keys.remote_irk; - record->remote_signature_key = result.distributed_keys.remote_signature_key; - if (result.distributed_keys.remote_link_key) { - record->SetLinkKey(*result.distributed_keys.remote_link_key, hci::KeyType::AUTHENTICATED_P256); - } - security_database_.SaveRecordsToStorage(); - - NotifyDeviceBonded(result.connection_address); - // We also notify bond complete using identity address. That's what old stack used to do. - if (result.distributed_keys.remote_identity_address) { - NotifyDeviceBonded(*result.distributed_keys.remote_identity_address); - } - - security_handler_->CallOn(this, &SecurityManagerImpl::WipeLePairingHandler); -} - -void SecurityManagerImpl::WipeLePairingHandler() { - pending_le_pairing_.handler_.reset(); - pending_le_pairing_.connection_handle_ = kInvalidConnectionHandle; - pending_le_pairing_.address_ = hci::AddressWithType(); -} - -// Facade Configuration API functions -void SecurityManagerImpl::SetDisconnectCallback(FacadeDisconnectCallback callback) { - this->facade_disconnect_callback_ = std::make_optional<FacadeDisconnectCallback>(callback); -} - -void SecurityManagerImpl::SetIoCapability(hci::IoCapability io_capability) { - this->local_io_capability_ = io_capability; -} - -void SecurityManagerImpl::SetLeIoCapability(security::IoCapability io_capability) { - this->local_le_io_capability_ = io_capability; -} - -void SecurityManagerImpl::SetLeAuthRequirements(uint8_t auth_req) { - this->local_le_auth_req_ = auth_req; -} - -void SecurityManagerImpl::SetLeMaximumEncryptionKeySize(uint8_t maximum_encryption_key_size) { - this->local_maximum_encryption_key_size_ = maximum_encryption_key_size; -} - -void SecurityManagerImpl::SetLeOobDataPresent(OobDataFlag data_present) { - this->local_le_oob_data_present_ = data_present; -} - -void SecurityManagerImpl::GetOutOfBandData(channel::SecurityCommandStatusCallback callback) { - this->security_manager_channel_->SendCommand( - hci::ReadLocalOobDataBuilder::Create(), - std::forward<channel::SecurityCommandStatusCallback>(callback)); -} - -void SecurityManagerImpl::GetLeOutOfBandData(std::array<uint8_t, 16>* confirmation_value, - std::array<uint8_t, 16>* random_value) { - local_le_oob_data_ = std::make_optional<MyOobData>(PairingHandlerLe::GenerateOobData()); - *confirmation_value = local_le_oob_data_.value().c; - *random_value = local_le_oob_data_.value().r; -} - -void SecurityManagerImpl::SetOutOfBandData(hci::AddressWithType remote_address, - std::array<uint8_t, 16> confirmation_value, - std::array<uint8_t, 16> random_value) { - remote_oob_data_address_ = remote_address; - remote_oob_data_le_sc_c_ = confirmation_value; - remote_oob_data_le_sc_r_ = random_value; -} - -void SecurityManagerImpl::SetAuthenticationRequirements( - hci::AuthenticationRequirements authentication_requirements) { - this->local_authentication_requirements_ = authentication_requirements; -} - -void SecurityManagerImpl::InternalEnforceSecurityPolicy( - hci::AddressWithType remote, l2cap::classic::SecurityPolicy policy, - l2cap::classic::SecurityEnforcementInterface::ResultCallback result_callback) { - if (IsSecurityRequirementSatisfied(remote, policy)) { - // Notify client immediately if already satisfied - std::move(result_callback)(true); - return; - } - - // At this point we don't meet the security requirements; must pair - auto record = this->security_database_.FindOrCreate(remote); - hci::AuthenticationRequirements authentication_requirements = kDefaultAuthenticationRequirements; - enforce_security_policy_callback_map_[remote] = {policy, std::move(result_callback)}; - - switch (policy) { - case l2cap::classic::SecurityPolicy::BEST: - case l2cap::classic::SecurityPolicy::AUTHENTICATED_ENCRYPTED_TRANSPORT: - // Force MITM requirement locally - authentication_requirements = - hci::AuthenticationRequirements::GENERAL_BONDING_MITM_PROTECTION; - break; - case l2cap::classic::SecurityPolicy::ENCRYPTED_TRANSPORT: - authentication_requirements = hci::AuthenticationRequirements::GENERAL_BONDING; - break; - default: - // I could hear the voice of Myles, "This should be an ASSERT!" - log::fatal("Unreachable code path"); - return; - } - - log::warn("Dispatch #3"); - DispatchPairingHandler(record, true, this->local_io_capability_, - std::as_const(authentication_requirements), pairing::OobData(), - pairing::OobData()); -} - -void SecurityManagerImpl::UpdateLinkSecurityCondition(hci::AddressWithType remote) { - auto entry = enforce_security_policy_callback_map_.find(remote); - if (entry == enforce_security_policy_callback_map_.end()) { - log::error("No L2CAP security policy callback pending for {}", remote); - return; - } - std::move(entry->second.callback_)(IsSecurityRequirementSatisfied(remote, entry->second.policy_)); - enforce_security_policy_callback_map_.erase(entry); -} - -bool SecurityManagerImpl::IsSecurityRequirementSatisfied(hci::AddressWithType remote, - l2cap::classic::SecurityPolicy policy) { - auto record = security_database_.FindOrCreate(remote); - switch (policy) { - case l2cap::classic::SecurityPolicy::BEST: - case l2cap::classic::SecurityPolicy::AUTHENTICATED_ENCRYPTED_TRANSPORT: - return record->IsPaired() && record->IsAuthenticated(); - case l2cap::classic::SecurityPolicy::ENCRYPTED_TRANSPORT: - return record->IsPaired(); - default: - return true; - } -} - -void SecurityManagerImpl::EnforceSecurityPolicy( - hci::AddressWithType remote, l2cap::classic::SecurityPolicy policy, - l2cap::classic::SecurityEnforcementInterface::ResultCallback result_callback) { - log::info("Attempting to enforce security policy"); - auto record = security_database_.FindOrCreate(remote); - if (!record->IsPairing()) { - this->InternalEnforceSecurityPolicy(remote, policy, std::move(result_callback)); - } -} - -void SecurityManagerImpl::EnforceLeSecurityPolicy( - hci::AddressWithType /* remote */, l2cap::le::SecurityPolicy policy, - l2cap::le::SecurityEnforcementInterface::ResultCallback result_callback) { - bool result = false; - // TODO(jpawlowski): Implement for LE - switch (policy) { - case l2cap::le::SecurityPolicy::BEST: - break; - case l2cap::le::SecurityPolicy::AUTHENTICATED_ENCRYPTED_TRANSPORT: - break; - case l2cap::le::SecurityPolicy::ENCRYPTED_TRANSPORT: - break; - case l2cap::le::SecurityPolicy::NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK: - result = true; - break; - case l2cap::le::SecurityPolicy::_NOT_FOR_YOU__AUTHENTICATED_PAIRING_WITH_128_BIT_KEY: - break; - case l2cap::le::SecurityPolicy::_NOT_FOR_YOU__AUTHORIZATION: - break; - } - result_callback(result); -} -} // namespace internal -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/internal/security_manager_impl.h b/system/gd/security/internal/security_manager_impl.h deleted file mode 100644 index e5a9cb81c6..0000000000 --- a/system/gd/security/internal/security_manager_impl.h +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <storage/storage_module.h> - -#include <unordered_map> -#include <utility> -#include <vector> - -#include "hci/acl_manager.h" -#include "hci/controller.h" -#include "hci/octets.h" -#include "l2cap/classic/security_enforcement_interface.h" -#include "l2cap/le/l2cap_le_module.h" -#include "l2cap/le/security_enforcement_interface.h" -#include "neighbor/name_db.h" -#include "os/handler.h" -#include "security/channel/security_manager_channel.h" -#include "security/initial_informations.h" -#include "security/pairing/classic_pairing_handler.h" -#include "security/pairing/oob_data.h" -#include "security/pairing_handler_le.h" -#include "security/record/security_record.h" -#include "security/record/security_record_database.h" - -namespace bluetooth { -namespace security { - -class ISecurityManagerListener; - -static constexpr hci::IoCapability kDefaultIoCapability = hci::IoCapability::DISPLAY_YES_NO; -static constexpr hci::AuthenticationRequirements kDefaultAuthenticationRequirements = - hci::AuthenticationRequirements::GENERAL_BONDING; - -namespace internal { - -static constexpr uint16_t kInvalidConnectionHandle = 0xFFFF; - -struct LeFixedChannelEntry { - std::unique_ptr<l2cap::le::FixedChannel> channel_; - std::unique_ptr<os::EnqueueBuffer<packet::BasePacketBuilder>> enqueue_buffer_; -}; - -class SecurityManagerImpl : public channel::ISecurityManagerChannelListener, public UICallbacks { -public: - explicit SecurityManagerImpl(os::Handler* security_handler, - l2cap::le::L2capLeModule* l2cap_le_module, - channel::SecurityManagerChannel* security_manager_channel, - hci::HciLayer* hci_layer, hci::AclManager* acl_manager, - hci::Controller* controller, storage::StorageModule* storage_module, - neighbor::NameDbModule* name_db_module); - - ~SecurityManagerImpl() { - /* L2CAP layer doesn't guarantee to send the registered OnCloseCallback during shutdown. Cleanup - * the remaining queues to prevent crashes */ - for (auto& stored_chan : all_channels_) { - stored_chan.channel_->GetQueueUpEnd()->UnregisterDequeue(); - stored_chan.enqueue_buffer_.reset(); - } - } - - // All APIs must be invoked in SM layer handler - - /** - * Initialize the security record map from an internal device database. - */ - void Init(); - - /** - * Initiates bond over Classic transport with device, if not bonded yet. - * - * @param address device address we want to bond with - */ - void CreateBond(hci::AddressWithType address); - - /** - * Initiates bond over Classic transport with device, if not bonded yet. - * - * Allows for OobData to be passed in for use while pairing - * - * @param address device address we want to bond with - * @param remote_p192_oob_data P192 data given to the stack - * @param remote_p256_oob_data P256 data given to the stack - */ - void CreateBondOutOfBand(hci::AddressWithType address, pairing::OobData remote_p192_oob_data, - pairing::OobData remote_p256_oob_data); - - /** - * Initiates bond over Low Energy transport with device, if not bonded yet. - * - * @param address device address we want to bond with - */ - void CreateBondLe(hci::AddressWithType address); - - /* void CreateBond(std::shared_ptr<hci::LeDevice> device); */ - - /** - * Cancels the pairing process for this device. - * - * @param device pointer to device with which we want to cancel our bond - */ - void CancelBond(hci::AddressWithType device); - - /* void CancelBond(std::shared_ptr<hci::LeDevice> device); */ - - /** - * Disassociates the device and removes the persistent LTK - * - * @param device pointer to device we want to forget - * @return true if removed - */ - void RemoveBond(hci::AddressWithType device); - - /* void RemoveBond(std::shared_ptr<hci::LeDevice> device); */ - - /** - * Register Security UI handler, for handling prompts around the Pairing process. - */ - void SetUserInterfaceHandler(UI* user_interface, os::Handler* handler); - - /** - * Specify the initiator address policy used for LE transport. Can only be called once. - */ - void SetLeInitiatorAddressPolicyForTest(hci::LeAddressManager::AddressPolicy address_policy, - hci::AddressWithType fixed_address, - hci::Octet16 rotation_irk, - std::chrono::milliseconds minimum_rotation_time, - std::chrono::milliseconds maximum_rotation_time); - - /** - * Register to listen for callback events from SecurityManager - * - * @param listener ISecurityManagerListener instance to handle callbacks - */ - void RegisterCallbackListener(ISecurityManagerListener* listener, os::Handler* handler); - - /** - * Unregister listener for callback events from SecurityManager - * - * @param listener ISecurityManagerListener instance to unregister - */ - void UnregisterCallbackListener(ISecurityManagerListener* listener); - - /** - * Handle the events sent back from HCI that we care about - * - * @param packet data received from HCI - */ - void OnHciEventReceived(hci::EventView packet) override; - - /** - * When a conncetion closes we should clean up the pairing handler - * - * @param address Remote address - */ - void OnConnectionClosed(hci::Address address) override; - - /** - * Pairing handler has finished or cancelled - * - * @param address address for pairing handler - * @param status status from SimplePairingComplete or other error code - */ - void OnPairingHandlerComplete(hci::Address address, PairingResultOrFailure status); - - // UICallbacks implementation - void OnPairingPromptAccepted(const bluetooth::hci::AddressWithType& address, - bool confirmed) override; - void OnConfirmYesNo(const bluetooth::hci::AddressWithType& address, bool confirmed) override; - void OnPasskeyEntry(const bluetooth::hci::AddressWithType& address, uint32_t passkey) override; - void OnPinEntry(const bluetooth::hci::AddressWithType& address, - std::vector<uint8_t> pin) override; - - // Facade Configuration API functions - using FacadeDisconnectCallback = common::Callback<void(bluetooth::hci::AddressWithType)>; - void SetDisconnectCallback(FacadeDisconnectCallback callback); - void SetIoCapability(hci::IoCapability io_capability); - void SetAuthenticationRequirements(hci::AuthenticationRequirements authentication_requirements); - void GetOutOfBandData(channel::SecurityCommandStatusCallback callback); - void SetLeIoCapability(security::IoCapability io_capability); - void SetLeAuthRequirements(uint8_t auth_req); - void SetLeMaximumEncryptionKeySize(uint8_t maximum_encryption_key_size); - void SetLeOobDataPresent(OobDataFlag data_present); - void GetLeOutOfBandData(std::array<uint8_t, 16>* confirmation_value, - std::array<uint8_t, 16>* random_value); - void SetOutOfBandData(hci::AddressWithType remote_address, - std::array<uint8_t, 16> confirmation_value, - std::array<uint8_t, 16> random_value); - - void EnforceSecurityPolicy( - hci::AddressWithType remote, l2cap::classic::SecurityPolicy policy, - l2cap::classic::SecurityEnforcementInterface::ResultCallback result_callback); - void EnforceLeSecurityPolicy( - hci::AddressWithType remote, l2cap::le::SecurityPolicy policy, - l2cap::le::SecurityEnforcementInterface::ResultCallback result_callback); - -protected: - std::vector<std::pair<ISecurityManagerListener*, os::Handler*>> listeners_; - UI* user_interface_ = nullptr; - os::Handler* user_interface_handler_ = nullptr; - - void NotifyDeviceBonded(hci::AddressWithType device); - void NotifyDeviceBondFailed(hci::AddressWithType device, PairingFailure status); - void NotifyDeviceUnbonded(hci::AddressWithType device); - void NotifyEncryptionStateChanged(hci::EncryptionChangeView encryption_change_view); - -private: - template <class T> - void HandleEvent(T packet); - - void DispatchPairingHandler(std::shared_ptr<record::SecurityRecord> record, - bool locally_initiated, hci::IoCapability io_capability, - hci::AuthenticationRequirements auth_requirements, - pairing::OobData remote_p192_oob_data_, - pairing::OobData remote_p256_oob_data_); - void OnL2capRegistrationCompleteLe( - l2cap::le::FixedChannelManager::RegistrationResult result, - std::unique_ptr<l2cap::le::FixedChannelService> le_smp_service); - void OnSmpCommandLe(hci::AddressWithType device); - void OnConnectionOpenLe(std::unique_ptr<l2cap::le::FixedChannel> channel); - void OnConnectionClosedLe(hci::AddressWithType address, hci::ErrorCode error_code); - void OnConnectionFailureLe(bluetooth::l2cap::le::FixedChannelManager::ConnectionResult result); - void OnPairingFinished(bluetooth::security::PairingResultOrFailure pairing_result); - void OnHciLeEvent(hci::LeMetaEventView event); - LeFixedChannelEntry* FindStoredLeChannel(const hci::AddressWithType& device); - LeFixedChannelEntry* FindStoredLeChannel(uint8_t connection_handle); - bool EraseStoredLeChannel(const hci::AddressWithType& device); - void InternalEnforceSecurityPolicy( - hci::AddressWithType remote, l2cap::classic::SecurityPolicy policy, - l2cap::classic::SecurityEnforcementInterface::ResultCallback result_callback); - void UpdateLinkSecurityCondition(hci::AddressWithType remote); - bool IsSecurityRequirementSatisfied(hci::AddressWithType remote, - l2cap::classic::SecurityPolicy policy); - void ConnectionIsReadyStartPairing(LeFixedChannelEntry* stored_channel); - void WipeLePairingHandler(); - - os::Handler* security_handler_ __attribute__((unused)); - l2cap::le::L2capLeModule* l2cap_le_module_ __attribute__((unused)); - std::unique_ptr<l2cap::le::FixedChannelManager> l2cap_manager_le_; - hci::LeSecurityInterface* hci_security_interface_le_ __attribute__((unused)); - channel::SecurityManagerChannel* security_manager_channel_; - hci::AclManager* acl_manager_; - hci::Controller* controller_; - storage::StorageModule* storage_module_ __attribute__((unused)); - record::SecurityRecordStorage security_record_storage_; - record::SecurityRecordDatabase security_database_; - neighbor::NameDbModule* name_db_module_; - std::unordered_map<hci::Address, std::shared_ptr<pairing::PairingHandler>> pairing_handler_map_; - hci::IoCapability local_io_capability_ = kDefaultIoCapability; - hci::AuthenticationRequirements local_authentication_requirements_ = - kDefaultAuthenticationRequirements; - security::IoCapability local_le_io_capability_ = security::IoCapability::KEYBOARD_DISPLAY; - uint8_t local_le_auth_req_ = AuthReqMaskBondingFlag | AuthReqMaskMitm | AuthReqMaskSc; - uint8_t local_maximum_encryption_key_size_ = 0x10; - OobDataFlag local_le_oob_data_present_ = OobDataFlag::NOT_PRESENT; - std::optional<MyOobData> local_le_oob_data_; - std::optional<hci::AddressWithType> remote_oob_data_address_; - std::optional<hci::Octet16> remote_oob_data_le_sc_c_; - std::optional<hci::Octet16> remote_oob_data_le_sc_r_; - std::optional<FacadeDisconnectCallback> facade_disconnect_callback_; - hci::AddressWithType local_identity_address_; - hci::Octet16 local_identity_resolving_key_; - - struct PendingSecurityEnforcementEntry { - l2cap::classic::SecurityPolicy policy_; - l2cap::classic::SecurityEnforcementInterface::ResultCallback callback_; - }; - std::unordered_map<hci::AddressWithType, PendingSecurityEnforcementEntry> - enforce_security_policy_callback_map_; - - struct { - hci::AddressWithType address_; - uint16_t connection_handle_{kInvalidConnectionHandle}; - std::unique_ptr<PairingHandlerLe> handler_; - } pending_le_pairing_; - - std::list<LeFixedChannelEntry> all_channels_; -}; -} // namespace internal -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/l2cap_security_module_interface.cc b/system/gd/security/l2cap_security_module_interface.cc deleted file mode 100644 index ce28388c39..0000000000 --- a/system/gd/security/l2cap_security_module_interface.cc +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2020 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 "security/l2cap_security_module_interface.h" - -#include "common/bind.h" - -namespace bluetooth { -namespace security { - -L2capSecurityModuleInterface::L2capSecurityModuleInterface( - internal::SecurityManagerImpl* security_manager_impl, os::Handler* security_handler) - : security_manager_impl_(security_manager_impl), security_handler_(security_handler) {} - -void L2capSecurityModuleInterface::Enforce( - hci::AddressWithType remote, l2cap::classic::SecurityPolicy policy, - l2cap::classic::SecurityEnforcementInterface::ResultCallback result_callback) { - this->security_handler_->Post(common::BindOnce( - &internal::SecurityManagerImpl::EnforceSecurityPolicy, - common::Unretained(security_manager_impl_), std::forward<hci::AddressWithType>(remote), - std::forward<l2cap::classic::SecurityPolicy>(policy), - std::forward<l2cap::classic::SecurityEnforcementInterface::ResultCallback>( - result_callback))); -} - -void L2capSecurityModuleInterface::Enforce( - hci::AddressWithType remote, l2cap::le::SecurityPolicy policy, - l2cap::le::SecurityEnforcementInterface::ResultCallback result_callback) { - this->security_handler_->Post(common::BindOnce( - &internal::SecurityManagerImpl::EnforceLeSecurityPolicy, - common::Unretained(security_manager_impl_), std::forward<hci::AddressWithType>(remote), - std::forward<l2cap::le::SecurityPolicy>(policy), - std::forward<l2cap::le::SecurityEnforcementInterface::ResultCallback>(result_callback))); -} - -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/l2cap_security_module_interface.h b/system/gd/security/l2cap_security_module_interface.h deleted file mode 100644 index a199c22890..0000000000 --- a/system/gd/security/l2cap_security_module_interface.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2020 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. - */ -#pragma once - -#include "l2cap/classic/security_enforcement_interface.h" -#include "l2cap/le/security_enforcement_interface.h" -#include "os/handler.h" -#include "security/internal/security_manager_impl.h" - -namespace bluetooth { -namespace security { -class L2capSecurityModuleInterface : public l2cap::classic::SecurityEnforcementInterface, - public l2cap::le::SecurityEnforcementInterface { -public: - L2capSecurityModuleInterface(internal::SecurityManagerImpl* security_manager_impl, - os::Handler* security_handler); - void Enforce( - hci::AddressWithType remote, l2cap::classic::SecurityPolicy policy, - l2cap::classic::SecurityEnforcementInterface::ResultCallback result_callback) override; - void Enforce(hci::AddressWithType remote, l2cap::le::SecurityPolicy policy, - l2cap::le::SecurityEnforcementInterface::ResultCallback result_callback) override; - -private: - internal::SecurityManagerImpl* security_manager_impl_; - os::Handler* security_handler_ = nullptr; -}; - -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/pairing/Android.bp b/system/gd/security/pairing/Android.bp deleted file mode 100644 index 20e5e331f9..0000000000 --- a/system/gd/security/pairing/Android.bp +++ /dev/null @@ -1,22 +0,0 @@ -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "system_bt_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["system_bt_license"], -} - -filegroup { - name: "BluetoothSecurityPairingSources", - srcs: [ - "classic_pairing_handler.cc", - ], -} - -filegroup { - name: "BluetoothSecurityPairingTestSources", - srcs: [ - "classic_pairing_handler_unittest.cc", - ], -} diff --git a/system/gd/security/pairing/classic_pairing_handler.cc b/system/gd/security/pairing/classic_pairing_handler.cc deleted file mode 100644 index a4a73909db..0000000000 --- a/system/gd/security/pairing/classic_pairing_handler.cc +++ /dev/null @@ -1,696 +0,0 @@ -/* - * - * Copyright 2019 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 "security/pairing/classic_pairing_handler.h" - -#include <bluetooth/log.h> - -#include "common/bind.h" - -namespace bluetooth { -namespace security { -namespace pairing { - -void ClassicPairingHandler::NotifyUiDisplayYesNo(uint32_t numeric_value) { - log::assert_that(user_interface_handler_ != nullptr, - "assert failed: user_interface_handler_ != nullptr"); - ConfirmationData data(*GetRecord()->GetPseudoAddress(), device_name_, numeric_value); - data.SetRemoteIoCaps(remote_io_capability_); - data.SetRemoteAuthReqs(remote_authentication_requirements_); - data.SetRemoteOobDataPresent(remote_oob_present_); - user_interface_handler_->CallOn(user_interface_, &UI::DisplayConfirmValue, data); -} - -void ClassicPairingHandler::NotifyUiDisplayYesNo() { - log::assert_that(user_interface_handler_ != nullptr, - "assert failed: user_interface_handler_ != nullptr"); - ConfirmationData data(*GetRecord()->GetPseudoAddress(), device_name_); - data.SetRemoteIoCaps(remote_io_capability_); - data.SetRemoteAuthReqs(remote_authentication_requirements_); - data.SetRemoteOobDataPresent(remote_oob_present_); - user_interface_handler_->CallOn(user_interface_, &UI::DisplayYesNoDialog, data); -} - -void ClassicPairingHandler::NotifyUiDisplayPasskey(uint32_t passkey) { - log::assert_that(user_interface_handler_ != nullptr, - "assert failed: user_interface_handler_ != nullptr"); - ConfirmationData data(*GetRecord()->GetPseudoAddress(), device_name_, passkey); - data.SetRemoteIoCaps(remote_io_capability_); - data.SetRemoteAuthReqs(remote_authentication_requirements_); - data.SetRemoteOobDataPresent(remote_oob_present_); - user_interface_handler_->CallOn(user_interface_, &UI::DisplayPasskey, data); -} - -void ClassicPairingHandler::NotifyUiDisplayPasskeyInput() { - log::assert_that(user_interface_handler_ != nullptr, - "assert failed: user_interface_handler_ != nullptr"); - ConfirmationData data(*GetRecord()->GetPseudoAddress(), device_name_); - data.SetRemoteIoCaps(remote_io_capability_); - data.SetRemoteAuthReqs(remote_authentication_requirements_); - data.SetRemoteOobDataPresent(remote_oob_present_); - user_interface_handler_->CallOn(user_interface_, &UI::DisplayEnterPasskeyDialog, data); -} - -void ClassicPairingHandler::NotifyUiDisplayPinCodeInput() { - log::assert_that(user_interface_handler_ != nullptr, - "assert failed: user_interface_handler_ != nullptr"); - ConfirmationData data(*GetRecord()->GetPseudoAddress(), device_name_); - data.SetRemoteIoCaps(remote_io_capability_); - data.SetRemoteAuthReqs(remote_authentication_requirements_); - data.SetRemoteOobDataPresent(remote_oob_present_); - user_interface_handler_->CallOn(user_interface_, &UI::DisplayEnterPinDialog, data); -} - -void ClassicPairingHandler::NotifyUiDisplayCancel() { - log::assert_that(user_interface_handler_ != nullptr, - "assert failed: user_interface_handler_ != nullptr"); - user_interface_handler_->CallOn(user_interface_, &UI::Cancel, *GetRecord()->GetPseudoAddress()); -} - -void ClassicPairingHandler::OnPairingPromptAccepted( - const bluetooth::hci::AddressWithType& /* address */, bool /* confirmed */) { - // NOTE: This is not used by Classic, only by LE - log::fatal("This is not supported by Classic Pairing Handler, only LE"); -} - -void ClassicPairingHandler::OnConfirmYesNo(const bluetooth::hci::AddressWithType& /* address */, - bool confirmed) { - if (confirmed) { - GetChannel()->SendCommand(hci::UserConfirmationRequestReplyBuilder::Create( - GetRecord()->GetPseudoAddress()->GetAddress())); - } else { - GetChannel()->SendCommand(hci::UserConfirmationRequestNegativeReplyBuilder::Create( - GetRecord()->GetPseudoAddress()->GetAddress())); - } -} - -void ClassicPairingHandler::OnPasskeyEntry(const bluetooth::hci::AddressWithType& address, - uint32_t passkey) { - GetChannel()->SendCommand( - hci::UserPasskeyRequestReplyBuilder::Create(address.GetAddress(), passkey)); -} - -void ClassicPairingHandler::OnPinEntry(const bluetooth::hci::AddressWithType& address, - std::vector<uint8_t> pin) { - std::array<uint8_t, 16> padded_pin; - for (size_t i = 0; i < 16 && i < pin.size(); i++) { - padded_pin[i] = pin[i]; - } - log::info("{}", address.GetAddress()); - GetChannel()->SendCommand( - hci::PinCodeRequestReplyBuilder::Create(address.GetAddress(), pin.size(), padded_pin)); -} - -void ClassicPairingHandler::Initiate(bool locally_initiated, hci::IoCapability io_capability, - hci::AuthenticationRequirements auth_requirements, - OobData remote_p192_oob_data, OobData remote_p256_oob_data) { - log::info("Initiate"); - locally_initiated_ = locally_initiated; - local_io_capability_ = io_capability; - local_authentication_requirements_ = auth_requirements; - remote_p192_oob_data_ = remote_p192_oob_data; - remote_p256_oob_data_ = remote_p256_oob_data; - bool has192 = remote_p192_oob_data.IsValid(); - bool has256 = remote_p256_oob_data.IsValid(); - bool has_both = has192 && has256; - - if (has_both) { - remote_oob_present_ = hci::OobDataPresent::P_192_AND_256_PRESENT; - } else { - if (has192) { - remote_oob_present_ = hci::OobDataPresent::P_192_PRESENT; - } else if (has256) { - remote_oob_present_ = hci::OobDataPresent::P_256_PRESENT; - } - } - - if (locally_initiated_) { - GetChannel()->Connect(GetRecord()->GetPseudoAddress()->GetAddress()); - } -} - -void ClassicPairingHandler::OnNameRequestComplete(hci::Address address, bool /* success */) { - if (GetNameDbModule()->IsNameCached(address)) { - auto remote_name = GetNameDbModule()->ReadCachedRemoteName(address); - std::string tmp_name; - for (uint8_t i : remote_name) { - tmp_name += i; - } - device_name_ = tmp_name; - } - has_gotten_name_response_ = true; - // For PIN Pairing - if (is_legacy_pin_code_) { - NotifyUiDisplayPinCodeInput(); - } - // For SSP/Numeric comparison flow - if (user_confirmation_request_) { - this->OnReceive(*user_confirmation_request_); - } - // For OOB Flow; we go to link key notification and must wait for name - if (link_key_notification_) { - this->OnReceive(*link_key_notification_); - } -} - -void ClassicPairingHandler::Cancel() { - if (is_cancelled_) { - return; - } - is_cancelled_ = true; - PairingResultOrFailure result = PairingResult(); - if (last_status_ != hci::ErrorCode::SUCCESS) { - result = PairingFailure(hci::ErrorCodeText(last_status_)); - } - std::move(complete_callback_).Run(GetRecord()->GetPseudoAddress()->GetAddress(), result); -} - -void ClassicPairingHandler::OnReceive(hci::ChangeConnectionLinkKeyCompleteView packet) { - log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()"); - log::info("Received unsupported event: {}", hci::EventCodeText(packet.GetEventCode())); -} - -void ClassicPairingHandler::OnReceive(hci::CentralLinkKeyCompleteView packet) { - log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()"); - log::info("Received unsupported event: {}", hci::EventCodeText(packet.GetEventCode())); -} - -void ClassicPairingHandler::OnReceive(hci::PinCodeRequestView packet) { - log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()"); - log::info("Received: {}", hci::EventCodeText(packet.GetEventCode())); - log::assert_that(GetRecord()->GetPseudoAddress()->GetAddress() == packet.GetBdAddr(), - "Address mismatch"); - is_legacy_pin_code_ = true; - GetNameDbModule()->ReadRemoteNameRequest( - GetRecord()->GetPseudoAddress()->GetAddress(), - common::BindOnce(&ClassicPairingHandler::OnNameRequestComplete, common::Unretained(this)), - security_handler_); -} - -void ClassicPairingHandler::OnReceive(hci::LinkKeyRequestView packet) { - log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()"); - if (already_link_key_replied_) { - log::warn("Pairing is already in progress..."); - return; - } - already_link_key_replied_ = true; - log::info("Received: {}", hci::EventCodeText(packet.GetEventCode())); - log::assert_that(GetRecord()->GetPseudoAddress()->GetAddress() == packet.GetBdAddr(), - "Address mismatch"); - if (GetRecord()->IsPaired()) { - log::info("Sending: LINK_KEY_REQUEST_REPLY"); - this->GetChannel()->SendCommand(hci::LinkKeyRequestReplyBuilder::Create( - GetRecord()->GetPseudoAddress()->GetAddress(), GetRecord()->GetLinkKey())); - last_status_ = hci::ErrorCode::SUCCESS; - Cancel(); - } else { - log::info("Sending: LINK_KEY_REQUEST_NEGATIVE_REPLY"); - this->GetChannel()->SendCommand(hci::LinkKeyRequestNegativeReplyBuilder::Create( - GetRecord()->GetPseudoAddress()->GetAddress())); - } -} - -void ClassicPairingHandler::OnReceive(hci::LinkKeyNotificationView packet) { - log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()"); - log::info("Received: {}", hci::EventCodeText(packet.GetEventCode())); - log::assert_that(GetRecord()->GetPseudoAddress()->GetAddress() == packet.GetBdAddr(), - "Address mismatch"); - GetRecord()->SetLinkKey(packet.GetLinkKey(), packet.GetKeyType()); - if (!has_gotten_name_response_) { - link_key_notification_ = std::make_optional<hci::LinkKeyNotificationView>(packet); - return; - } - if (is_legacy_pin_code_) { - last_status_ = hci::ErrorCode::SUCCESS; - } - Cancel(); -} - -void ClassicPairingHandler::OnReceive(hci::IoCapabilityRequestView packet) { - log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()"); - log::info("Received: {}", hci::EventCodeText(packet.GetEventCode())); - log::assert_that(GetRecord()->GetPseudoAddress()->GetAddress() == packet.GetBdAddr(), - "Address mismatch"); - hci::IoCapability io_capability = local_io_capability_; - hci::OobDataPresent oob_present = remote_oob_present_; - hci::AuthenticationRequirements authentication_requirements = local_authentication_requirements_; - auto reply_packet = hci::IoCapabilityRequestReplyBuilder::Create( - GetRecord()->GetPseudoAddress()->GetAddress(), io_capability, oob_present, - authentication_requirements); - this->GetChannel()->SendCommand(std::move(reply_packet)); - GetNameDbModule()->ReadRemoteNameRequest( - GetRecord()->GetPseudoAddress()->GetAddress(), - common::BindOnce(&ClassicPairingHandler::OnNameRequestComplete, common::Unretained(this)), - security_handler_); -} - -void ClassicPairingHandler::OnReceive(hci::IoCapabilityResponseView packet) { - log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()"); - log::info("Received: {}", hci::EventCodeText(packet.GetEventCode())); - log::assert_that(GetRecord()->GetPseudoAddress()->GetAddress() == packet.GetBdAddr(), - "Address mismatch"); - - remote_io_capability_ = packet.GetIoCapability(); - remote_authentication_requirements_ = packet.GetAuthenticationRequirements(); - - switch (remote_authentication_requirements_) { - case hci::AuthenticationRequirements::NO_BONDING: - GetRecord()->SetIsEncryptionRequired( - local_authentication_requirements_ != hci::AuthenticationRequirements::NO_BONDING || - local_authentication_requirements_ != - hci::AuthenticationRequirements::NO_BONDING_MITM_PROTECTION); - GetRecord()->SetRequiresMitmProtection( - local_authentication_requirements_ == - hci::AuthenticationRequirements::DEDICATED_BONDING_MITM_PROTECTION || - local_authentication_requirements_ == - hci::AuthenticationRequirements::GENERAL_BONDING_MITM_PROTECTION || - local_authentication_requirements_ == - hci::AuthenticationRequirements::NO_BONDING_MITM_PROTECTION); - // TODO(optedoblivion): check for HID device (CoD) and if HID don't make temporary - GetRecord()->SetIsTemporary( - local_authentication_requirements_ == hci::AuthenticationRequirements::NO_BONDING || - local_authentication_requirements_ == - hci::AuthenticationRequirements::NO_BONDING_MITM_PROTECTION); - break; - case hci::AuthenticationRequirements::NO_BONDING_MITM_PROTECTION: - GetRecord()->SetIsEncryptionRequired( - local_authentication_requirements_ != hci::AuthenticationRequirements::NO_BONDING || - local_authentication_requirements_ != - hci::AuthenticationRequirements::NO_BONDING_MITM_PROTECTION); - GetRecord()->SetRequiresMitmProtection(true); - GetRecord()->SetIsTemporary( - local_authentication_requirements_ == hci::AuthenticationRequirements::NO_BONDING || - local_authentication_requirements_ == - hci::AuthenticationRequirements::NO_BONDING_MITM_PROTECTION); - break; - case hci::AuthenticationRequirements::DEDICATED_BONDING: - GetRecord()->SetIsEncryptionRequired(true); - GetRecord()->SetRequiresMitmProtection( - local_authentication_requirements_ == - hci::AuthenticationRequirements::DEDICATED_BONDING_MITM_PROTECTION || - local_authentication_requirements_ == - hci::AuthenticationRequirements::GENERAL_BONDING_MITM_PROTECTION || - local_authentication_requirements_ == - hci::AuthenticationRequirements::NO_BONDING_MITM_PROTECTION); - break; - case hci::AuthenticationRequirements::DEDICATED_BONDING_MITM_PROTECTION: - GetRecord()->SetIsEncryptionRequired(true); - GetRecord()->SetRequiresMitmProtection(true); - break; - case hci::AuthenticationRequirements::GENERAL_BONDING: - GetRecord()->SetIsEncryptionRequired(true); - GetRecord()->SetRequiresMitmProtection( - local_authentication_requirements_ == - hci::AuthenticationRequirements::DEDICATED_BONDING_MITM_PROTECTION || - local_authentication_requirements_ == - hci::AuthenticationRequirements::GENERAL_BONDING_MITM_PROTECTION || - local_authentication_requirements_ == - hci::AuthenticationRequirements::NO_BONDING_MITM_PROTECTION); - break; - case hci::AuthenticationRequirements::GENERAL_BONDING_MITM_PROTECTION: - GetRecord()->SetIsEncryptionRequired(true); - GetRecord()->SetRequiresMitmProtection(true); - break; - default: - GetRecord()->SetIsEncryptionRequired(true); - GetRecord()->SetRequiresMitmProtection(true); - break; - } - - has_gotten_io_cap_response_ = true; - if (user_confirmation_request_) { - this->OnReceive(*user_confirmation_request_); - } -} - -void ClassicPairingHandler::OnReceive(hci::SimplePairingCompleteView packet) { - log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()"); - log::info("Received: {}", hci::EventCodeText(packet.GetEventCode())); - log::assert_that(GetRecord()->GetPseudoAddress()->GetAddress() == packet.GetBdAddr(), - "Address mismatch"); - last_status_ = packet.GetStatus(); - if (last_status_ != hci::ErrorCode::SUCCESS) { - log::info("Failed SimplePairingComplete: {}", hci::ErrorCodeText(last_status_)); - // Cancel here since we won't get LinkKeyNotification - Cancel(); - } -} - -void ClassicPairingHandler::OnReceive(hci::ReturnLinkKeysView packet) { - log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()"); - log::info("Received: {}", hci::EventCodeText(packet.GetEventCode())); -} - -void ClassicPairingHandler::OnReceive(hci::EncryptionChangeView packet) { - log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()"); - log::info("Received: {}", hci::EventCodeText(packet.GetEventCode())); -} - -void ClassicPairingHandler::OnReceive(hci::EncryptionKeyRefreshCompleteView packet) { - log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()"); - log::info("Received: {}", hci::EventCodeText(packet.GetEventCode())); -} - -void ClassicPairingHandler::OnReceive(hci::RemoteOobDataRequestView packet) { - log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()"); - log::info("Received: {}", hci::EventCodeText(packet.GetEventCode())); - log::assert_that(GetRecord()->GetPseudoAddress()->GetAddress() == packet.GetBdAddr(), - "Address mismatch"); - - // Corev5.2 V2PF - switch (remote_oob_present_) { - case hci::OobDataPresent::NOT_PRESENT: - log::warn("Missing remote OOB data"); - GetChannel()->SendCommand(hci::RemoteOobDataRequestNegativeReplyBuilder::Create( - GetRecord()->GetPseudoAddress()->GetAddress())); - break; - case hci::OobDataPresent::P_192_PRESENT: - log::info("P192 Present"); - // TODO(optedoblivion): Figure this out and remove - secure_connections_enabled_ = false; - if (secure_connections_enabled_) { - GetChannel()->SendCommand(hci::RemoteOobExtendedDataRequestReplyBuilder::Create( - GetRecord()->GetPseudoAddress()->GetAddress(), this->remote_p192_oob_data_.GetC(), - this->remote_p192_oob_data_.GetR(), this->remote_p256_oob_data_.GetC(), - this->remote_p256_oob_data_.GetR())); - } else { - GetChannel()->SendCommand(hci::RemoteOobDataRequestReplyBuilder::Create( - GetRecord()->GetPseudoAddress()->GetAddress(), this->remote_p192_oob_data_.GetC(), - this->remote_p192_oob_data_.GetR())); - } - break; - case hci::OobDataPresent::P_256_PRESENT: - log::info("P256 Present"); - GetChannel()->SendCommand(hci::RemoteOobExtendedDataRequestReplyBuilder::Create( - GetRecord()->GetPseudoAddress()->GetAddress(), this->remote_p192_oob_data_.GetC(), - this->remote_p192_oob_data_.GetR(), this->remote_p256_oob_data_.GetC(), - this->remote_p256_oob_data_.GetR())); - break; - case hci::OobDataPresent::P_192_AND_256_PRESENT: - log::info("P192 and P256 Present"); - GetChannel()->SendCommand(hci::RemoteOobExtendedDataRequestReplyBuilder::Create( - GetRecord()->GetPseudoAddress()->GetAddress(), this->remote_p192_oob_data_.GetC(), - this->remote_p192_oob_data_.GetR(), this->remote_p256_oob_data_.GetC(), - this->remote_p256_oob_data_.GetR())); - break; - } -} - -void ClassicPairingHandler::OnReceive(hci::UserPasskeyNotificationView packet) { - log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()"); - log::info("Received: {}", hci::EventCodeText(packet.GetEventCode())); - log::assert_that(GetRecord()->GetPseudoAddress()->GetAddress() == packet.GetBdAddr(), - "Address mismatch"); - NotifyUiDisplayPasskey(packet.GetPasskey()); -} - -void ClassicPairingHandler::OnReceive(hci::KeypressNotificationView packet) { - log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()"); - log::info("Received: {}", hci::EventCodeText(packet.GetEventCode())); - log::info("Notification Type: {}", - hci::KeypressNotificationTypeText(packet.GetNotificationType())); - switch (packet.GetNotificationType()) { - case hci::KeypressNotificationType::ENTRY_STARTED: - // Tell the UI to highlight the first digit - break; - case hci::KeypressNotificationType::DIGIT_ENTERED: - // Tell the UI to move one digit to the right - break; - case hci::KeypressNotificationType::DIGIT_ERASED: - // Tell the UI to move back one digit - break; - case hci::KeypressNotificationType::CLEARED: - // Tell the UI to highlight the first digit again - break; - case hci::KeypressNotificationType::ENTRY_COMPLETED: - // Tell the UI to hide the dialog - break; - } -} - -/** - * Here we decide what type of pairing authentication method we will use - * - * The table is on pg 2133 of the Core v5.1 spec. - */ - -void ClassicPairingHandler::OnReceive(hci::UserConfirmationRequestView packet) { - // Ensure we have io cap response otherwise checks will be wrong if it comes late - // Ensure we have the name response otherwise we cannot show a name for the device to the user - if (!has_gotten_io_cap_response_ || !has_gotten_name_response_) { - user_confirmation_request_ = std::make_optional<hci::UserConfirmationRequestView>(packet); - return; - } - log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()"); - log::info("Received: {}", hci::EventCodeText(packet.GetEventCode())); - log::assert_that(GetRecord()->GetPseudoAddress()->GetAddress() == packet.GetBdAddr(), - "Address mismatch"); - // if locally_initialized, use default, otherwise us remote io caps - hci::IoCapability initiator_io_capability = - (locally_initiated_) ? local_io_capability_ : remote_io_capability_; - hci::IoCapability responder_io_capability = - (!locally_initiated_) ? local_io_capability_ : remote_io_capability_; - switch (initiator_io_capability) { - case hci::IoCapability::DISPLAY_ONLY: - switch (responder_io_capability) { - case hci::IoCapability::DISPLAY_ONLY: - // NumericComparison, Both auto confirm - log::info("Numeric Comparison: A and B auto confirm"); - if (!GetRecord()->RequiresMitmProtection()) { - GetChannel()->SendCommand(hci::UserConfirmationRequestReplyBuilder::Create( - GetRecord()->GetPseudoAddress()->GetAddress())); - // NOTE(optedoblivion) BTA needs a callback for when auto accepting JustWorks - // If we auto accept from the ClassicPairingHandler in GD then we won't - // get a callback to this shim function. - // We will have to call it anyway until we eliminate the need - // TODO(optedoblivion): REMOVE WHEN SHIM LEAVES - NotifyUiDisplayYesNo(); - } else { - GetChannel()->SendCommand(hci::UserConfirmationRequestNegativeReplyBuilder::Create( - GetRecord()->GetPseudoAddress()->GetAddress())); - } - // Unauthenticated - GetRecord()->SetAuthenticated(false); - break; - case hci::IoCapability::DISPLAY_YES_NO: - // NumericComparison, Initiator auto confirm, Responder display - if (!GetRecord()->RequiresMitmProtection()) { - GetChannel()->SendCommand(hci::UserConfirmationRequestReplyBuilder::Create( - GetRecord()->GetPseudoAddress()->GetAddress())); - // TODO(optedoblivion): REMOVE WHEN SHIM LEAVES - NotifyUiDisplayYesNo(); - } else { - GetChannel()->SendCommand(hci::UserConfirmationRequestNegativeReplyBuilder::Create( - GetRecord()->GetPseudoAddress()->GetAddress())); - } - log::info("Numeric Comparison: A auto confirm"); - // Unauthenticated - GetRecord()->SetAuthenticated(true); - break; - case hci::IoCapability::KEYBOARD_ONLY: - // PassKey Entry, Initiator display, Responder input - NotifyUiDisplayPasskey(packet.GetNumericValue()); - log::info("Passkey Entry: A display, B input"); - // Authenticated - GetRecord()->SetAuthenticated(true); - break; - case hci::IoCapability::NO_INPUT_NO_OUTPUT: - // NumericComparison, Both auto confirm - log::info("Numeric Comparison: A and B auto confirm"); - if (!GetRecord()->RequiresMitmProtection()) { - GetChannel()->SendCommand(hci::UserConfirmationRequestReplyBuilder::Create( - GetRecord()->GetPseudoAddress()->GetAddress())); - // TODO(optedoblivion): REMOVE WHEN SHIM LEAVES - NotifyUiDisplayYesNo(); - } else { - GetChannel()->SendCommand(hci::UserConfirmationRequestNegativeReplyBuilder::Create( - GetRecord()->GetPseudoAddress()->GetAddress())); - } - // Unauthenticated - GetRecord()->SetAuthenticated(true); - break; - } - break; - case hci::IoCapability::DISPLAY_YES_NO: - switch (responder_io_capability) { - case hci::IoCapability::DISPLAY_ONLY: - // NumericComparison, Initiator display, Responder auto confirm - log::info("Numeric Comparison: A DisplayYesNo, B auto confirm"); - NotifyUiDisplayYesNo(packet.GetNumericValue()); - // Unauthenticated - GetRecord()->SetAuthenticated(true); - break; - case hci::IoCapability::DISPLAY_YES_NO: - // NumericComparison Both Display, Both confirm - log::info("Numeric Comparison: A and B DisplayYesNo"); - NotifyUiDisplayYesNo(packet.GetNumericValue()); - // Authenticated - GetRecord()->SetAuthenticated(true); - break; - case hci::IoCapability::KEYBOARD_ONLY: - // PassKey Entry, Initiator display, Responder input - NotifyUiDisplayPasskey(packet.GetNumericValue()); - log::info("Passkey Entry: A display, B input"); - // Authenticated - GetRecord()->SetAuthenticated(true); - break; - case hci::IoCapability::NO_INPUT_NO_OUTPUT: - // NumericComparison, auto confirm Responder, Yes/No confirm Initiator. Don't show - // confirmation value - log::info("Numeric Comparison: A DisplayYesNo, B auto confirm, no show value"); - NotifyUiDisplayYesNo(); - // Unauthenticated - GetRecord()->SetAuthenticated(true); - break; - } - break; - case hci::IoCapability::KEYBOARD_ONLY: - switch (responder_io_capability) { - case hci::IoCapability::DISPLAY_ONLY: - // PassKey Entry, Responder display, Initiator input - NotifyUiDisplayPasskeyInput(); - log::info("Passkey Entry: A input, B display"); - // Authenticated - GetRecord()->SetAuthenticated(true); - break; - case hci::IoCapability::DISPLAY_YES_NO: - // PassKey Entry, Responder display, Initiator input - NotifyUiDisplayPasskeyInput(); - log::info("Passkey Entry: A input, B display"); - // Authenticated - GetRecord()->SetAuthenticated(true); - break; - case hci::IoCapability::KEYBOARD_ONLY: - // PassKey Entry, both input - NotifyUiDisplayPasskeyInput(); - log::info("Passkey Entry: A input, B input"); - // Authenticated - GetRecord()->SetAuthenticated(true); - break; - case hci::IoCapability::NO_INPUT_NO_OUTPUT: - // NumericComparison, both auto confirm - log::info("Numeric Comparison: A and B auto confirm"); - if (!GetRecord()->RequiresMitmProtection()) { - GetChannel()->SendCommand(hci::UserConfirmationRequestReplyBuilder::Create( - GetRecord()->GetPseudoAddress()->GetAddress())); - // TODO(optedoblivion): REMOVE WHEN SHIM LEAVES - NotifyUiDisplayYesNo(); - } else { - GetChannel()->SendCommand(hci::UserConfirmationRequestNegativeReplyBuilder::Create( - GetRecord()->GetPseudoAddress()->GetAddress())); - } - // Unauthenticated - GetRecord()->SetAuthenticated(false); - break; - } - break; - case hci::IoCapability::NO_INPUT_NO_OUTPUT: - switch (responder_io_capability) { - case hci::IoCapability::DISPLAY_ONLY: - // NumericComparison, both auto confirm - log::info("Numeric Comparison: A and B auto confirm"); - if (!GetRecord()->RequiresMitmProtection()) { - GetChannel()->SendCommand(hci::UserConfirmationRequestReplyBuilder::Create( - GetRecord()->GetPseudoAddress()->GetAddress())); - // TODO(optedoblivion): REMOVE WHEN SHIM LEAVES - NotifyUiDisplayYesNo(); - } else { - GetChannel()->SendCommand(hci::UserConfirmationRequestNegativeReplyBuilder::Create( - GetRecord()->GetPseudoAddress()->GetAddress())); - } - // Unauthenticated - GetRecord()->SetAuthenticated(false); - break; - case hci::IoCapability::DISPLAY_YES_NO: - // NumericComparison, Initiator auto confirm, Responder Yes/No confirm, no show conf val - log::info("Numeric Comparison: A auto confirm"); - if (!GetRecord()->RequiresMitmProtection()) { - GetChannel()->SendCommand(hci::UserConfirmationRequestReplyBuilder::Create( - GetRecord()->GetPseudoAddress()->GetAddress())); - // TODO(optedoblivion): REMOVE WHEN SHIM LEAVES - NotifyUiDisplayYesNo(); - } else { - GetChannel()->SendCommand(hci::UserConfirmationRequestNegativeReplyBuilder::Create( - GetRecord()->GetPseudoAddress()->GetAddress())); - } - // Unauthenticated - GetRecord()->SetAuthenticated(false); - break; - case hci::IoCapability::KEYBOARD_ONLY: - // NumericComparison, both auto confirm - log::info("Numeric Comparison: A and B auto confirm"); - if (!GetRecord()->RequiresMitmProtection()) { - GetChannel()->SendCommand(hci::UserConfirmationRequestReplyBuilder::Create( - GetRecord()->GetPseudoAddress()->GetAddress())); - // TODO(optedoblivion): REMOVE WHEN SHIM LEAVES - NotifyUiDisplayYesNo(); - } else { - GetChannel()->SendCommand(hci::UserConfirmationRequestNegativeReplyBuilder::Create( - GetRecord()->GetPseudoAddress()->GetAddress())); - } - // Unauthenticated - GetRecord()->SetAuthenticated(false); - break; - case hci::IoCapability::NO_INPUT_NO_OUTPUT: - // NumericComparison, both auto confirm - log::info("Numeric Comparison: A and B auto confirm"); - if (!GetRecord()->RequiresMitmProtection()) { - GetChannel()->SendCommand(hci::UserConfirmationRequestReplyBuilder::Create( - GetRecord()->GetPseudoAddress()->GetAddress())); - // TODO(optedoblivion): REMOVE WHEN SHIM LEAVES - NotifyUiDisplayYesNo(); - } else { - GetChannel()->SendCommand(hci::UserConfirmationRequestNegativeReplyBuilder::Create( - GetRecord()->GetPseudoAddress()->GetAddress())); - } - // Unauthenticated - GetRecord()->SetAuthenticated(false); - break; - } - break; - } -} - -void ClassicPairingHandler::OnReceive(hci::UserPasskeyRequestView packet) { - log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()"); - log::assert_that(GetRecord()->GetPseudoAddress()->GetAddress() == packet.GetBdAddr(), - "Address mismatch"); -} - -void ClassicPairingHandler::OnUserInput(bool user_input) { - if (user_input) { - UserClickedYes(); - } else { - UserClickedNo(); - } -} - -void ClassicPairingHandler::UserClickedYes() { - GetChannel()->SendCommand(hci::UserConfirmationRequestReplyBuilder::Create( - GetRecord()->GetPseudoAddress()->GetAddress())); -} - -void ClassicPairingHandler::UserClickedNo() { - GetChannel()->SendCommand(hci::UserConfirmationRequestNegativeReplyBuilder::Create( - GetRecord()->GetPseudoAddress()->GetAddress())); -} - -void ClassicPairingHandler::OnPasskeyInput(uint32_t passkey) { passkey_ = passkey; } - -} // namespace pairing -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/pairing/classic_pairing_handler.h b/system/gd/security/pairing/classic_pairing_handler.h deleted file mode 100644 index f3af782c50..0000000000 --- a/system/gd/security/pairing/classic_pairing_handler.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * - * Copyright 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License") override; - * 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. - * - */ -#pragma once - -#include <utility> - -#include "common/callback.h" -#include "security/initial_informations.h" -#include "security/pairing/pairing_handler.h" - -namespace bluetooth { -namespace security { - -class ISecurityManagerListener; - -namespace pairing { - -class ClassicPairingHandler : public PairingHandler { -public: - ClassicPairingHandler( - channel::SecurityManagerChannel* security_manager_channel, - std::shared_ptr<record::SecurityRecord> record, os::Handler* security_handler, - common::OnceCallback<void(hci::Address, PairingResultOrFailure)> complete_callback, - UI* user_interface, os::Handler* user_interface_handler, std::string device_name, - neighbor::NameDbModule* name_db_module) - : PairingHandler(security_manager_channel, std::move(record), name_db_module), - security_handler_(security_handler), - remote_io_capability_(hci::IoCapability::DISPLAY_YES_NO), - remote_oob_present_(hci::OobDataPresent::NOT_PRESENT), - remote_authentication_requirements_( - hci::AuthenticationRequirements::DEDICATED_BONDING_MITM_PROTECTION), - local_io_capability_(hci::IoCapability::DISPLAY_YES_NO), - local_oob_present_(hci::OobDataPresent::NOT_PRESENT), - local_authentication_requirements_( - hci::AuthenticationRequirements::DEDICATED_BONDING_MITM_PROTECTION), - complete_callback_(std::move(complete_callback)), - user_interface_(user_interface), - user_interface_handler_(user_interface_handler), - device_name_(std::move(device_name)) {} - - ~ClassicPairingHandler() = default; - - void Initiate(bool locally_initiated, hci::IoCapability io_capability, - hci::AuthenticationRequirements auth_requirements, OobData remote_p192_oob_data, - OobData remote_p256_oob_data) override; - void Cancel() override; - - void OnReceive(hci::ChangeConnectionLinkKeyCompleteView packet) override; - void OnReceive(hci::CentralLinkKeyCompleteView packet) override; - void OnReceive(hci::PinCodeRequestView packet) override; - void OnReceive(hci::LinkKeyRequestView packet) override; - void OnReceive(hci::LinkKeyNotificationView packet) override; - void OnReceive(hci::IoCapabilityRequestView packet) override; - void OnReceive(hci::IoCapabilityResponseView packet) override; - void OnReceive(hci::SimplePairingCompleteView packet) override; - void OnReceive(hci::ReturnLinkKeysView packet) override; - void OnReceive(hci::EncryptionChangeView packet) override; - void OnReceive(hci::EncryptionKeyRefreshCompleteView packet) override; - void OnReceive(hci::RemoteOobDataRequestView packet) override; - void OnReceive(hci::UserPasskeyNotificationView packet) override; - void OnReceive(hci::KeypressNotificationView packet) override; - void OnReceive(hci::UserConfirmationRequestView packet) override; - void OnReceive(hci::UserPasskeyRequestView packet) override; - - void OnPairingPromptAccepted(const bluetooth::hci::AddressWithType& address, - bool confirmed) override; - void OnConfirmYesNo(const bluetooth::hci::AddressWithType& address, bool confirmed) override; - void OnPasskeyEntry(const bluetooth::hci::AddressWithType& address, uint32_t passkey) override; - void OnPinEntry(const bluetooth::hci::AddressWithType& address, - std::vector<uint8_t> pin) override; - - void OnNameRequestComplete(hci::Address address, bool success); - -private: - void OnUserInput(bool user_input); - void OnPasskeyInput(uint32_t passkey); - void NotifyUiDisplayYesNo(uint32_t numeric_value); - void NotifyUiDisplayYesNo(); - void NotifyUiDisplayPasskey(uint32_t passkey); - void NotifyUiDisplayPasskeyInput(); - void NotifyUiDisplayPinCodeInput(); - void NotifyUiDisplayCancel(); - void UserClickedYes(); - void UserClickedNo(); - - os::Handler* security_handler_ __attribute__((unused)); - hci::IoCapability remote_io_capability_; - hci::OobDataPresent remote_oob_present_ __attribute__((unused)); - hci::AuthenticationRequirements remote_authentication_requirements_ __attribute__((unused)); - hci::IoCapability local_io_capability_; - hci::OobDataPresent local_oob_present_ __attribute__((unused)); - hci::AuthenticationRequirements local_authentication_requirements_ __attribute__((unused)); - OobData remote_p192_oob_data_; - OobData remote_p256_oob_data_; - common::OnceCallback<void(hci::Address, PairingResultOrFailure)> complete_callback_; - UI* user_interface_; - os::Handler* user_interface_handler_; - std::string device_name_; - bool is_cancelled_ = false; - - bool has_gotten_io_cap_response_ = false; - bool has_gotten_name_response_ = false; - std::optional<hci::UserConfirmationRequestView> user_confirmation_request_ = std::nullopt; - std::optional<hci::LinkKeyNotificationView> link_key_notification_ = std::nullopt; - - hci::ErrorCode last_status_ = hci::ErrorCode::UNKNOWN_HCI_COMMAND; - bool locally_initiated_ = false; - uint32_t passkey_ = 0; - bool already_link_key_replied_ = false; - bool secure_connections_enabled_ = true; - bool is_legacy_pin_code_ = false; -}; - -} // namespace pairing -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/pairing/classic_pairing_handler_unittest.cc b/system/gd/security/pairing/classic_pairing_handler_unittest.cc deleted file mode 100644 index d61c20eb62..0000000000 --- a/system/gd/security/pairing/classic_pairing_handler_unittest.cc +++ /dev/null @@ -1,812 +0,0 @@ -/* - * - * Copyright 2019 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 "security/pairing/classic_pairing_handler.h" - -#include <bluetooth/log.h> -#include <gtest/gtest.h> - -#include <memory> -#include <utility> - -#include "hci/hci_packets.h" -#include "packet/raw_builder.h" -#include "security/channel/security_manager_channel.h" -#include "security/initial_informations.h" -#include "security/test/fake_hci_layer.h" -#include "security/test/fake_name_db.h" -#include "security/test/fake_security_interface.h" - -namespace bluetooth { -namespace security { -namespace pairing { -namespace { - -using bluetooth::security::channel::SecurityManagerChannel; -using hci::Address; -using hci::AuthenticationRequirements; -using hci::CommandCompleteBuilder; -using hci::IoCapabilityRequestReplyBuilder; -using hci::IoCapabilityRequestView; -using hci::OobDataPresent; -using hci::OpCode; -using os::Handler; -using os::Thread; -using packet::RawBuilder; - -class FakeSecurityManagerChannel : public channel::SecurityManagerChannel { -public: - FakeSecurityManagerChannel(os::Handler* handler, hci::HciLayer* hci_layer) - : channel::SecurityManagerChannel(handler, hci_layer) {} - ~FakeSecurityManagerChannel() {} - - void OnLinkConnected(std::unique_ptr<l2cap::classic::LinkSecurityInterface> link) override { - log::error("CALLED"); - } - - void OnLinkDisconnected(hci::Address address) override { log::error("CALLED"); } - - void OnEncryptionChange(hci::Address address, bool encrypted) override { log::error("CALLED"); } - - void OnAuthenticationComplete(hci::ErrorCode hci_status, hci::Address remote) override { - log::error("CALLED"); - } -}; - -class TestUI : public UI { -public: - ~TestUI() = default; - void DisplayPairingPrompt(const hci::AddressWithType& address, std::string name) override {} - void Cancel(const hci::AddressWithType& address) override {} - void DisplayConfirmValue(ConfirmationData data) override {} - void DisplayYesNoDialog(ConfirmationData data) override {} - void DisplayEnterPasskeyDialog(ConfirmationData data) override {} - void DisplayPasskey(ConfirmationData data) override {} - void DisplayEnterPinDialog(ConfirmationData data) override {} -}; - -class SecurityManagerChannelCallback : public channel::ISecurityManagerChannelListener { -public: - explicit SecurityManagerChannelCallback(pairing::ClassicPairingHandler* pairing_handler) - : pairing_handler_(pairing_handler) {} - void OnHciEventReceived(hci::EventView packet) override { - auto event = hci::EventView::Create(packet); - log::assert_that(event.IsValid(), "Received invalid packet"); - const hci::EventCode code = event.GetEventCode(); - switch (code) { - case hci::EventCode::PIN_CODE_REQUEST: - pairing_handler_->OnReceive(hci::PinCodeRequestView::Create(event)); - break; - case hci::EventCode::LINK_KEY_REQUEST: - pairing_handler_->OnReceive(hci::LinkKeyRequestView::Create(event)); - break; - case hci::EventCode::LINK_KEY_NOTIFICATION: - pairing_handler_->OnReceive(hci::LinkKeyNotificationView::Create(event)); - break; - case hci::EventCode::IO_CAPABILITY_REQUEST: - pairing_handler_->OnReceive(hci::IoCapabilityRequestView::Create(event)); - break; - case hci::EventCode::IO_CAPABILITY_RESPONSE: - pairing_handler_->OnReceive(hci::IoCapabilityResponseView::Create(event)); - break; - case hci::EventCode::SIMPLE_PAIRING_COMPLETE: - pairing_handler_->OnReceive(hci::SimplePairingCompleteView::Create(event)); - break; - case hci::EventCode::RETURN_LINK_KEYS: - pairing_handler_->OnReceive(hci::ReturnLinkKeysView::Create(event)); - break; - case hci::EventCode::REMOTE_OOB_DATA_REQUEST: - pairing_handler_->OnReceive(hci::RemoteOobDataRequestView::Create(event)); - break; - case hci::EventCode::USER_PASSKEY_NOTIFICATION: - pairing_handler_->OnReceive(hci::UserPasskeyNotificationView::Create(event)); - break; - case hci::EventCode::KEYPRESS_NOTIFICATION: - pairing_handler_->OnReceive(hci::KeypressNotificationView::Create(event)); - break; - case hci::EventCode::USER_CONFIRMATION_REQUEST: - pairing_handler_->OnReceive(hci::UserConfirmationRequestView::Create(event)); - break; - case hci::EventCode::USER_PASSKEY_REQUEST: - pairing_handler_->OnReceive(hci::UserPasskeyRequestView::Create(event)); - break; - default: - log::fatal("Cannot handle received packet: {}", hci::EventCodeText(code)); - break; - } - } - - void OnConnectionClosed(hci::Address address) override { log::info("Called"); } - -private: - pairing::ClassicPairingHandler* pairing_handler_ = nullptr; -}; - -bool expect_success_ = true; - -static void pairing_complete_callback(bluetooth::hci::Address address, - PairingResultOrFailure status) { - if (expect_success_) { - ASSERT_TRUE(std::holds_alternative<PairingResult>(status)); - } else { - ASSERT_FALSE(std::holds_alternative<PairingResult>(status)); - } -} - -class ClassicPairingHandlerTest : public ::testing::Test { -protected: - void SetUp() override { - expect_success_ = true; - hci_layer_ = new FakeHciLayer(); - name_db_module_ = new FakeNameDbModule(); - fake_registry_.InjectTestModule(&FakeHciLayer::Factory, hci_layer_); - fake_registry_.InjectTestModule(&neighbor::NameDbModule::Factory, name_db_module_); - handler_ = fake_registry_.GetTestModuleHandler(&FakeHciLayer::Factory); - channel_ = new FakeSecurityManagerChannel(handler_, hci_layer_); - security_record_ = std::make_shared<record::SecurityRecord>(device_); - user_interface_ = new TestUI(); - user_interface_handler_ = handler_; - pairing_handler_ = new pairing::ClassicPairingHandler( - channel_, security_record_, handler_, common::Bind(&pairing_complete_callback), - user_interface_, user_interface_handler_, "Fake name", name_db_module_); - channel_callback_ = new SecurityManagerChannelCallback(pairing_handler_); - channel_->SetChannelListener(channel_callback_); - security_interface_ = new FakeSecurityInterface(handler_, channel_); - channel_->SetSecurityInterface(security_interface_); - } - - void TearDown() override { - channel_->SetChannelListener(nullptr); - synchronize(); - fake_registry_.StopAll(); - delete user_interface_; - delete pairing_handler_; - delete channel_; - delete channel_callback_; - delete security_interface_; - } - - void synchronize() { - fake_registry_.SynchronizeModuleHandler(&FakeHciLayer::Factory, std::chrono::milliseconds(20)); - fake_registry_.SynchronizeModuleHandler(&FakeNameDbModule::Factory, - std::chrono::milliseconds(20)); - } - - void ReceiveLinkKeyRequest(hci::AddressWithType device) { - hci_layer_->IncomingEvent(hci::LinkKeyRequestBuilder::Create(device.GetAddress())); - synchronize(); - } - - void ReceiveIoCapabilityRequest(hci::AddressWithType device) { - hci_layer_->IncomingEvent(hci::IoCapabilityRequestBuilder::Create(device.GetAddress())); - synchronize(); - } - - void ReceiveIoCapabilityResponse(hci::AddressWithType device, hci::IoCapability io_cap, - hci::OobDataPresent oob_present, - hci::AuthenticationRequirements auth_reqs) { - hci_layer_->IncomingEvent(hci::IoCapabilityResponseBuilder::Create(device.GetAddress(), io_cap, - oob_present, auth_reqs)); - synchronize(); - } - - void ReceiveOobDataRequest(hci::AddressWithType device) { - hci_layer_->IncomingEvent(hci::RemoteOobDataRequestBuilder::Create(device.GetAddress())); - synchronize(); - } - - void ReceiveUserConfirmationRequest(hci::AddressWithType device, uint32_t numeric_value) { - hci_layer_->IncomingEvent( - hci::UserConfirmationRequestBuilder::Create(device.GetAddress(), numeric_value)); - synchronize(); - } - - void ReceiveSimplePairingComplete(hci::ErrorCode status, hci::AddressWithType device) { - hci_layer_->IncomingEvent( - hci::SimplePairingCompleteBuilder::Create(status, device.GetAddress())); - synchronize(); - } - - void ReceiveLinkKeyNotification(hci::AddressWithType device, std::array<uint8_t, 16> link_key, - hci::KeyType key_type) { - hci_layer_->IncomingEvent( - hci::LinkKeyNotificationBuilder::Create(device.GetAddress(), link_key, key_type)); - synchronize(); - } - - TestModuleRegistry fake_registry_; - Thread& thread_ = fake_registry_.GetTestThread(); - Handler* handler_ = nullptr; - FakeHciLayer* hci_layer_ = nullptr; - hci::AddressWithType device_; - SecurityManagerChannelCallback* channel_callback_ = nullptr; - channel::SecurityManagerChannel* channel_ = nullptr; - pairing::ClassicPairingHandler* pairing_handler_ = nullptr; - std::shared_ptr<record::SecurityRecord> security_record_ = nullptr; - UI* user_interface_; - os::Handler* user_interface_handler_; - l2cap::classic::SecurityInterface* security_interface_ = nullptr; - FakeNameDbModule* name_db_module_ = nullptr; -}; - -// Security Manager Boot Sequence (Required for SSP, these are already set at boot time) -// - WriteSimplePairingMode -// - WriteSecureConnectionsHostSupport -// - WriteAuthenticatedPayloadTimeout - -/*** Locally initiated ***/ -// Security Pairing Sequence (JustWorks) -// -> *Establish L2CAP connection* -// -> AuthenticationRequested (L2CAP handles this) -// <- LinkKeyRequest // This is entry point for remote initiated -// -> LinkKeyRequestNegativeReply -// <- IoCapabilityRequest -// -> IoCapabilityRequestReply -// <- IoCapabilityResponse -// <- UserConfirmationRequest -// -> UserConfirmationRequestReply (auto) -// <- SimplePairingComplete -// <- LinkKeyNotification -// <- AuthenticationComplete -// -> SetConnectionEncryption -// <- EncryptionChange -// -> L2capConnectionResponse (if triggered by L2cap connection request) - -hci::SecurityCommandView GetLastCommand(FakeHciLayer* hci_layer) { - auto last_command = std::move(hci_layer->GetLastCommand()->command); - auto command_packet = GetPacketView(std::move(last_command)); - auto command_packet_view = hci::CommandView::Create(command_packet); - auto security_command_view = hci::SecurityCommandView::Create(command_packet_view); - if (!security_command_view.IsValid()) { - log::error("Invalid security command received"); - } - return security_command_view; -} - -TEST_F(ClassicPairingHandlerTest, setup_teardown) {} - -/*** JustWorks (Numeric Comparison w/ no UI) ***/ -// display_only + display_only is JustWorks no confirmation -// Needs dialog as per security a bug unless pairing is temporary -TEST_F(ClassicPairingHandlerTest, locally_initiatied_display_only_display_only_temp) { - hci::IoCapability injected_io_capability = hci::IoCapability::DISPLAY_ONLY; - hci::AuthenticationRequirements injected_authentication_requirements = - hci::AuthenticationRequirements::NO_BONDING; - pairing_handler_->Initiate(true, injected_io_capability, injected_authentication_requirements, - pairing::OobData(), pairing::OobData()); - ReceiveLinkKeyRequest(device_); - auto security_command_view = GetLastCommand(hci_layer_); - auto link_key_neg_reply = hci::LinkKeyRequestNegativeReplyView::Create(security_command_view); - ASSERT_TRUE(link_key_neg_reply.IsValid()); - ASSERT_EQ(OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, link_key_neg_reply.GetOpCode()); - ReceiveIoCapabilityRequest(device_); - security_command_view = GetLastCommand(hci_layer_); - ASSERT_EQ(OpCode::IO_CAPABILITY_REQUEST_REPLY, security_command_view.GetOpCode()); - auto io_cap_request_reply = hci::IoCapabilityRequestReplyView::Create(security_command_view); - ASSERT_TRUE(io_cap_request_reply.IsValid()); - ASSERT_EQ(injected_io_capability, io_cap_request_reply.GetIoCapability()); - ASSERT_EQ(hci::OobDataPresent::NOT_PRESENT, io_cap_request_reply.GetOobPresent()); - ASSERT_EQ(injected_authentication_requirements, - io_cap_request_reply.GetAuthenticationRequirements()); - ReceiveIoCapabilityResponse(device_, hci::IoCapability::DISPLAY_ONLY, - hci::OobDataPresent::NOT_PRESENT, - hci::AuthenticationRequirements::NO_BONDING); - uint32_t numeric_value = 0x123; - ReceiveUserConfirmationRequest(device_, numeric_value); - security_command_view = GetLastCommand(hci_layer_); - ASSERT_EQ(OpCode::USER_CONFIRMATION_REQUEST_REPLY, security_command_view.GetOpCode()); - auto user_conf_request_reply = - hci::UserConfirmationRequestReplyView::Create(security_command_view); - ASSERT_TRUE(user_conf_request_reply.IsValid()); - ReceiveSimplePairingComplete(hci::ErrorCode::SUCCESS, device_); - std::array<uint8_t, 16> link_key = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5}; - hci::KeyType key_type = hci::KeyType::DEBUG_COMBINATION; - ReceiveLinkKeyNotification(device_, link_key, key_type); - ASSERT_EQ(link_key, security_record_->GetLinkKey()); - ASSERT_EQ(key_type, security_record_->GetKeyType()); - ASSERT_FALSE(security_record_->IsAuthenticated()); - ASSERT_FALSE(security_record_->RequiresMitmProtection()); -} - -// display_only + display_yes_no is JustWorks no confirmation -// Needs dialog as per security a bug unless pairing is temporary -TEST_F(ClassicPairingHandlerTest, locally_initiatied_display_only_display_yes_no_temp) { - hci::IoCapability injected_io_capability = hci::IoCapability::DISPLAY_ONLY; - hci::AuthenticationRequirements injected_authentication_requirements = - hci::AuthenticationRequirements::NO_BONDING; - pairing_handler_->Initiate(true, injected_io_capability, injected_authentication_requirements, - pairing::OobData(), pairing::OobData()); - ReceiveLinkKeyRequest(device_); - auto security_command_view = GetLastCommand(hci_layer_); - auto link_key_neg_reply = hci::LinkKeyRequestNegativeReplyView::Create(security_command_view); - ASSERT_TRUE(link_key_neg_reply.IsValid()); - ASSERT_EQ(OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, link_key_neg_reply.GetOpCode()); - ReceiveIoCapabilityRequest(device_); - security_command_view = GetLastCommand(hci_layer_); - ASSERT_EQ(OpCode::IO_CAPABILITY_REQUEST_REPLY, security_command_view.GetOpCode()); - auto io_cap_request_reply = hci::IoCapabilityRequestReplyView::Create(security_command_view); - ASSERT_TRUE(io_cap_request_reply.IsValid()); - ASSERT_EQ(injected_io_capability, io_cap_request_reply.GetIoCapability()); - ASSERT_EQ(hci::OobDataPresent::NOT_PRESENT, io_cap_request_reply.GetOobPresent()); - ASSERT_EQ(injected_authentication_requirements, - io_cap_request_reply.GetAuthenticationRequirements()); - ReceiveIoCapabilityResponse(device_, hci::IoCapability::DISPLAY_YES_NO, - hci::OobDataPresent::NOT_PRESENT, - hci::AuthenticationRequirements::NO_BONDING); - uint32_t numeric_value = 0x123; - ReceiveUserConfirmationRequest(device_, numeric_value); - security_command_view = GetLastCommand(hci_layer_); - ASSERT_EQ(OpCode::USER_CONFIRMATION_REQUEST_REPLY, security_command_view.GetOpCode()); - auto user_conf_request_reply = - hci::UserConfirmationRequestReplyView::Create(security_command_view); - ASSERT_TRUE(user_conf_request_reply.IsValid()); - ReceiveSimplePairingComplete(hci::ErrorCode::SUCCESS, device_); - std::array<uint8_t, 16> link_key = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5}; - hci::KeyType key_type = hci::KeyType::DEBUG_COMBINATION; - ReceiveLinkKeyNotification(device_, link_key, key_type); - ASSERT_EQ(link_key, security_record_->GetLinkKey()); - ASSERT_EQ(key_type, security_record_->GetKeyType()); - ASSERT_TRUE(security_record_->IsAuthenticated()); - ASSERT_FALSE(security_record_->RequiresMitmProtection()); -} - -// display_only + no_input_no_output is JustWorks no confirmation -// Needs dialog as per security a bug unless pairing is temporary -TEST_F(ClassicPairingHandlerTest, locally_initiatied_display_only_no_input_no_output_temp) { - hci::IoCapability injected_io_capability = hci::IoCapability::DISPLAY_ONLY; - hci::AuthenticationRequirements injected_authentication_requirements = - hci::AuthenticationRequirements::NO_BONDING; - pairing_handler_->Initiate(true, injected_io_capability, injected_authentication_requirements, - pairing::OobData(), pairing::OobData()); - ReceiveLinkKeyRequest(device_); - auto security_command_view = GetLastCommand(hci_layer_); - auto link_key_neg_reply = hci::LinkKeyRequestNegativeReplyView::Create(security_command_view); - ASSERT_TRUE(link_key_neg_reply.IsValid()); - ASSERT_EQ(OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, link_key_neg_reply.GetOpCode()); - ReceiveIoCapabilityRequest(device_); - security_command_view = GetLastCommand(hci_layer_); - ASSERT_EQ(OpCode::IO_CAPABILITY_REQUEST_REPLY, security_command_view.GetOpCode()); - auto io_cap_request_reply = hci::IoCapabilityRequestReplyView::Create(security_command_view); - ASSERT_TRUE(io_cap_request_reply.IsValid()); - ASSERT_EQ(injected_io_capability, io_cap_request_reply.GetIoCapability()); - ASSERT_EQ(hci::OobDataPresent::NOT_PRESENT, io_cap_request_reply.GetOobPresent()); - ASSERT_EQ(injected_authentication_requirements, - io_cap_request_reply.GetAuthenticationRequirements()); - ReceiveIoCapabilityResponse(device_, hci::IoCapability::NO_INPUT_NO_OUTPUT, - hci::OobDataPresent::NOT_PRESENT, - hci::AuthenticationRequirements::NO_BONDING); - uint32_t numeric_value = 0x123; - ReceiveUserConfirmationRequest(device_, numeric_value); - security_command_view = GetLastCommand(hci_layer_); - ASSERT_EQ(OpCode::USER_CONFIRMATION_REQUEST_REPLY, security_command_view.GetOpCode()); - auto user_conf_request_reply = - hci::UserConfirmationRequestReplyView::Create(security_command_view); - ASSERT_TRUE(user_conf_request_reply.IsValid()); - ReceiveSimplePairingComplete(hci::ErrorCode::SUCCESS, device_); - std::array<uint8_t, 16> link_key = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5}; - hci::KeyType key_type = hci::KeyType::DEBUG_COMBINATION; - ReceiveLinkKeyNotification(device_, link_key, key_type); - ASSERT_EQ(link_key, security_record_->GetLinkKey()); - ASSERT_EQ(key_type, security_record_->GetKeyType()); - ASSERT_TRUE(security_record_->IsAuthenticated()); - ASSERT_FALSE(security_record_->RequiresMitmProtection()); -} - -// keyboard_only + no_input_no_output is JustWorks no confirmation -// Needs dialog as per security a bug unless pairing is temporary -TEST_F(ClassicPairingHandlerTest, locally_initiatied_keyboard_only_no_input_no_output_temp) { - hci::IoCapability injected_io_capability = hci::IoCapability::KEYBOARD_ONLY; - hci::AuthenticationRequirements injected_authentication_requirements = - hci::AuthenticationRequirements::NO_BONDING; - pairing_handler_->Initiate(true, injected_io_capability, injected_authentication_requirements, - pairing::OobData(), pairing::OobData()); - ReceiveLinkKeyRequest(device_); - auto security_command_view = GetLastCommand(hci_layer_); - auto link_key_neg_reply = hci::LinkKeyRequestNegativeReplyView::Create(security_command_view); - ASSERT_TRUE(link_key_neg_reply.IsValid()); - ASSERT_EQ(OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, link_key_neg_reply.GetOpCode()); - ReceiveIoCapabilityRequest(device_); - security_command_view = GetLastCommand(hci_layer_); - ASSERT_EQ(OpCode::IO_CAPABILITY_REQUEST_REPLY, security_command_view.GetOpCode()); - auto io_cap_request_reply = hci::IoCapabilityRequestReplyView::Create(security_command_view); - ASSERT_TRUE(io_cap_request_reply.IsValid()); - ASSERT_EQ(injected_io_capability, io_cap_request_reply.GetIoCapability()); - ASSERT_EQ(hci::OobDataPresent::NOT_PRESENT, io_cap_request_reply.GetOobPresent()); - ASSERT_EQ(injected_authentication_requirements, - io_cap_request_reply.GetAuthenticationRequirements()); - ReceiveIoCapabilityResponse(device_, hci::IoCapability::NO_INPUT_NO_OUTPUT, - hci::OobDataPresent::NOT_PRESENT, - hci::AuthenticationRequirements::NO_BONDING); - uint32_t numeric_value = 0x123; - ReceiveUserConfirmationRequest(device_, numeric_value); - security_command_view = GetLastCommand(hci_layer_); - ASSERT_EQ(OpCode::USER_CONFIRMATION_REQUEST_REPLY, security_command_view.GetOpCode()); - auto user_conf_request_reply = - hci::UserConfirmationRequestReplyView::Create(security_command_view); - ASSERT_TRUE(user_conf_request_reply.IsValid()); - ReceiveSimplePairingComplete(hci::ErrorCode::SUCCESS, device_); - std::array<uint8_t, 16> link_key = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5}; - hci::KeyType key_type = hci::KeyType::DEBUG_COMBINATION; - ReceiveLinkKeyNotification(device_, link_key, key_type); - ASSERT_EQ(link_key, security_record_->GetLinkKey()); - ASSERT_EQ(key_type, security_record_->GetKeyType()); - ASSERT_FALSE(security_record_->IsAuthenticated()); - ASSERT_FALSE(security_record_->RequiresMitmProtection()); -} - -// no_input_no_output + display_only is JustWorks no confirmation -// Needs dialog as per security a bug unless pairing is temporary -TEST_F(ClassicPairingHandlerTest, locally_initiatied_no_input_no_output_display_only_temp) { - hci::IoCapability injected_io_capability = hci::IoCapability::NO_INPUT_NO_OUTPUT; - hci::AuthenticationRequirements injected_authentication_requirements = - hci::AuthenticationRequirements::NO_BONDING; - pairing_handler_->Initiate(true, injected_io_capability, injected_authentication_requirements, - pairing::OobData(), pairing::OobData()); - ReceiveLinkKeyRequest(device_); - auto security_command_view = GetLastCommand(hci_layer_); - auto link_key_neg_reply = hci::LinkKeyRequestNegativeReplyView::Create(security_command_view); - ASSERT_TRUE(link_key_neg_reply.IsValid()); - ASSERT_EQ(OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, link_key_neg_reply.GetOpCode()); - ReceiveIoCapabilityRequest(device_); - security_command_view = GetLastCommand(hci_layer_); - ASSERT_EQ(OpCode::IO_CAPABILITY_REQUEST_REPLY, security_command_view.GetOpCode()); - auto io_cap_request_reply = hci::IoCapabilityRequestReplyView::Create(security_command_view); - ASSERT_TRUE(io_cap_request_reply.IsValid()); - ASSERT_EQ(injected_io_capability, io_cap_request_reply.GetIoCapability()); - ASSERT_EQ(hci::OobDataPresent::NOT_PRESENT, io_cap_request_reply.GetOobPresent()); - ASSERT_EQ(injected_authentication_requirements, - io_cap_request_reply.GetAuthenticationRequirements()); - ReceiveIoCapabilityResponse(device_, hci::IoCapability::DISPLAY_ONLY, - hci::OobDataPresent::NOT_PRESENT, - hci::AuthenticationRequirements::NO_BONDING); - uint32_t numeric_value = 0x123; - ReceiveUserConfirmationRequest(device_, numeric_value); - security_command_view = GetLastCommand(hci_layer_); - ASSERT_EQ(OpCode::USER_CONFIRMATION_REQUEST_REPLY, security_command_view.GetOpCode()); - auto user_conf_request_reply = - hci::UserConfirmationRequestReplyView::Create(security_command_view); - ASSERT_TRUE(user_conf_request_reply.IsValid()); - ReceiveSimplePairingComplete(hci::ErrorCode::SUCCESS, device_); - std::array<uint8_t, 16> link_key = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5}; - hci::KeyType key_type = hci::KeyType::DEBUG_COMBINATION; - ReceiveLinkKeyNotification(device_, link_key, key_type); - ASSERT_EQ(link_key, security_record_->GetLinkKey()); - ASSERT_EQ(key_type, security_record_->GetKeyType()); - ASSERT_FALSE(security_record_->IsAuthenticated()); - ASSERT_FALSE(security_record_->RequiresMitmProtection()); -} - -// no_input_no_output + display_yes_no is JustWorks no confirmation -// Needs dialog as per security a bug unless pairing is temporary -TEST_F(ClassicPairingHandlerTest, locally_initiatied_no_input_no_output_display_yes_no_temp) { - hci::IoCapability injected_io_capability = hci::IoCapability::NO_INPUT_NO_OUTPUT; - hci::AuthenticationRequirements injected_authentication_requirements = - hci::AuthenticationRequirements::NO_BONDING; - pairing_handler_->Initiate(true, injected_io_capability, injected_authentication_requirements, - pairing::OobData(), pairing::OobData()); - ReceiveLinkKeyRequest(device_); - auto security_command_view = GetLastCommand(hci_layer_); - auto link_key_neg_reply = hci::LinkKeyRequestNegativeReplyView::Create(security_command_view); - ASSERT_TRUE(link_key_neg_reply.IsValid()); - ASSERT_EQ(OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, link_key_neg_reply.GetOpCode()); - ReceiveIoCapabilityRequest(device_); - security_command_view = GetLastCommand(hci_layer_); - ASSERT_EQ(OpCode::IO_CAPABILITY_REQUEST_REPLY, security_command_view.GetOpCode()); - auto io_cap_request_reply = hci::IoCapabilityRequestReplyView::Create(security_command_view); - ASSERT_TRUE(io_cap_request_reply.IsValid()); - ASSERT_EQ(injected_io_capability, io_cap_request_reply.GetIoCapability()); - ASSERT_EQ(hci::OobDataPresent::NOT_PRESENT, io_cap_request_reply.GetOobPresent()); - ASSERT_EQ(injected_authentication_requirements, - io_cap_request_reply.GetAuthenticationRequirements()); - ReceiveIoCapabilityResponse(device_, hci::IoCapability::DISPLAY_YES_NO, - hci::OobDataPresent::NOT_PRESENT, - hci::AuthenticationRequirements::NO_BONDING); - uint32_t numeric_value = 0x123; - ReceiveUserConfirmationRequest(device_, numeric_value); - security_command_view = GetLastCommand(hci_layer_); - ASSERT_EQ(OpCode::USER_CONFIRMATION_REQUEST_REPLY, security_command_view.GetOpCode()); - auto user_conf_request_reply = - hci::UserConfirmationRequestReplyView::Create(security_command_view); - ASSERT_TRUE(user_conf_request_reply.IsValid()); - ReceiveSimplePairingComplete(hci::ErrorCode::SUCCESS, device_); - std::array<uint8_t, 16> link_key = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5}; - hci::KeyType key_type = hci::KeyType::DEBUG_COMBINATION; - ReceiveLinkKeyNotification(device_, link_key, key_type); - ASSERT_EQ(link_key, security_record_->GetLinkKey()); - ASSERT_EQ(key_type, security_record_->GetKeyType()); - ASSERT_FALSE(security_record_->IsAuthenticated()); - ASSERT_FALSE(security_record_->RequiresMitmProtection()); -} - -// no_input_no_output + keyboard_only is JustWorks no confirmation -// Needs dialog as per security a bug unless pairing is temporary -TEST_F(ClassicPairingHandlerTest, locally_initiatied_no_input_no_output_keyboard_only_temp) { - hci::IoCapability injected_io_capability = hci::IoCapability::NO_INPUT_NO_OUTPUT; - hci::AuthenticationRequirements injected_authentication_requirements = - hci::AuthenticationRequirements::NO_BONDING; - pairing_handler_->Initiate(true, injected_io_capability, injected_authentication_requirements, - pairing::OobData(), pairing::OobData()); - ReceiveLinkKeyRequest(device_); - auto security_command_view = GetLastCommand(hci_layer_); - auto link_key_neg_reply = hci::LinkKeyRequestNegativeReplyView::Create(security_command_view); - ASSERT_TRUE(link_key_neg_reply.IsValid()); - ASSERT_EQ(OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, link_key_neg_reply.GetOpCode()); - ReceiveIoCapabilityRequest(device_); - security_command_view = GetLastCommand(hci_layer_); - ASSERT_EQ(OpCode::IO_CAPABILITY_REQUEST_REPLY, security_command_view.GetOpCode()); - auto io_cap_request_reply = hci::IoCapabilityRequestReplyView::Create(security_command_view); - ASSERT_TRUE(io_cap_request_reply.IsValid()); - ASSERT_EQ(injected_io_capability, io_cap_request_reply.GetIoCapability()); - ASSERT_EQ(hci::OobDataPresent::NOT_PRESENT, io_cap_request_reply.GetOobPresent()); - ASSERT_EQ(injected_authentication_requirements, - io_cap_request_reply.GetAuthenticationRequirements()); - ReceiveIoCapabilityResponse(device_, hci::IoCapability::KEYBOARD_ONLY, - hci::OobDataPresent::NOT_PRESENT, - hci::AuthenticationRequirements::NO_BONDING); - uint32_t numeric_value = 0x123; - ReceiveUserConfirmationRequest(device_, numeric_value); - security_command_view = GetLastCommand(hci_layer_); - ASSERT_EQ(OpCode::USER_CONFIRMATION_REQUEST_REPLY, security_command_view.GetOpCode()); - auto user_conf_request_reply = - hci::UserConfirmationRequestReplyView::Create(security_command_view); - ASSERT_TRUE(user_conf_request_reply.IsValid()); - ReceiveSimplePairingComplete(hci::ErrorCode::SUCCESS, device_); - std::array<uint8_t, 16> link_key = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5}; - hci::KeyType key_type = hci::KeyType::DEBUG_COMBINATION; - ReceiveLinkKeyNotification(device_, link_key, key_type); - ASSERT_EQ(link_key, security_record_->GetLinkKey()); - ASSERT_EQ(key_type, security_record_->GetKeyType()); - ASSERT_FALSE(security_record_->IsAuthenticated()); - ASSERT_FALSE(security_record_->RequiresMitmProtection()); -} - -// no_input_no_output + no_input_no_output is JustWorks no confirmation -// Needs dialog as per security a bug unless pairing is temporary -TEST_F(ClassicPairingHandlerTest, locally_initiatied_no_input_no_output_no_input_no_output_temp) { - hci::IoCapability injected_io_capability = hci::IoCapability::NO_INPUT_NO_OUTPUT; - hci::AuthenticationRequirements injected_authentication_requirements = - hci::AuthenticationRequirements::NO_BONDING; - pairing_handler_->Initiate(true, injected_io_capability, injected_authentication_requirements, - pairing::OobData(), pairing::OobData()); - ReceiveLinkKeyRequest(device_); - auto security_command_view = GetLastCommand(hci_layer_); - auto link_key_neg_reply = hci::LinkKeyRequestNegativeReplyView::Create(security_command_view); - ASSERT_TRUE(link_key_neg_reply.IsValid()); - ASSERT_EQ(OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, link_key_neg_reply.GetOpCode()); - ReceiveIoCapabilityRequest(device_); - security_command_view = GetLastCommand(hci_layer_); - ASSERT_EQ(OpCode::IO_CAPABILITY_REQUEST_REPLY, security_command_view.GetOpCode()); - auto io_cap_request_reply = hci::IoCapabilityRequestReplyView::Create(security_command_view); - ASSERT_TRUE(io_cap_request_reply.IsValid()); - ASSERT_EQ(injected_io_capability, io_cap_request_reply.GetIoCapability()); - ASSERT_EQ(hci::OobDataPresent::NOT_PRESENT, io_cap_request_reply.GetOobPresent()); - ASSERT_EQ(injected_authentication_requirements, - io_cap_request_reply.GetAuthenticationRequirements()); - ReceiveIoCapabilityResponse(device_, hci::IoCapability::NO_INPUT_NO_OUTPUT, - hci::OobDataPresent::NOT_PRESENT, - hci::AuthenticationRequirements::NO_BONDING); - uint32_t numeric_value = 0x123; - ReceiveUserConfirmationRequest(device_, numeric_value); - security_command_view = GetLastCommand(hci_layer_); - ASSERT_EQ(OpCode::USER_CONFIRMATION_REQUEST_REPLY, security_command_view.GetOpCode()); - auto user_conf_request_reply = - hci::UserConfirmationRequestReplyView::Create(security_command_view); - ASSERT_TRUE(user_conf_request_reply.IsValid()); - ReceiveSimplePairingComplete(hci::ErrorCode::SUCCESS, device_); - std::array<uint8_t, 16> link_key = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5}; - hci::KeyType key_type = hci::KeyType::DEBUG_COMBINATION; - ReceiveLinkKeyNotification(device_, link_key, key_type); - ASSERT_EQ(link_key, security_record_->GetLinkKey()); - ASSERT_EQ(key_type, security_record_->GetKeyType()); - ASSERT_FALSE(security_record_->IsAuthenticated()); - ASSERT_FALSE(security_record_->RequiresMitmProtection()); -} - -TEST_F(ClassicPairingHandlerTest, - remote_initiatied_no_input_no_output_no_input_no_output_with_missing_oob_data) {} - -// CreateBondOutOfBand no_input_no_output + no_input_no_output OOB Data missing when asked -TEST_F(ClassicPairingHandlerTest, - locally_initiatied_no_input_no_output_no_input_no_output_with_missing_oob_data) { - expect_success_ = false; - hci::IoCapability injected_io_capability = hci::IoCapability::NO_INPUT_NO_OUTPUT; - hci::AuthenticationRequirements injected_authentication_requirements = - hci::AuthenticationRequirements::NO_BONDING; - pairing_handler_->Initiate(true, injected_io_capability, injected_authentication_requirements, - pairing::OobData(), pairing::OobData()); - - ReceiveLinkKeyRequest(device_); - auto security_command_view = GetLastCommand(hci_layer_); - auto link_key_neg_reply = hci::LinkKeyRequestNegativeReplyView::Create(security_command_view); - ASSERT_TRUE(link_key_neg_reply.IsValid()); - ASSERT_EQ(OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, link_key_neg_reply.GetOpCode()); - ReceiveIoCapabilityRequest(device_); - security_command_view = GetLastCommand(hci_layer_); - ASSERT_EQ(OpCode::IO_CAPABILITY_REQUEST_REPLY, security_command_view.GetOpCode()); - auto io_cap_request_reply = hci::IoCapabilityRequestReplyView::Create(security_command_view); - ASSERT_TRUE(io_cap_request_reply.IsValid()); - ASSERT_EQ(injected_io_capability, io_cap_request_reply.GetIoCapability()); - ASSERT_EQ(hci::OobDataPresent::NOT_PRESENT, io_cap_request_reply.GetOobPresent()); - ASSERT_EQ(injected_authentication_requirements, - io_cap_request_reply.GetAuthenticationRequirements()); - ReceiveIoCapabilityResponse(device_, hci::IoCapability::NO_INPUT_NO_OUTPUT, - hci::OobDataPresent::NOT_PRESENT, - hci::AuthenticationRequirements::NO_BONDING); - // At this point the pairing handler thinks it has NOT_PRESENT - ReceiveOobDataRequest(device_); - security_command_view = GetLastCommand(hci_layer_); - auto oob_data_req_neg_reply = - hci::RemoteOobDataRequestNegativeReplyView::Create(security_command_view); - ASSERT_TRUE(oob_data_req_neg_reply.IsValid()); - ASSERT_EQ(OpCode::REMOTE_OOB_DATA_REQUEST_NEGATIVE_REPLY, oob_data_req_neg_reply.GetOpCode()); - ReceiveSimplePairingComplete(hci::ErrorCode::AUTHENTICATION_FAILURE, device_); -} - -// CreateBondOutOfBand no_input_no_output + no_input_no_output OOB Data P192 -TEST_F(ClassicPairingHandlerTest, - locally_initiatied_no_input_no_output_no_input_no_output_p192_oob_data) { - hci::IoCapability injected_io_capability = hci::IoCapability::NO_INPUT_NO_OUTPUT; - hci::AuthenticationRequirements injected_authentication_requirements = - hci::AuthenticationRequirements::NO_BONDING; - pairing::OobData oob_data({1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}); - pairing_handler_->Initiate(true, injected_io_capability, injected_authentication_requirements, - oob_data, pairing::OobData()); - - ReceiveLinkKeyRequest(device_); - auto security_command_view = GetLastCommand(hci_layer_); - auto link_key_neg_reply = hci::LinkKeyRequestNegativeReplyView::Create(security_command_view); - ASSERT_TRUE(link_key_neg_reply.IsValid()); - ASSERT_EQ(OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, link_key_neg_reply.GetOpCode()); - ReceiveIoCapabilityRequest(device_); - security_command_view = GetLastCommand(hci_layer_); - ASSERT_EQ(OpCode::IO_CAPABILITY_REQUEST_REPLY, security_command_view.GetOpCode()); - auto io_cap_request_reply = hci::IoCapabilityRequestReplyView::Create(security_command_view); - ASSERT_TRUE(io_cap_request_reply.IsValid()); - ASSERT_EQ(injected_io_capability, io_cap_request_reply.GetIoCapability()); - ASSERT_EQ(hci::OobDataPresent::P_192_PRESENT, io_cap_request_reply.GetOobPresent()); - ASSERT_EQ(injected_authentication_requirements, - io_cap_request_reply.GetAuthenticationRequirements()); - ReceiveIoCapabilityResponse(device_, hci::IoCapability::NO_INPUT_NO_OUTPUT, - hci::OobDataPresent::NOT_PRESENT, - hci::AuthenticationRequirements::NO_BONDING); - // At this point the pairing handler thinks it has NOT_PRESENT - ReceiveOobDataRequest(device_); - security_command_view = GetLastCommand(hci_layer_); - // NOTE(optedoblivion): Extended data is manually disabled in the pairing handler - // since the controller doesn't seem to currently have support. - auto oob_data_req_reply = hci::RemoteOobDataRequestReplyView::Create(security_command_view); - ASSERT_TRUE(oob_data_req_reply.IsValid()); - ASSERT_EQ(OpCode::REMOTE_OOB_DATA_REQUEST_REPLY, oob_data_req_reply.GetOpCode()); - ReceiveSimplePairingComplete(hci::ErrorCode::SUCCESS, device_); - std::array<uint8_t, 16> link_key = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5}; - hci::KeyType key_type = hci::KeyType::DEBUG_COMBINATION; - ReceiveLinkKeyNotification(device_, link_key, key_type); - ASSERT_EQ(link_key, security_record_->GetLinkKey()); - ASSERT_EQ(key_type, security_record_->GetKeyType()); - ASSERT_FALSE(security_record_->IsAuthenticated()); - ASSERT_FALSE(security_record_->RequiresMitmProtection()); -} - -// CreateBondOutOfBand no_input_no_output + no_input_no_output OOB Data P256 -TEST_F(ClassicPairingHandlerTest, - locally_initiatied_no_input_no_output_no_input_no_output_p256_oob_data) { - hci::IoCapability injected_io_capability = hci::IoCapability::NO_INPUT_NO_OUTPUT; - hci::AuthenticationRequirements injected_authentication_requirements = - hci::AuthenticationRequirements::NO_BONDING; - pairing::OobData oob_data({1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}); - pairing_handler_->Initiate(true, injected_io_capability, injected_authentication_requirements, - pairing::OobData(), oob_data); - ReceiveLinkKeyRequest(device_); - auto security_command_view = GetLastCommand(hci_layer_); - auto link_key_neg_reply = hci::LinkKeyRequestNegativeReplyView::Create(security_command_view); - ASSERT_TRUE(link_key_neg_reply.IsValid()); - ASSERT_EQ(OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, link_key_neg_reply.GetOpCode()); - ReceiveIoCapabilityRequest(device_); - security_command_view = GetLastCommand(hci_layer_); - ASSERT_EQ(OpCode::IO_CAPABILITY_REQUEST_REPLY, security_command_view.GetOpCode()); - auto io_cap_request_reply = hci::IoCapabilityRequestReplyView::Create(security_command_view); - ASSERT_TRUE(io_cap_request_reply.IsValid()); - ASSERT_EQ(injected_io_capability, io_cap_request_reply.GetIoCapability()); - ASSERT_EQ(hci::OobDataPresent::P_256_PRESENT, io_cap_request_reply.GetOobPresent()); - ASSERT_EQ(injected_authentication_requirements, - io_cap_request_reply.GetAuthenticationRequirements()); - ReceiveIoCapabilityResponse(device_, hci::IoCapability::NO_INPUT_NO_OUTPUT, - hci::OobDataPresent::NOT_PRESENT, - hci::AuthenticationRequirements::NO_BONDING); - // At this point the pairing handler thinks it has NOT_PRESENT - ReceiveOobDataRequest(device_); - security_command_view = GetLastCommand(hci_layer_); - auto oob_data_req_reply = - hci::RemoteOobExtendedDataRequestReplyView::Create(security_command_view); - ASSERT_TRUE(oob_data_req_reply.IsValid()); - ASSERT_EQ(OpCode::REMOTE_OOB_EXTENDED_DATA_REQUEST_REPLY, oob_data_req_reply.GetOpCode()); - ReceiveSimplePairingComplete(hci::ErrorCode::SUCCESS, device_); - std::array<uint8_t, 16> link_key = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5}; - hci::KeyType key_type = hci::KeyType::DEBUG_COMBINATION; - ReceiveLinkKeyNotification(device_, link_key, key_type); - ASSERT_EQ(link_key, security_record_->GetLinkKey()); - ASSERT_EQ(key_type, security_record_->GetKeyType()); - ASSERT_FALSE(security_record_->IsAuthenticated()); - ASSERT_FALSE(security_record_->RequiresMitmProtection()); -} - -// CreateBondOutOfBand no_input_no_output + no_input_no_output OOB Data P192 and 256 -TEST_F(ClassicPairingHandlerTest, - locally_initiatied_no_input_no_output_no_input_no_output_p192_and_256_oob_data) { - hci::IoCapability injected_io_capability = hci::IoCapability::NO_INPUT_NO_OUTPUT; - hci::AuthenticationRequirements injected_authentication_requirements = - hci::AuthenticationRequirements::NO_BONDING; - pairing::OobData oob_data({1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}); - pairing_handler_->Initiate(true, injected_io_capability, injected_authentication_requirements, - oob_data, oob_data); - ReceiveLinkKeyRequest(device_); - auto security_command_view = GetLastCommand(hci_layer_); - auto link_key_neg_reply = hci::LinkKeyRequestNegativeReplyView::Create(security_command_view); - ASSERT_TRUE(link_key_neg_reply.IsValid()); - ASSERT_EQ(OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, link_key_neg_reply.GetOpCode()); - ReceiveIoCapabilityRequest(device_); - security_command_view = GetLastCommand(hci_layer_); - ASSERT_EQ(OpCode::IO_CAPABILITY_REQUEST_REPLY, security_command_view.GetOpCode()); - auto io_cap_request_reply = hci::IoCapabilityRequestReplyView::Create(security_command_view); - ASSERT_TRUE(io_cap_request_reply.IsValid()); - ASSERT_EQ(injected_io_capability, io_cap_request_reply.GetIoCapability()); - ASSERT_EQ(hci::OobDataPresent::P_192_AND_256_PRESENT, io_cap_request_reply.GetOobPresent()); - ASSERT_EQ(injected_authentication_requirements, - io_cap_request_reply.GetAuthenticationRequirements()); - ReceiveIoCapabilityResponse(device_, hci::IoCapability::NO_INPUT_NO_OUTPUT, - hci::OobDataPresent::NOT_PRESENT, - hci::AuthenticationRequirements::NO_BONDING); - // At this point the pairing handler thinks it has NOT_PRESENT - ReceiveOobDataRequest(device_); - security_command_view = GetLastCommand(hci_layer_); - auto oob_data_req_reply = - hci::RemoteOobExtendedDataRequestReplyView::Create(security_command_view); - ASSERT_TRUE(oob_data_req_reply.IsValid()); - ASSERT_EQ(OpCode::REMOTE_OOB_EXTENDED_DATA_REQUEST_REPLY, oob_data_req_reply.GetOpCode()); - ReceiveSimplePairingComplete(hci::ErrorCode::SUCCESS, device_); - std::array<uint8_t, 16> link_key = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5}; - hci::KeyType key_type = hci::KeyType::DEBUG_COMBINATION; - ReceiveLinkKeyNotification(device_, link_key, key_type); - ASSERT_EQ(link_key, security_record_->GetLinkKey()); - ASSERT_EQ(key_type, security_record_->GetKeyType()); - ASSERT_FALSE(security_record_->IsAuthenticated()); - ASSERT_FALSE(security_record_->RequiresMitmProtection()); -} - -/*** Numeric Comparison ***/ -// display_yes_no + display_only - -// display_yes_no + display_yes_no -// display_yes_no + keyboard_only -// display_yes_no + no_input_no_output - -// keyboard_only + display_only -// keyboard_only + display_yes_no - -// keyboard_only + keyboard_only (a just works I missed) - -// Remotely initiated - -// Collisions - -} // namespace -} // namespace pairing -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/pairing/oob_data.h b/system/gd/security/pairing/oob_data.h deleted file mode 100644 index bd75e59c0e..0000000000 --- a/system/gd/security/pairing/oob_data.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * - * Copyright 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License") override; - * 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. - * - */ -#pragma once - -#include <array> -#include <cstdint> - -namespace bluetooth { -namespace security { -namespace pairing { - -using SimplePairingHash = std::array<uint8_t, 16>; -using SimplePairingRandomizer = std::array<uint8_t, 16>; - -class OobData { -public: - OobData() {} - OobData(SimplePairingHash C, SimplePairingRandomizer R) : C_(C), R_(R) {} - - SimplePairingHash GetC() { return C_; } - - SimplePairingRandomizer GetR() { return R_; } - - bool IsValid() { - return !std::all_of(C_.begin(), C_.end(), [](uint8_t b) { return b == 0; }) && - !std::all_of(R_.begin(), R_.end(), [](uint8_t b) { return b == 0; }); - } - -private: - SimplePairingHash C_ = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - SimplePairingRandomizer R_ = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -}; - -} // namespace pairing -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/pairing/pairing_handler.h b/system/gd/security/pairing/pairing_handler.h deleted file mode 100644 index 795d11f1dd..0000000000 --- a/system/gd/security/pairing/pairing_handler.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * - * Copyright 2019 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. - * - */ -#pragma once - -#include <neighbor/name_db.h> - -#include <utility> -#include <vector> - -#include "hci/address_with_type.h" -#include "hci/hci_packets.h" -#include "neighbor/name_db.h" -#include "security/channel/security_manager_channel.h" -#include "security/pairing/oob_data.h" -#include "security/record/security_record.h" -#include "security/ui.h" - -namespace bluetooth { -namespace security { -namespace pairing { - -/** - * Base structure for handling pairing events. - * - * <p>Extend this class in order to implement a new style of pairing. - */ -class PairingHandler : public UICallbacks { -public: - PairingHandler(channel::SecurityManagerChannel* security_manager_channel, - std::shared_ptr<record::SecurityRecord> record, - neighbor::NameDbModule* name_db_module) - : security_manager_channel_(security_manager_channel), - record_(std::move(record)), - name_db_module_(name_db_module) {} - ~PairingHandler() = default; - - // Classic - virtual void Initiate(bool locally_initiated, hci::IoCapability io_capability, - hci::AuthenticationRequirements auth_requirements, - OobData local_p192_oob_data, OobData local_p256_oob_data) = 0; - virtual void Cancel() = 0; - virtual void OnReceive(hci::ChangeConnectionLinkKeyCompleteView packet) = 0; - virtual void OnReceive(hci::CentralLinkKeyCompleteView packet) = 0; - virtual void OnReceive(hci::PinCodeRequestView packet) = 0; - virtual void OnReceive(hci::LinkKeyRequestView packet) = 0; - virtual void OnReceive(hci::LinkKeyNotificationView packet) = 0; - virtual void OnReceive(hci::IoCapabilityRequestView packet) = 0; - virtual void OnReceive(hci::IoCapabilityResponseView packet) = 0; - virtual void OnReceive(hci::SimplePairingCompleteView packet) = 0; - virtual void OnReceive(hci::ReturnLinkKeysView packet) = 0; - virtual void OnReceive(hci::EncryptionChangeView packet) = 0; - virtual void OnReceive(hci::EncryptionKeyRefreshCompleteView packet) = 0; - virtual void OnReceive(hci::RemoteOobDataRequestView packet) = 0; - virtual void OnReceive(hci::UserPasskeyNotificationView packet) = 0; - virtual void OnReceive(hci::KeypressNotificationView packet) = 0; - virtual void OnReceive(hci::UserConfirmationRequestView packet) = 0; - virtual void OnReceive(hci::UserPasskeyRequestView packet) = 0; - - virtual void OnPairingPromptAccepted(const bluetooth::hci::AddressWithType& address, - bool confirmed) = 0; - virtual void OnConfirmYesNo(const bluetooth::hci::AddressWithType& address, bool confirmed) = 0; - virtual void OnPasskeyEntry(const bluetooth::hci::AddressWithType& address, uint32_t passkey) = 0; - virtual void OnPinEntry(const bluetooth::hci::AddressWithType& address, - std::vector<uint8_t> pin) override = 0; - -protected: - std::shared_ptr<record::SecurityRecord> GetRecord() { return record_; } - channel::SecurityManagerChannel* GetChannel() { return security_manager_channel_; } - neighbor::NameDbModule* GetNameDbModule() { return name_db_module_; } - -private: - channel::SecurityManagerChannel* security_manager_channel_ __attribute__((unused)); - std::shared_ptr<record::SecurityRecord> record_ __attribute__((unused)); - neighbor::NameDbModule* name_db_module_; -}; - -} // namespace pairing -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/pairing_failure.h b/system/gd/security/pairing_failure.h deleted file mode 100644 index 1b671d91ce..0000000000 --- a/system/gd/security/pairing_failure.h +++ /dev/null @@ -1,60 +0,0 @@ -/****************************************************************************** - * - * Copyright 2019 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. - * - ******************************************************************************/ - -#pragma once - -#include <string> - -#include "security/smp_packets.h" - -namespace bluetooth { -namespace security { - -/* This structure holds the information about the failure in case of airing failure */ -struct PairingFailure { - /* A place in code that triggered this failure. It can be modified by functions that pass the - * error to a location that better reflect the current state of flow. i.e. instead of generic - * location responsible for waiting for packet, replace it with location of receiving specific - * packet in a specific flow */ - // base::Location location; - - /* This is the failure message, that will be passed, either into upper layers, - * or to the metrics in future */ - std::string message; - - /* If failure is due to mismatch of received code, this contains the received opcode */ - Code received_code_{0}; - - /* if the failure is due to "SMP failure", this field contains the reson code - */ - PairingFailedReason reason{0}; - - PairingFailure(/*const base::Location& location, */ const std::string& message) - : /*location(location), */ message(message) {} - - PairingFailure(/*const base::Location& location, */ const std::string& message, - Code received_code) - : /*location(location), */ message(message), received_code_(received_code) {} - - PairingFailure(/*const base::Location& location, */ const std::string& message, - PairingFailedReason reason) - : /*location(location),*/ message(message), reason(reason) {} -}; - -} // namespace security -} // namespace bluetooth
\ No newline at end of file diff --git a/system/gd/security/pairing_handler_le.cc b/system/gd/security/pairing_handler_le.cc deleted file mode 100644 index 8bb11eb648..0000000000 --- a/system/gd/security/pairing_handler_le.cc +++ /dev/null @@ -1,501 +0,0 @@ -/****************************************************************************** - * - * Copyright 2019 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 "security/pairing_handler_le.h" - -#include <bluetooth/log.h> - -#include "hci/octets.h" -#include "os/rand.h" - -namespace bluetooth { -namespace security { - -using hci::Octet16; - -MyOobData PairingHandlerLe::GenerateOobData() { - MyOobData data{}; - std::tie(data.private_key, data.public_key) = GenerateECDHKeyPair(); - - data.r = bluetooth::os::GenerateRandom<16>(); - data.c = crypto_toolbox::f4(data.public_key.x.data(), data.public_key.x.data(), data.r, 0); - return data; -} - -void PairingHandlerLe::PairingMain(InitialInformations i) { - log::info("Pairing Started"); - - if (i.remotely_initiated) { - log::info("Was remotely initiated, presenting user with the accept prompt"); - i.user_interface_handler->Post(common::BindOnce(&UI::DisplayPairingPrompt, - common::Unretained(i.user_interface), - i.remote_connection_address, i.remote_name)); - - // If pairing was initiated by remote device, wait for the user to accept - // the request from the UI. - log::info("Waiting for the prompt response"); - std::optional<PairingEvent> pairingAccepted = WaitUiPairingAccept(); - if (!pairingAccepted || pairingAccepted->ui_value == 0) { - log::info("User either did not accept the remote pairing, or the prompt timed out"); - // TODO: Uncomment this one once we find a way to attempt to send packet when the link is down - // SendL2capPacket(i, PairingFailedBuilder::Create(PairingFailedReason::UNSPECIFIED_REASON)); - i.OnPairingFinished(PairingFailure( - "User either did not accept the remote pairing, or the prompt timed out")); - return; - } - - log::info("Pairing prompt accepted"); - } - - /************************************************ PHASE 1 - * *********************************************************/ - Phase1ResultOrFailure phase_1_result = ExchangePairingFeature(i); - if (std::holds_alternative<PairingFailure>(phase_1_result)) { - log::warn("Pairing failed in phase 1"); - // We already send pairing fialed in lower layer. Which one should do that ? how about - // disconneciton? SendL2capPacket(i, - // PairingFailedBuilder::Create(PairingFailedReason::UNSPECIFIED_REASON)); - // TODO: disconnect? - i.OnPairingFinished(std::get<PairingFailure>(phase_1_result)); - return; - } - - auto [pairing_request, pairing_response] = std::get<Phase1Result>(phase_1_result); - - uint8_t key_size = std::min(pairing_request.GetMaximumEncryptionKeySize(), - pairing_response.GetMaximumEncryptionKeySize()); - if (key_size < 7 || key_size > 16) { - log::warn("Resulting key size is bad {}", key_size); - SendL2capPacket(i, PairingFailedBuilder::Create(PairingFailedReason::ENCRYPTION_KEY_SIZE)); - i.OnPairingFinished( - PairingFailure("Resulting key size is bad", PairingFailedReason::ENCRYPTION_KEY_SIZE)); - return; - } - if (key_size != 16) { - log::warn("Resulting key size is less than 16 octets!"); - } - - /************************************************ PHASE 2 - * *********************************************************/ - bool isSecureConnections = - pairing_request.GetAuthReq() & pairing_response.GetAuthReq() & AuthReqMaskSc; - if (isSecureConnections) { - // 2.3.5.6 LE Secure Connections pairing phase 2 - log::info("Pairing Phase 2 LE Secure connections Started"); - - /* - TODO: what to do with this piece of spec ? - If Secure Connections pairing has been initiated over BR/EDR, the - following fields of the SM Pairing Request PDU are reserved for future use: - • the IO Capability field, - • the OOB data flag field, and - • all bits in the Auth Req field except the CT2 bit. - */ - - OobDataFlag remote_have_oob_data = - IAmCentral(i) ? pairing_response.GetOobDataFlag() : pairing_request.GetOobDataFlag(); - - auto key_exchange_result = ExchangePublicKeys(i, remote_have_oob_data); - if (std::holds_alternative<PairingFailure>(key_exchange_result)) { - log::error("Public key exchange failed"); - i.OnPairingFinished(std::get<PairingFailure>(key_exchange_result)); - return; - } - auto [PKa, PKb, dhkey] = std::get<KeyExchangeResult>(key_exchange_result); - - // Public key exchange finished, Diffie-Hellman key computed. - - Stage1ResultOrFailure stage1result = - DoSecureConnectionsStage1(i, PKa, PKb, pairing_request, pairing_response); - if (std::holds_alternative<PairingFailure>(stage1result)) { - i.OnPairingFinished(std::get<PairingFailure>(stage1result)); - return; - } - - Stage2ResultOrFailure stage_2_result = - DoSecureConnectionsStage2(i, PKa, PKb, pairing_request, pairing_response, - std::get<Stage1Result>(stage1result), dhkey); - if (std::holds_alternative<PairingFailure>(stage_2_result)) { - i.OnPairingFinished(std::get<PairingFailure>(stage_2_result)); - return; - } - - Octet16 ltk = std::get<Octet16>(stage_2_result); - // Mask the key - std::fill(ltk.begin() + key_size, ltk.end(), 0x00); - - if (IAmCentral(i)) { - log::info("Sending start encryption request"); - SendHciLeStartEncryption(i, i.connection_handle, {0}, {0}, ltk); - } else { - auto ltk_req = WaitLeLongTermKeyRequest(); - SendHciLeLongTermKeyReply(i, i.connection_handle, ltk); - } - } else { - // 2.3.5.5 LE legacy pairing phase 2 - log::info("Pairing Phase 2 LE legacy pairing Started"); - - LegacyStage1ResultOrFailure stage1result = DoLegacyStage1(i, pairing_request, pairing_response); - if (std::holds_alternative<PairingFailure>(stage1result)) { - log::error("Phase 1 failed"); - i.OnPairingFinished(std::get<PairingFailure>(stage1result)); - return; - } - - Octet16 tk = std::get<Octet16>(stage1result); - StkOrFailure stage2result = DoLegacyStage2(i, pairing_request, pairing_response, tk); - if (std::holds_alternative<PairingFailure>(stage2result)) { - log::error("stage 2 failed"); - i.OnPairingFinished(std::get<PairingFailure>(stage2result)); - return; - } - - Octet16 stk = std::get<Octet16>(stage2result); - // Mask the key - std::fill(stk.begin() + key_size, stk.end(), 0x00); - if (IAmCentral(i)) { - log::info("Sending start encryption request"); - SendHciLeStartEncryption(i, i.connection_handle, {0}, {0}, stk); - } else { - auto ltk_req = WaitLeLongTermKeyRequest(); - SendHciLeLongTermKeyReply(i, i.connection_handle, stk); - } - } - - /************************************************ PHASE 3 - * *********************************************************/ - log::info("Waiting for encryption changed"); - auto encryption_change_result = WaitEncryptionChanged(); - if (std::holds_alternative<PairingFailure>(encryption_change_result)) { - i.OnPairingFinished(std::get<PairingFailure>(encryption_change_result)); - return; - } else if (std::holds_alternative<EncryptionChangeView>(encryption_change_result)) { - EncryptionChangeView encryption_changed = - std::get<EncryptionChangeView>(encryption_change_result); - if (encryption_changed.GetStatus() != hci::ErrorCode::SUCCESS || - encryption_changed.GetEncryptionEnabled() != hci::EncryptionEnabled::ON) { - i.OnPairingFinished(PairingFailure("Encryption change failed")); - return; - } - } else if (std::holds_alternative<EncryptionKeyRefreshCompleteView>(encryption_change_result)) { - EncryptionKeyRefreshCompleteView encryption_changed = - std::get<EncryptionKeyRefreshCompleteView>(encryption_change_result); - if (encryption_changed.GetStatus() != hci::ErrorCode::SUCCESS) { - i.OnPairingFinished(PairingFailure("Encryption key refresh failed")); - return; - } - } else { - i.OnPairingFinished(PairingFailure("Unknown case of encryption change result")); - return; - } - log::info("Encryption change finished successfully"); - - DistributedKeysOrFailure keyExchangeStatus = - DistributeKeys(i, pairing_response, isSecureConnections); - if (std::holds_alternative<PairingFailure>(keyExchangeStatus)) { - i.OnPairingFinished(std::get<PairingFailure>(keyExchangeStatus)); - log::error("Key exchange failed"); - return; - } - - // If it's secure connections pairing, do cross-transport key derivation - DistributedKeys distributed_keys = std::get<DistributedKeys>(keyExchangeStatus); - if ((pairing_response.GetAuthReq() & AuthReqMaskSc) && distributed_keys.remote_ltk.has_value()) { - bool use_h7 = (pairing_response.GetAuthReq() & AuthReqMaskCt2); - Octet16 link_key = crypto_toolbox::ltk_to_link_key(*(distributed_keys.remote_ltk), use_h7); - distributed_keys.remote_link_key = link_key; - } - - // bool bonding = pairing_request.GetAuthReq() & pairing_response.GetAuthReq() & - // AuthReqMaskBondingFlag; - - i.OnPairingFinished(PairingResult{ - .connection_address = i.remote_connection_address, - .distributed_keys = distributed_keys, - .key_size = key_size, - }); - - log::info("Pairing finished successfully."); -} - -Phase1ResultOrFailure PairingHandlerLe::ExchangePairingFeature(const InitialInformations& i) { - log::info("Phase 1 start"); - - if (IAmCentral(i)) { - // Send Pairing Request - const auto& x = i.myPairingCapabilities; - auto pairing_request_builder = PairingRequestBuilder::Create( - x.io_capability, x.oob_data_flag, x.auth_req, x.maximum_encryption_key_size, - x.initiator_key_distribution, x.responder_key_distribution); - // basically pairing_request = myPairingCapabilities; - - // Convert builder to view - std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>(); - BitInserter it(*packet_bytes); - pairing_request_builder->Serialize(it); - PacketView<kLittleEndian> packet_bytes_view(packet_bytes); - auto temp_cmd_view = CommandView::Create(packet_bytes_view); - auto pairing_request = PairingRequestView::Create(temp_cmd_view); - log::assert_that(pairing_request.IsValid(), "assert failed: pairing_request.IsValid()"); - - log::info("Sending Pairing Request"); - SendL2capPacket(i, std::move(pairing_request_builder)); - - log::info("Waiting for Pairing Response"); - auto response = WaitPairingResponse(); - - /* There is a potential collision where the peripheral initiates the pairing at the same time we - * initiate it, by sending security request. */ - if (std::holds_alternative<PairingFailure>(response) && - std::get<PairingFailure>(response).received_code_ == Code::SECURITY_REQUEST) { - log::info("Received security request, waiting for Pairing Response again..."); - response = WaitPairingResponse(); - } - - if (std::holds_alternative<PairingFailure>(response)) { - // TODO: should the failure reason be different in some cases ? How about - // when we lost connection ? Don't send anything at all, or have L2CAP - // layer ignore it? - SendL2capPacket(i, PairingFailedBuilder::Create(PairingFailedReason::UNSPECIFIED_REASON)); - return std::get<PairingFailure>(response); - } - - auto pairing_response = std::get<PairingResponseView>(response); - - log::info("Phase 1 finish"); - return Phase1Result{pairing_request, pairing_response}; - } else { - std::optional<PairingRequestView> pairing_request; - - if (i.remotely_initiated) { - if (!i.pairing_request.has_value()) { - return PairingFailure( - "You must pass PairingRequest as a initial information to peripheral!"); - } - - pairing_request = i.pairing_request.value(); - - if (!pairing_request->IsValid()) { - return PairingFailure("Malformed PairingRequest"); - } - } else { - SendL2capPacket(i, SecurityRequestBuilder::Create(i.myPairingCapabilities.auth_req)); - - log::info("Waiting for Pairing Request"); - auto request = WaitPairingRequest(); - if (std::holds_alternative<PairingFailure>(request)) { - log::info("{}", std::get<PairingFailure>(request).message); - SendL2capPacket(i, PairingFailedBuilder::Create(PairingFailedReason::UNSPECIFIED_REASON)); - return std::get<PairingFailure>(request); - } - - pairing_request = std::get<PairingRequestView>(request); - } - - uint8_t key_size = pairing_request->GetMaximumEncryptionKeySize(); - if (key_size < 7 || key_size > 16) { - log::warn("Resulting key size is bad {}", key_size); - SendL2capPacket(i, PairingFailedBuilder::Create(PairingFailedReason::ENCRYPTION_KEY_SIZE)); - return PairingFailure("Resulting key size is bad", PairingFailedReason::ENCRYPTION_KEY_SIZE); - } - - // Send Pairing Request - const auto& x = i.myPairingCapabilities; - // basically pairing_response_builder = my_first_packet; - // We are not allowed to enable bits that the remote did not allow us to set in - // initiator_key_dist and responder_key_distribution - auto pairing_response_builder = PairingResponseBuilder::Create( - x.io_capability, x.oob_data_flag, x.auth_req, x.maximum_encryption_key_size, - x.initiator_key_distribution & pairing_request->GetInitiatorKeyDistribution(), - x.responder_key_distribution & pairing_request->GetResponderKeyDistribution()); - - // Convert builder to view - std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>(); - BitInserter it(*packet_bytes); - pairing_response_builder->Serialize(it); - PacketView<kLittleEndian> packet_bytes_view(packet_bytes); - auto temp_cmd_view = CommandView::Create(packet_bytes_view); - auto pairing_response = PairingResponseView::Create(temp_cmd_view); - log::assert_that(pairing_response.IsValid(), "assert failed: pairing_response.IsValid()"); - - log::info("Sending Pairing Response"); - SendL2capPacket(i, std::move(pairing_response_builder)); - - log::info("Phase 1 finish"); - return Phase1Result{pairing_request.value(), pairing_response}; - } -} - -DistributedKeysOrFailure PairingHandlerLe::DistributeKeys( - const InitialInformations& i, const PairingResponseView& pairing_response, - bool isSecureConnections) { - uint8_t keys_i_receive = IAmCentral(i) ? pairing_response.GetResponderKeyDistribution() - : pairing_response.GetInitiatorKeyDistribution(); - uint8_t keys_i_send = IAmCentral(i) ? pairing_response.GetInitiatorKeyDistribution() - : pairing_response.GetResponderKeyDistribution(); - - // In Secure Connections on the LE Transport, the EncKey field shall be ignored - if (isSecureConnections) { - keys_i_send = (~KeyMaskEnc) & keys_i_send; - keys_i_receive = (~KeyMaskEnc) & keys_i_receive; - } - - log::info("Key distribution start, keys_i_send=0x{:02x}, keys_i_receive=0x{:02x}", keys_i_send, - keys_i_receive); - - // TODO: obtain actual values, and apply key_size to the LTK - Octet16 my_ltk = bluetooth::os::GenerateRandom<16>(); - uint16_t my_ediv = bluetooth::os::GenerateRandom(); - std::array<uint8_t, 8> my_rand = bluetooth::os::GenerateRandom<8>(); - - Octet16 my_irk = i.my_identity_resolving_key; - Address my_identity_address = i.my_identity_address.GetAddress(); - AddrType my_identity_address_type = - static_cast<bluetooth::security::AddrType>(i.my_identity_address.GetAddressType()); - Octet16 my_signature_key{0}; - - if (IAmCentral(i)) { - // EncKey is unused for LE Secure Connections - DistributedKeysOrFailure keys = ReceiveKeys(keys_i_receive); - if (std::holds_alternative<PairingFailure>(keys)) { - return keys; - } - - SendKeys(i, keys_i_send, my_ltk, my_ediv, my_rand, my_irk, my_identity_address, - my_identity_address_type, my_signature_key); - - std::get<DistributedKeys>(keys).local_ltk = my_ltk; - std::get<DistributedKeys>(keys).local_ediv = my_ediv; - std::get<DistributedKeys>(keys).local_rand = my_rand; - log::info("Key distribution finish"); - return keys; - } else { - SendKeys(i, keys_i_send, my_ltk, my_ediv, my_rand, my_irk, my_identity_address, - my_identity_address_type, my_signature_key); - - DistributedKeysOrFailure keys = ReceiveKeys(keys_i_receive); - if (std::holds_alternative<PairingFailure>(keys)) { - return keys; - } - - std::get<DistributedKeys>(keys).local_ltk = my_ltk; - std::get<DistributedKeys>(keys).local_ediv = my_ediv; - std::get<DistributedKeys>(keys).local_rand = my_rand; - log::info("Key distribution finish"); - return keys; - } -} - -DistributedKeysOrFailure PairingHandlerLe::ReceiveKeys(const uint8_t& keys_i_receive) { - std::optional<Octet16> ltk; /* Legacy only */ - std::optional<uint16_t> ediv; /* Legacy only */ - std::optional<std::array<uint8_t, 8>> rand; /* Legacy only */ - std::optional<hci::AddressWithType> identity_address; - std::optional<Octet16> irk; - std::optional<Octet16> signature_key; - - if (keys_i_receive & KeyMaskEnc) { - { - auto packet = WaitEncryptionInformation(); - if (std::holds_alternative<PairingFailure>(packet)) { - log::error("Was expecting Encryption Information but did not receive!"); - return std::get<PairingFailure>(packet); - } - ltk = std::get<EncryptionInformationView>(packet).GetLongTermKey(); - } - - { - auto packet = WaitCentralIdentification(); - if (std::holds_alternative<PairingFailure>(packet)) { - log::error("Was expecting Central Identification but did not receive!"); - return std::get<PairingFailure>(packet); - } - ediv = std::get<CentralIdentificationView>(packet).GetEdiv(); - rand = std::get<CentralIdentificationView>(packet).GetRand(); - } - } - - if (keys_i_receive & KeyMaskId) { - auto packet = WaitIdentityInformation(); - if (std::holds_alternative<PairingFailure>(packet)) { - log::error("Was expecting Identity Information but did not receive!"); - return std::get<PairingFailure>(packet); - } - - log::info("Received Identity Information"); - irk = std::get<IdentityInformationView>(packet).GetIdentityResolvingKey(); - - auto iapacket = WaitIdentityAddressInformation(); - if (std::holds_alternative<PairingFailure>(iapacket)) { - log::error("Was expecting Identity Address Information but did not receive!"); - return std::get<PairingFailure>(iapacket); - } - log::info("Received Identity Address Information"); - auto iapacketview = std::get<IdentityAddressInformationView>(iapacket); - identity_address = hci::AddressWithType(iapacketview.GetBdAddr(), - iapacketview.GetAddrType() == AddrType::PUBLIC - ? hci::AddressType::PUBLIC_DEVICE_ADDRESS - : hci::AddressType::RANDOM_DEVICE_ADDRESS); - } - - if (keys_i_receive & KeyMaskSign) { - auto packet = WaitSigningInformation(); - if (std::holds_alternative<PairingFailure>(packet)) { - log::error("Was expecting Signing Information but did not receive!"); - return std::get<PairingFailure>(packet); - } - - log::info("Received Signing Information"); - signature_key = std::get<SigningInformationView>(packet).GetSignatureKey(); - } - - return DistributedKeys{.remote_ltk = ltk, - .remote_ediv = ediv, - .remote_rand = rand, - .remote_identity_address = identity_address, - .remote_irk = irk, - .remote_signature_key = signature_key}; -} - -void PairingHandlerLe::SendKeys(const InitialInformations& i, const uint8_t& keys_i_send, - Octet16 ltk, uint16_t ediv, std::array<uint8_t, 8> rand, - Octet16 irk, Address identity_address, - AddrType identity_addres_type, Octet16 signature_key) { - if (keys_i_send & KeyMaskEnc) { - log::info("Sending Encryption Information"); - SendL2capPacket(i, EncryptionInformationBuilder::Create(ltk)); - log::info("Sending Central Identification"); - SendL2capPacket(i, CentralIdentificationBuilder::Create(ediv, rand)); - } - - if (keys_i_send & KeyMaskId) { - log::info("Sending Identity Information"); - SendL2capPacket(i, IdentityInformationBuilder::Create(irk)); - log::info("Sending Identity Address Information"); - SendL2capPacket( - i, IdentityAddressInformationBuilder::Create(identity_addres_type, identity_address)); - } - - if (keys_i_send & KeyMaskSign) { - log::info("Sending Signing Information"); - SendL2capPacket(i, SigningInformationBuilder::Create(signature_key)); - } -} - -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/pairing_handler_le.h b/system/gd/security/pairing_handler_le.h deleted file mode 100644 index 753e43678e..0000000000 --- a/system/gd/security/pairing_handler_le.h +++ /dev/null @@ -1,559 +0,0 @@ -/****************************************************************************** - * - * Copyright 2019 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. - * - ******************************************************************************/ - -#pragma once - -#include <bluetooth/log.h> - -#include <array> -#include <chrono> -#include <condition_variable> -#include <mutex> -#include <optional> -#include <queue> -#include <thread> -#include <variant> - -#include "hci/hci_packets.h" -#include "hci/le_security_interface.h" -#include "security/ecdh_keys.h" -#include "security/initial_informations.h" -#include "security/pairing_failure.h" -#include "security/smp_packets.h" - -// Code generated by PDL does not allow us ot do || and && operations on bits -// efficiently. Use those masks on fields requiring them until this is solved -constexpr uint8_t AuthReqMaskBondingFlag = 0x01; -constexpr uint8_t AuthReqMaskMitm = 0x04; -constexpr uint8_t AuthReqMaskSc = 0x08; -constexpr uint8_t AuthReqMaskKeypress = 0x10; -constexpr uint8_t AuthReqMaskCt2 = 0x20; - -constexpr uint8_t KeyMaskEnc = 0x01; -constexpr uint8_t KeyMaskId = 0x02; -constexpr uint8_t KeyMaskSign = 0x04; -constexpr uint8_t KeyMaskLink = 0x08; - -using bluetooth::hci::EncryptionChangeView; -using bluetooth::hci::EncryptionKeyRefreshCompleteView; - -namespace bluetooth { -namespace security { - -/* This class represents an event send from other subsystems into SMP Pairing Handler, - * i.e. user request from the UI, L2CAP or HCI interaction */ -class PairingEvent { -public: - enum TYPE { EXIT, L2CAP, HCI_EVENT, UI }; - TYPE type; - - std::optional<CommandView> l2cap_packet; - - std::optional<hci::EventView> hci_event; - - enum UI_ACTION_TYPE { PAIRING_ACCEPTED, CONFIRM_YESNO, PASSKEY }; - UI_ACTION_TYPE ui_action; - uint32_t ui_value; - - PairingEvent(TYPE type) : type(type) {} - PairingEvent(CommandView l2cap_packet) : type(L2CAP), l2cap_packet(l2cap_packet) {} - PairingEvent(UI_ACTION_TYPE ui_action, uint32_t ui_value) - : type(UI), ui_action(ui_action), ui_value(ui_value) {} - PairingEvent(hci::EventView hci_event) : type(HCI_EVENT), hci_event(hci_event) {} -}; - -constexpr int SMP_TIMEOUT = 30; - -using CommandViewOrFailure = std::variant<CommandView, PairingFailure>; -using Phase1Result = std::pair<PairingRequestView /* pairning_request*/, - PairingResponseView /* pairing_response */>; -using Phase1ResultOrFailure = std::variant<PairingFailure, Phase1Result>; -using KeyExchangeResult = std::tuple<EcdhPublicKey /* PKa */, EcdhPublicKey /* PKb */, - std::array<uint8_t, 32> /*dhkey*/>; -using Stage1Result = std::tuple<hci::Octet16, hci::Octet16, hci::Octet16, hci::Octet16>; -using Stage1ResultOrFailure = std::variant<PairingFailure, Stage1Result>; -using Stage2ResultOrFailure = std::variant<PairingFailure, hci::Octet16 /* LTK */>; -using DistributedKeysOrFailure = std::variant<PairingFailure, DistributedKeys, std::monostate>; - -using LegacyStage1Result = hci::Octet16 /*TK*/; -using LegacyStage1ResultOrFailure = std::variant<PairingFailure, LegacyStage1Result>; -using StkOrFailure = std::variant<PairingFailure, hci::Octet16 /* STK */>; - -/* PairingHandlerLe takes care of the Pairing process. Pairing is strictly defined - * exchange of messages and UI interactions, divided into PHASES. - * - * Each PairingHandlerLe have a thread executing |PairingMain| method. Thread is - * blocked when waiting for UI/L2CAP/HCI interactions, and moves through all the - * phases. - */ -class PairingHandlerLe { -public: - // This is the phase of pairing as defined in BT Spec (with exception of - // accept prompt) - // * ACCEPT_PROMPT - we're waiting for the user to accept remotely initiated pairing - // * PHASE1 - feature exchange - // * PHASE2 - authentication - // * PHASE3 - key exchange - enum PAIRING_PHASE { ACCEPT_PROMPT, PHASE1, PHASE2, PHASE3 }; - PAIRING_PHASE phase; - - // All the knowledge to initiate the pairing process must be passed into this function - PairingHandlerLe(PAIRING_PHASE phase, InitialInformations informations) - : phase(phase), queue_guard(), thread_(&PairingHandlerLe::PairingMain, this, informations) {} - - ~PairingHandlerLe() { - SendExitSignal(); - // we need ot check if thread is joinable, because tests call join form - // within WaitUntilPairingFinished - if (thread_.joinable()) { - thread_.join(); - } - } - - void PairingMain(InitialInformations i); - - Phase1ResultOrFailure ExchangePairingFeature(const InitialInformations& i); - - void SendL2capPacket(const InitialInformations& i, - std::unique_ptr<bluetooth::security::CommandBuilder> command) { - i.proper_l2cap_interface->Enqueue(std::move(command), i.l2cap_handler); - } - - void SendHciLeStartEncryption(const InitialInformations& i, uint16_t conn_handle, - const std::array<uint8_t, 8>& rand, const uint16_t& ediv, - const hci::Octet16& ltk) { - i.le_security_interface->EnqueueCommand( - hci::LeStartEncryptionBuilder::Create(conn_handle, rand, ediv, ltk), - i.l2cap_handler->BindOnce([](hci::CommandStatusView) { - // TODO: handle command status. It's important - can show we are not - // connected any more. - - // TODO: if anything useful must be done there, use some sort of proper - // handler, wait/notify, and execute on the handler thread - })); - } - - void SendHciLeLongTermKeyReply(const InitialInformations& i, uint16_t conn_handle, - const hci::Octet16& ltk) { - i.le_security_interface->EnqueueCommand( - hci::LeLongTermKeyRequestReplyBuilder::Create(conn_handle, ltk), - i.l2cap_handler->BindOnce([](hci::CommandCompleteView) {})); - } - - std::variant<PairingFailure, EncryptionChangeView, EncryptionKeyRefreshCompleteView> - WaitEncryptionChanged() { - PairingEvent e = WaitForEvent(); - if (e.type != PairingEvent::HCI_EVENT) { - return PairingFailure("Was expecting HCI event but received something else"); - } - - if (!e.hci_event->IsValid()) { - return PairingFailure("Received invalid HCI event"); - } - - if (e.hci_event->GetEventCode() == hci::EventCode::ENCRYPTION_CHANGE) { - EncryptionChangeView enc_chg_packet = EncryptionChangeView::Create(*e.hci_event); - if (!enc_chg_packet.IsValid()) { - return PairingFailure("Invalid Encryption Change packet received"); - } - return enc_chg_packet; - } - - if (e.hci_event->GetEventCode() == hci::EventCode::ENCRYPTION_KEY_REFRESH_COMPLETE) { - hci::EncryptionKeyRefreshCompleteView enc_packet = - EncryptionKeyRefreshCompleteView::Create(*e.hci_event); - if (!enc_packet.IsValid()) { - return PairingFailure("Invalid Key Refresh packet received"); - } - return enc_packet; - } - - return PairingFailure( - "Was expecting Encryption Change or Key Refresh Complete but received something else"); - } - - std::variant<PairingFailure, hci::LeLongTermKeyRequestView> WaitLeLongTermKeyRequest() { - PairingEvent e = WaitForEvent(); - if (e.type != PairingEvent::HCI_EVENT) { - return PairingFailure("Was expecting HCI event but received something else"); - } - - if (!e.hci_event->IsValid()) { - return PairingFailure("Received invalid HCI event"); - } - - if (e.hci_event->GetEventCode() != hci::EventCode::LE_META_EVENT) { - return PairingFailure("Was expecting LE event"); - } - - hci::LeMetaEventView le_event = hci::LeMetaEventView::Create(*e.hci_event); - if (!le_event.IsValid()) { - return PairingFailure("Invalid LE Event received"); - } - - if (le_event.GetSubeventCode() != hci::SubeventCode::LONG_TERM_KEY_REQUEST) { - return PairingFailure("Was expecting Long Term Key Request"); - } - - hci::LeLongTermKeyRequestView ltk_req_packet = hci::LeLongTermKeyRequestView::Create(le_event); - if (!ltk_req_packet.IsValid()) { - return PairingFailure("Invalid LE Long Term Key Request received"); - } - - return ltk_req_packet; - } - - inline bool IAmCentral(const InitialInformations& i) { return i.my_role == hci::Role::CENTRAL; } - - /* This function generates data that should be passed to remote device, except - the private key. */ - static MyOobData GenerateOobData(); - - std::variant<PairingFailure, KeyExchangeResult> ExchangePublicKeys( - const InitialInformations& i, OobDataFlag remote_have_oob_data); - - Stage1ResultOrFailure DoSecureConnectionsStage1(const InitialInformations& i, - const EcdhPublicKey& PKa, - const EcdhPublicKey& PKb, - const PairingRequestView& pairing_request, - const PairingResponseView& pairing_response); - - Stage1ResultOrFailure SecureConnectionsNumericComparison(const InitialInformations& i, - const EcdhPublicKey& PKa, - const EcdhPublicKey& PKb); - - Stage1ResultOrFailure SecureConnectionsJustWorks(const InitialInformations& i, - const EcdhPublicKey& PKa, - const EcdhPublicKey& PKb); - - Stage1ResultOrFailure SecureConnectionsPasskeyEntry(const InitialInformations& i, - const EcdhPublicKey& PKa, - const EcdhPublicKey& PKb, - IoCapability my_iocaps, - IoCapability remote_iocaps); - - Stage1ResultOrFailure SecureConnectionsOutOfBand(const InitialInformations& i, - const EcdhPublicKey& Pka, - const EcdhPublicKey& Pkb, - OobDataFlag my_oob_flag, - OobDataFlag remote_oob_flag); - - Stage2ResultOrFailure DoSecureConnectionsStage2( - const InitialInformations& i, const EcdhPublicKey& PKa, const EcdhPublicKey& PKb, - const PairingRequestView& pairing_request, const PairingResponseView& pairing_response, - const Stage1Result stage1result, const std::array<uint8_t, 32>& dhkey); - - DistributedKeysOrFailure DistributeKeys(const InitialInformations& i, - const PairingResponseView& pairing_response, - bool isSecureConnections); - - DistributedKeysOrFailure ReceiveKeys(const uint8_t& keys_i_receive); - - LegacyStage1ResultOrFailure DoLegacyStage1(const InitialInformations& i, - const PairingRequestView& pairing_request, - const PairingResponseView& pairing_response); - LegacyStage1ResultOrFailure LegacyOutOfBand(const InitialInformations& i); - LegacyStage1ResultOrFailure LegacyJustWorks(); - LegacyStage1ResultOrFailure LegacyPasskeyEntry(const InitialInformations& i, - const IoCapability& my_iocaps, - const IoCapability& remote_iocaps); - StkOrFailure DoLegacyStage2(const InitialInformations& i, - const PairingRequestView& pairing_request, - const PairingResponseView& pairing_response, const hci::Octet16& tk); - - void SendKeys(const InitialInformations& i, const uint8_t& keys_i_send, hci::Octet16 ltk, - uint16_t ediv, std::array<uint8_t, 8> rand, hci::Octet16 irk, - Address identity_address, AddrType identity_addres_type, - hci::Octet16 signature_key); - - /* This can be called from any thread to immediately finish the pairing in progress. */ - void SendExitSignal() { - { - std::unique_lock<std::mutex> lock(queue_guard); - queue.push(PairingEvent(PairingEvent::EXIT)); - } - pairing_thread_blocker_.notify_one(); - } - - /* SMP Command received from remote device */ - void OnCommandView(CommandView packet) { - { - std::unique_lock<std::mutex> lock(queue_guard); - queue.push(PairingEvent(std::move(packet))); - } - pairing_thread_blocker_.notify_one(); - } - - /* SMP Command received from remote device */ - void OnHciEvent(hci::EventView hci_event) { - { - std::unique_lock<std::mutex> lock(queue_guard); - queue.push(PairingEvent(std::move(hci_event))); - } - pairing_thread_blocker_.notify_one(); - } - - /* Interaction from user */ - void OnUiAction(PairingEvent::UI_ACTION_TYPE ui_action, uint32_t ui_value) { - { - std::unique_lock<std::mutex> lock(queue_guard); - queue.push(PairingEvent(ui_action, ui_value)); - } - pairing_thread_blocker_.notify_one(); - } - - /* HCI LE event received from remote device */ - void OnHciLeEvent(hci::LeMetaEventView hci_event) { - { - std::unique_lock<std::mutex> lock(queue_guard); - queue.push(PairingEvent(std::move(hci_event))); - } - pairing_thread_blocker_.notify_one(); - } - - /* Blocks the pairing process until some external interaction, or timeout happens */ - PairingEvent WaitForEvent() { - std::unique_lock<std::mutex> lock(queue_guard); - do { - if (!queue.empty()) { - PairingEvent e = queue.front(); - queue.pop(); - return e; - } - // This releases the lock while blocking. - if (pairing_thread_blocker_.wait_for(lock, std::chrono::seconds(SMP_TIMEOUT)) == - std::cv_status::timeout) { - return PairingEvent(PairingEvent::EXIT); - } - - } while (true); - } - - std::optional<PairingEvent> WaitUiPairingAccept() { - PairingEvent e = WaitForEvent(); - if (e.type == PairingEvent::UI && e.ui_action == PairingEvent::PAIRING_ACCEPTED) { - return e; - } else { - return std::nullopt; - } - } - - std::optional<PairingEvent> WaitUiConfirmYesNo() { - PairingEvent e = WaitForEvent(); - if (e.type == PairingEvent::UI && e.ui_action == PairingEvent::CONFIRM_YESNO) { - return e; - } else { - return std::nullopt; - } - } - - std::optional<PairingEvent> WaitUiPasskey() { - PairingEvent e = WaitForEvent(); - - // It's possible to receive PAIRING_CONFIRM from remote device while waiting for the passkey. - // Store it until it's needed. - if (e.type == PairingEvent::L2CAP) { - auto l2cap_packet = e.l2cap_packet.value(); - if (!l2cap_packet.IsValid()) { - log::warn("Malformed L2CAP packet received!"); - return std::nullopt; - } - - const auto& received_code = l2cap_packet.GetCode(); - if (received_code != Code::PAIRING_CONFIRM) { - log::warn("Was waiting for passkey, received bad packet instead!"); - return std::nullopt; - } - - auto pkt = PairingConfirmView::Create(l2cap_packet); - if (!pkt.IsValid()) { - log::warn("Malformed PAIRING_CONFIRM packet"); - return std::nullopt; - } - - cached_pariring_confirm_view = std::make_unique<PairingConfirmView>(pkt); - e = WaitForEvent(); - } - - if (e.type == PairingEvent::UI && e.ui_action == PairingEvent::PASSKEY) { - return e; - } else { - return std::nullopt; - } - } - - template <Code C> - struct CodeToPacketView; - template <> - struct CodeToPacketView<Code::PAIRING_REQUEST> { - typedef PairingRequestView type; - }; - template <> - struct CodeToPacketView<Code::PAIRING_RESPONSE> { - typedef PairingResponseView type; - }; - template <> - struct CodeToPacketView<Code::PAIRING_CONFIRM> { - typedef PairingConfirmView type; - }; - template <> - struct CodeToPacketView<Code::PAIRING_RANDOM> { - typedef PairingRandomView type; - }; - template <> - struct CodeToPacketView<Code::PAIRING_FAILED> { - typedef PairingFailedView type; - }; - template <> - struct CodeToPacketView<Code::ENCRYPTION_INFORMATION> { - typedef EncryptionInformationView type; - }; - template <> - struct CodeToPacketView<Code::CENTRAL_IDENTIFICATION> { - typedef CentralIdentificationView type; - }; - template <> - struct CodeToPacketView<Code::IDENTITY_INFORMATION> { - typedef IdentityInformationView type; - }; - template <> - struct CodeToPacketView<Code::IDENTITY_ADDRESS_INFORMATION> { - typedef IdentityAddressInformationView type; - }; - template <> - struct CodeToPacketView<Code::SIGNING_INFORMATION> { - typedef SigningInformationView type; - }; - template <> - struct CodeToPacketView<Code::SECURITY_REQUEST> { - typedef SecurityRequestView type; - }; - template <> - struct CodeToPacketView<Code::PAIRING_PUBLIC_KEY> { - typedef PairingPublicKeyView type; - }; - template <> - struct CodeToPacketView<Code::PAIRING_DH_KEY_CHECK> { - typedef PairingDhKeyCheckView type; - }; - template <> - struct CodeToPacketView<Code::PAIRING_KEYPRESS_NOTIFICATION> { - typedef PairingKeypressNotificationView type; - }; - - template <Code CODE> - std::variant<typename CodeToPacketView<CODE>::type, PairingFailure> WaitPacket() { - PairingEvent e = WaitForEvent(); - switch (e.type) { - case PairingEvent::EXIT: - return PairingFailure( - /*FROM_HERE,*/ "Was expecting L2CAP Packet " + CodeText(CODE) + - ", but received EXIT instead"); - - case PairingEvent::HCI_EVENT: - return PairingFailure( - /*FROM_HERE,*/ "Was expecting L2CAP Packet " + CodeText(CODE) + - ", but received HCI_EVENT instead"); - - case PairingEvent::UI: - return PairingFailure( - /*FROM_HERE,*/ "Was expecting L2CAP Packet " + CodeText(CODE) + - ", but received UI instead"); - - case PairingEvent::L2CAP: { - auto l2cap_packet = e.l2cap_packet.value(); - if (!l2cap_packet.IsValid()) { - return PairingFailure("Malformed L2CAP packet received!"); - } - - const auto& received_code = l2cap_packet.GetCode(); - if (received_code != CODE) { - if (received_code == Code::PAIRING_FAILED) { - auto pkt = PairingFailedView::Create(l2cap_packet); - if (!pkt.IsValid()) { - return PairingFailure("Malformed " + CodeText(CODE) + " packet"); - } - return PairingFailure(/*FROM_HERE,*/ - "Was expecting " + CodeText(CODE) + - ", but received PAIRING_FAILED instead", - pkt.GetReason()); - } - - return PairingFailure(/*FROM_HERE,*/ - "Was expecting " + CodeText(CODE) + ", but received " + - CodeText(received_code) + " instead", - received_code); - } - - auto pkt = CodeToPacketView<CODE>::type::Create(l2cap_packet); - if (!pkt.IsValid()) { - return PairingFailure("Malformed " + CodeText(CODE) + " packet"); - } - return pkt; - } - } - } - - auto WaitPairingRequest() { return WaitPacket<Code::PAIRING_REQUEST>(); } - - auto WaitPairingResponse() { return WaitPacket<Code::PAIRING_RESPONSE>(); } - - std::variant<bluetooth::security::PairingConfirmView, bluetooth::security::PairingFailure> - WaitPairingConfirm() { - if (cached_pariring_confirm_view) { - PairingConfirmView pkt = *cached_pariring_confirm_view; - cached_pariring_confirm_view.release(); - return pkt; - } - return WaitPacket<Code::PAIRING_CONFIRM>(); - } - - auto WaitPairingRandom() { return WaitPacket<Code::PAIRING_RANDOM>(); } - - auto WaitPairingPublicKey() { return WaitPacket<Code::PAIRING_PUBLIC_KEY>(); } - - auto WaitPairingDHKeyCheck() { return WaitPacket<Code::PAIRING_DH_KEY_CHECK>(); } - - auto WaitEncryptionInformationRequest() { return WaitPacket<Code::ENCRYPTION_INFORMATION>(); } - - auto WaitEncryptionInformation() { return WaitPacket<Code::ENCRYPTION_INFORMATION>(); } - - auto WaitCentralIdentification() { return WaitPacket<Code::CENTRAL_IDENTIFICATION>(); } - - auto WaitIdentityInformation() { return WaitPacket<Code::IDENTITY_INFORMATION>(); } - - auto WaitIdentityAddressInformation() { return WaitPacket<Code::IDENTITY_ADDRESS_INFORMATION>(); } - - auto WaitSigningInformation() { return WaitPacket<Code::SIGNING_INFORMATION>(); } - - /* This is just for test, never use in production code! */ - void WaitUntilPairingFinished() { thread_.join(); } - -private: - std::condition_variable pairing_thread_blocker_; - - std::mutex queue_guard; - std::queue<PairingEvent> queue; - - std::thread thread_; - - // holds pairing_confirm, if received out of order - std::unique_ptr<PairingConfirmView> cached_pariring_confirm_view; -}; -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/pairing_handler_le_legacy.cc b/system/gd/security/pairing_handler_le_legacy.cc deleted file mode 100644 index da35d83b81..0000000000 --- a/system/gd/security/pairing_handler_le_legacy.cc +++ /dev/null @@ -1,245 +0,0 @@ -/****************************************************************************** - * - * Copyright 2019 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 <bluetooth/log.h> - -#include "hci/octets.h" -#include "os/rand.h" -#include "security/pairing_handler_le.h" - -using bluetooth::os::GenerateRandom; - -namespace bluetooth { -namespace security { - -using hci::Octet16; - -LegacyStage1ResultOrFailure PairingHandlerLe::DoLegacyStage1( - const InitialInformations& i, const PairingRequestView& pairing_request, - const PairingResponseView& pairing_response) { - if (((pairing_request.GetAuthReq() | pairing_response.GetAuthReq()) & AuthReqMaskMitm) == 0) { - // If both devices have not set MITM option, Just Works shall be used - return LegacyJustWorks(); - } - - if (pairing_request.GetOobDataFlag() == OobDataFlag::PRESENT && - pairing_response.GetOobDataFlag() == OobDataFlag::PRESENT) { - // OobDataFlag remote_oob_flag = IAmCentral(i) ? pairing_response.GetOobDataFlag() : - // pairing_request.GetOobDataFlag(); OobDataFlag my_oob_flag = IAmCentral(i) ? - // pairing_request.GetOobDataFlag() : pairing_response.GetOobDataFlag(); - return LegacyOutOfBand(i); - } - - const auto& iom = pairing_request.GetIoCapability(); - const auto& ios = pairing_response.GetIoCapability(); - - if (iom == IoCapability::NO_INPUT_NO_OUTPUT || ios == IoCapability::NO_INPUT_NO_OUTPUT) { - return LegacyJustWorks(); - } - - if ((iom == IoCapability::DISPLAY_ONLY || iom == IoCapability::DISPLAY_YES_NO) && - (ios == IoCapability::DISPLAY_ONLY || ios == IoCapability::DISPLAY_YES_NO)) { - return LegacyJustWorks(); - } - - // This if() should not be needed, these are only combinations left. - if (iom == IoCapability::KEYBOARD_DISPLAY || iom == IoCapability::KEYBOARD_ONLY || - ios == IoCapability::KEYBOARD_DISPLAY || ios == IoCapability::KEYBOARD_ONLY) { - IoCapability my_iocaps = IAmCentral(i) ? iom : ios; - IoCapability remote_iocaps = IAmCentral(i) ? ios : iom; - return LegacyPasskeyEntry(i, my_iocaps, remote_iocaps); - } - - // We went through all possble combinations. - log::fatal("This should never happen"); - return LegacyJustWorks(); -} - -LegacyStage1ResultOrFailure PairingHandlerLe::LegacyJustWorks() { - log::info("Legacy Just Works start"); - return Octet16{0}; -} - -LegacyStage1ResultOrFailure PairingHandlerLe::LegacyPasskeyEntry( - const InitialInformations& i, const IoCapability& my_iocaps, - const IoCapability& remote_iocaps) { - bool i_am_displaying = false; - if (my_iocaps == IoCapability::DISPLAY_ONLY || my_iocaps == IoCapability::DISPLAY_YES_NO) { - i_am_displaying = true; - } else if (IAmCentral(i) && remote_iocaps == IoCapability::KEYBOARD_DISPLAY && - my_iocaps == IoCapability::KEYBOARD_DISPLAY) { - i_am_displaying = true; - } else if (my_iocaps == IoCapability::KEYBOARD_DISPLAY && - remote_iocaps == IoCapability::KEYBOARD_ONLY) { - i_am_displaying = true; - } - - log::info("Passkey Entry start {}", i_am_displaying ? "displaying" : "accepting"); - - uint32_t passkey; - if (i_am_displaying) { - // generate passkey in a valid range - passkey = GenerateRandom(); - passkey &= 0x0fffff; /* maximum 20 significant bits */ - constexpr uint32_t PASSKEY_MAX = 999999; - if (passkey > PASSKEY_MAX) { - passkey >>= 1; - } - - ConfirmationData data(i.remote_connection_address, i.remote_name, passkey); - i.user_interface_handler->Post( - common::BindOnce(&UI::DisplayConfirmValue, common::Unretained(i.user_interface), data)); - } else { - ConfirmationData data(i.remote_connection_address, i.remote_name); - i.user_interface_handler->Post(common::BindOnce(&UI::DisplayEnterPasskeyDialog, - common::Unretained(i.user_interface), data)); - std::optional<PairingEvent> response = WaitUiPasskey(); - if (!response) { - return PairingFailure("Passkey did not arrive!"); - } - - passkey = response->ui_value; - } - - Octet16 tk{0}; - tk[0] = (uint8_t)(passkey); - tk[1] = (uint8_t)(passkey >> 8); - tk[2] = (uint8_t)(passkey >> 16); - tk[3] = (uint8_t)(passkey >> 24); - - log::info("Passkey Entry finish"); - return tk; -} - -LegacyStage1ResultOrFailure PairingHandlerLe::LegacyOutOfBand(const InitialInformations& i) { - return i.remote_oob_data->security_manager_tk_value; -} - -StkOrFailure PairingHandlerLe::DoLegacyStage2(const InitialInformations& i, - const PairingRequestView& pairing_request, - const PairingResponseView& pairing_response, - const Octet16& tk) { - log::info("Legacy Step 2 start"); - std::vector<uint8_t> preq(pairing_request.begin(), pairing_request.end()); - std::vector<uint8_t> pres(pairing_response.begin(), pairing_response.end()); - - Octet16 mrand, srand; - if (IAmCentral(i)) { - mrand = GenerateRandom<16>(); - - // log::info("{} tk = {}", IAmCentral(i), base::HexEncode(tk.data(), tk.size())); - // log::info("{} mrand = {}", IAmCentral(i), base::HexEncode(mrand.data(), mrand.size())); - // log::info("{} pres = {}", IAmCentral(i), base::HexEncode(pres.data(), pres.size())); - // log::info("{} preq = {}", IAmCentral(i), base::HexEncode(preq.data(), preq.size())); - - Octet16 mconfirm = crypto_toolbox::c1(tk, mrand, preq.data(), pres.data(), - (uint8_t)i.my_connection_address.GetAddressType(), - i.my_connection_address.GetAddress().data(), - (uint8_t)i.remote_connection_address.GetAddressType(), - i.remote_connection_address.GetAddress().data()); - - // log::info("{} mconfirm = {}", IAmCentral(i), base::HexEncode(mconfirm.data(), - // mconfirm.size())); - - log::info("Central sends Mconfirm"); - SendL2capPacket(i, PairingConfirmBuilder::Create(mconfirm)); - - log::info("Central waits for the Sconfirm"); - auto sconfirm_pkt = WaitPairingConfirm(); - if (std::holds_alternative<PairingFailure>(sconfirm_pkt)) { - return std::get<PairingFailure>(sconfirm_pkt); - } - Octet16 sconfirm = std::get<PairingConfirmView>(sconfirm_pkt).GetConfirmValue(); - - log::info("Central sends Mrand"); - SendL2capPacket(i, PairingRandomBuilder::Create(mrand)); - - log::info("Central waits for Srand"); - auto random_pkt = WaitPairingRandom(); - if (std::holds_alternative<PairingFailure>(random_pkt)) { - return std::get<PairingFailure>(random_pkt); - } - srand = std::get<PairingRandomView>(random_pkt).GetRandomValue(); - - // log::info("{} srand = {}", IAmCentral(i), base::HexEncode(srand.data(), srand.size())); - - Octet16 sconfirm_generated = crypto_toolbox::c1( - tk, srand, preq.data(), pres.data(), (uint8_t)i.my_connection_address.GetAddressType(), - i.my_connection_address.GetAddress().data(), - (uint8_t)i.remote_connection_address.GetAddressType(), - i.remote_connection_address.GetAddress().data()); - - if (sconfirm != sconfirm_generated) { - log::info("sconfirm does not match generated value"); - - SendL2capPacket(i, PairingFailedBuilder::Create(PairingFailedReason::CONFIRM_VALUE_FAILED)); - return PairingFailure("sconfirm does not match generated value"); - } - } else { - srand = GenerateRandom<16>(); - - std::vector<uint8_t> preq(pairing_request.begin(), pairing_request.end()); - std::vector<uint8_t> pres(pairing_response.begin(), pairing_response.end()); - - Octet16 sconfirm = crypto_toolbox::c1(tk, srand, preq.data(), pres.data(), - (uint8_t)i.remote_connection_address.GetAddressType(), - i.remote_connection_address.GetAddress().data(), - (uint8_t)i.my_connection_address.GetAddressType(), - i.my_connection_address.GetAddress().data()); - - log::info("Peripheral waits for the Mconfirm"); - auto mconfirm_pkt = WaitPairingConfirm(); - if (std::holds_alternative<PairingFailure>(mconfirm_pkt)) { - return std::get<PairingFailure>(mconfirm_pkt); - } - Octet16 mconfirm = std::get<PairingConfirmView>(mconfirm_pkt).GetConfirmValue(); - - log::info("Peripheral sends Sconfirm"); - SendL2capPacket(i, PairingConfirmBuilder::Create(sconfirm)); - - log::info("Peripheral waits for Mrand"); - auto random_pkt = WaitPairingRandom(); - if (std::holds_alternative<PairingFailure>(random_pkt)) { - return std::get<PairingFailure>(random_pkt); - } - mrand = std::get<PairingRandomView>(random_pkt).GetRandomValue(); - - Octet16 mconfirm_generated = - crypto_toolbox::c1(tk, mrand, preq.data(), pres.data(), - (uint8_t)i.remote_connection_address.GetAddressType(), - i.remote_connection_address.GetAddress().data(), - (uint8_t)i.my_connection_address.GetAddressType(), - i.my_connection_address.GetAddress().data()); - - if (mconfirm != mconfirm_generated) { - log::info("mconfirm does not match generated value"); - SendL2capPacket(i, PairingFailedBuilder::Create(PairingFailedReason::CONFIRM_VALUE_FAILED)); - return PairingFailure("mconfirm does not match generated value"); - } - - log::info("Peripheral sends Srand"); - SendL2capPacket(i, PairingRandomBuilder::Create(srand)); - } - - log::info("Legacy stage 2 finish"); - - /* STK */ - return crypto_toolbox::s1(tk, mrand, srand); -} -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/pairing_handler_le_secure_connections.cc b/system/gd/security/pairing_handler_le_secure_connections.cc deleted file mode 100644 index a4ff418ce1..0000000000 --- a/system/gd/security/pairing_handler_le_secure_connections.cc +++ /dev/null @@ -1,506 +0,0 @@ -/****************************************************************************** - * - * Copyright 2019 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 <bluetooth/log.h> - -#include "crypto_toolbox/crypto_toolbox.h" -#include "hci/octets.h" -#include "os/rand.h" -#include "security/pairing_handler_le.h" - -using bluetooth::os::GenerateRandom; - -namespace bluetooth { -namespace security { -using hci::Octet16; - -std::variant<PairingFailure, KeyExchangeResult> PairingHandlerLe::ExchangePublicKeys( - const InitialInformations& i, OobDataFlag remote_have_oob_data) { - // Generate ECDH, or use one that was used for OOB data - const auto [private_key, public_key] = - (remote_have_oob_data == OobDataFlag::NOT_PRESENT || !i.my_oob_data) - ? GenerateECDHKeyPair() - : std::make_pair(i.my_oob_data->private_key, i.my_oob_data->public_key); - - log::info("Public key exchange start"); - std::unique_ptr<PairingPublicKeyBuilder> myPublicKey = - PairingPublicKeyBuilder::Create(public_key.x, public_key.y); - - if (!ValidateECDHPoint(public_key)) { - log::error("Can't validate my own public key!!!"); - return PairingFailure("Can't validate my own public key"); - } - - if (IAmCentral(i)) { - // Send pairing public key - log::info("Central sends out public key"); - SendL2capPacket(i, std::move(myPublicKey)); - } - - log::info("Waiting for Public key..."); - auto response = WaitPairingPublicKey(); - log::info("Received public key"); - if (std::holds_alternative<PairingFailure>(response)) { - return std::get<PairingFailure>(response); - } - - EcdhPublicKey remote_public_key; - auto ppkv = std::get<PairingPublicKeyView>(response); - remote_public_key.x = ppkv.GetPublicKeyX(); - remote_public_key.y = ppkv.GetPublicKeyY(); - log::info("Received Public key from remote"); - - if (public_key.x == remote_public_key.x) { - log::info("Remote and local public keys can't match"); - return PairingFailure("Remote and local public keys match"); - } - - // validate received public key - if (!ValidateECDHPoint(remote_public_key)) { - // TODO: Spec is unclear what should happend when the point is not on - // the correct curve: A device that detects an invalid public key from - // the peer at any point during the LE Secure Connections pairing - // process shall not use the resulting LTK, if any. - log::info("Can't validate remote public key"); - return PairingFailure("Can't validate remote public key"); - } - - if (!IAmCentral(i)) { - log::info("Peripheral sends out public key"); - // Send pairing public key - SendL2capPacket(i, std::move(myPublicKey)); - } - - log::info("Public key exchange finish"); - - std::array<uint8_t, 32> dhkey = ComputeDHKey(private_key, remote_public_key); - - const EcdhPublicKey& PKa = IAmCentral(i) ? public_key : remote_public_key; - const EcdhPublicKey& PKb = IAmCentral(i) ? remote_public_key : public_key; - - return KeyExchangeResult{PKa, PKb, dhkey}; -} - -Stage1ResultOrFailure PairingHandlerLe::DoSecureConnectionsStage1( - const InitialInformations& i, const EcdhPublicKey& PKa, const EcdhPublicKey& PKb, - const PairingRequestView& pairing_request, const PairingResponseView& pairing_response) { - if (((pairing_request.GetAuthReq() & AuthReqMaskMitm) == 0) && - ((pairing_response.GetAuthReq() & AuthReqMaskMitm) == 0)) { - // If both devices have not set MITM option, Just Works shall be used - return SecureConnectionsJustWorks(i, PKa, PKb); - } - - if (pairing_request.GetOobDataFlag() == OobDataFlag::PRESENT || - pairing_response.GetOobDataFlag() == OobDataFlag::PRESENT) { - OobDataFlag remote_oob_flag = - IAmCentral(i) ? pairing_response.GetOobDataFlag() : pairing_request.GetOobDataFlag(); - OobDataFlag my_oob_flag = - IAmCentral(i) ? pairing_request.GetOobDataFlag() : pairing_response.GetOobDataFlag(); - return SecureConnectionsOutOfBand(i, PKa, PKb, my_oob_flag, remote_oob_flag); - } - - const auto& iom = pairing_request.GetIoCapability(); - const auto& ios = pairing_response.GetIoCapability(); - - if ((iom == IoCapability::KEYBOARD_DISPLAY || iom == IoCapability::DISPLAY_YES_NO) && - (ios == IoCapability::KEYBOARD_DISPLAY || ios == IoCapability::DISPLAY_YES_NO)) { - return SecureConnectionsNumericComparison(i, PKa, PKb); - } - - if (iom == IoCapability::NO_INPUT_NO_OUTPUT || ios == IoCapability::NO_INPUT_NO_OUTPUT) { - return SecureConnectionsJustWorks(i, PKa, PKb); - } - - if ((iom == IoCapability::DISPLAY_ONLY || iom == IoCapability::DISPLAY_YES_NO) && - (ios == IoCapability::DISPLAY_ONLY || ios == IoCapability::DISPLAY_YES_NO)) { - return SecureConnectionsJustWorks(i, PKa, PKb); - } - - IoCapability my_iocaps = IAmCentral(i) ? iom : ios; - IoCapability remote_iocaps = IAmCentral(i) ? ios : iom; - return SecureConnectionsPasskeyEntry(i, PKa, PKb, my_iocaps, remote_iocaps); -} - -Stage2ResultOrFailure PairingHandlerLe::DoSecureConnectionsStage2( - const InitialInformations& i, const EcdhPublicKey& /* PKa */, - const EcdhPublicKey& /* PKb */, const PairingRequestView& pairing_request, - const PairingResponseView& pairing_response, const Stage1Result stage1result, - const std::array<uint8_t, 32>& dhkey) { - log::info("Authentication stage 2 started"); - - auto [Na, Nb, ra, rb] = stage1result; - - // 2.3.5.6.5 Authentication stage 2 long term key calculation - uint8_t a[7]; - uint8_t b[7]; - - if (IAmCentral(i)) { - memcpy(a, i.my_connection_address.GetAddress().data(), hci::Address::kLength); - a[6] = (uint8_t)i.my_connection_address.GetAddressType(); - memcpy(b, i.remote_connection_address.GetAddress().data(), hci::Address::kLength); - b[6] = (uint8_t)i.remote_connection_address.GetAddressType(); - } else { - memcpy(a, i.remote_connection_address.GetAddress().data(), hci::Address::kLength); - a[6] = (uint8_t)i.remote_connection_address.GetAddressType(); - memcpy(b, i.my_connection_address.GetAddress().data(), hci::Address::kLength); - b[6] = (uint8_t)i.my_connection_address.GetAddressType(); - } - - Octet16 ltk, mac_key; - crypto_toolbox::f5((uint8_t*)dhkey.data(), Na, Nb, a, b, &mac_key, <k); - - // DHKey exchange and check - - std::array<uint8_t, 3> iocapA{static_cast<uint8_t>(pairing_request.GetIoCapability()), - static_cast<uint8_t>(pairing_request.GetOobDataFlag()), - pairing_request.GetAuthReq()}; - std::array<uint8_t, 3> iocapB{static_cast<uint8_t>(pairing_response.GetIoCapability()), - static_cast<uint8_t>(pairing_response.GetOobDataFlag()), - pairing_response.GetAuthReq()}; - - // log::info("{} LTK = {}", IAmCentral(i), base::HexEncode(ltk.data(), ltk.size())); - // log::info("{} MAC_KEY = {}", IAmCentral(i), base::HexEncode(mac_key.data(), mac_key.size())); - // log::info("{} Na = {}", IAmCentral(i), base::HexEncode(Na.data(), Na.size())); - // log::info("{} Nb = {}", IAmCentral(i), base::HexEncode(Nb.data(), Nb.size())); - // log::info("{} ra = {}", IAmCentral(i), base::HexEncode(ra.data(), ra.size())); - // log::info("{} rb = {}", IAmCentral(i), base::HexEncode(rb.data(), rb.size())); - // log::info("{} iocapA = {}", IAmCentral(i), base::HexEncode(iocapA.data(), iocapA.size())); - // log::info("{} iocapB = {}", IAmCentral(i), base::HexEncode(iocapB.data(), iocapB.size())); - // log::info("{} a = {}", IAmCentral(i), base::HexEncode(a, 7)); - // log::info("{} b = {}", IAmCentral(i), base::HexEncode(b, 7)); - - Octet16 Ea = crypto_toolbox::f6(mac_key, Na, Nb, rb, iocapA.data(), a, b); - - Octet16 Eb = crypto_toolbox::f6(mac_key, Nb, Na, ra, iocapB.data(), b, a); - - if (IAmCentral(i)) { - // send Pairing DHKey Check - SendL2capPacket(i, PairingDhKeyCheckBuilder::Create(Ea)); - - auto response = WaitPairingDHKeyCheck(); - if (std::holds_alternative<PairingFailure>(response)) { - return std::get<PairingFailure>(response); - } - - if (std::get<PairingDhKeyCheckView>(response).GetDhKeyCheck() != Eb) { - log::info("Ea != Eb, aborting!"); - SendL2capPacket(i, PairingFailedBuilder::Create(PairingFailedReason::DHKEY_CHECK_FAILED)); - return PairingFailure("Ea != Eb"); - } - } else { - auto response = WaitPairingDHKeyCheck(); - if (std::holds_alternative<PairingFailure>(response)) { - return std::get<PairingFailure>(response); - } - - if (std::get<PairingDhKeyCheckView>(response).GetDhKeyCheck() != Ea) { - log::info("Ea != Eb, aborting!"); - SendL2capPacket(i, PairingFailedBuilder::Create(PairingFailedReason::DHKEY_CHECK_FAILED)); - return PairingFailure("Ea != Eb"); - } - - // send Pairing DHKey Check - SendL2capPacket(i, PairingDhKeyCheckBuilder::Create(Eb)); - } - - log::info("Authentication stage 2 (DHKey checks) finished"); - return ltk; -} - -Stage1ResultOrFailure PairingHandlerLe::SecureConnectionsOutOfBand(const InitialInformations& i, - const EcdhPublicKey& Pka, - const EcdhPublicKey& Pkb, - OobDataFlag my_oob_flag, - OobDataFlag remote_oob_flag) { - log::info("Out Of Band start"); - - Octet16 zeros{0}; - Octet16 localR = - (remote_oob_flag == OobDataFlag::PRESENT && i.my_oob_data) ? i.my_oob_data->r : zeros; - Octet16 remoteR; - - if (my_oob_flag == OobDataFlag::NOT_PRESENT || - (my_oob_flag == OobDataFlag::PRESENT && !i.remote_oob_data)) { - /* we have send the OOB data, but not received them. remote will check if - * C value is correct */ - remoteR = zeros; - } else { - remoteR = i.remote_oob_data->le_sc_r; - Octet16 remoteC = i.remote_oob_data->le_sc_c; - - Octet16 remoteC2; - if (IAmCentral(i)) { - remoteC2 = crypto_toolbox::f4((uint8_t*)Pkb.x.data(), (uint8_t*)Pkb.x.data(), remoteR, 0); - } else { - remoteC2 = crypto_toolbox::f4((uint8_t*)Pka.x.data(), (uint8_t*)Pka.x.data(), remoteR, 0); - } - - if (remoteC2 != remoteC) { - log::error("C_computed != C_from_remote, aborting!"); - return PairingFailure("C_computed != C_from_remote, aborting"); - } - } - - Octet16 Na, Nb, ra, rb; - if (IAmCentral(i)) { - ra = localR; - rb = remoteR; - Na = GenerateRandom<16>(); - // Send Pairing Random - SendL2capPacket(i, PairingRandomBuilder::Create(Na)); - - log::info("Central waits for Nb"); - auto random = WaitPairingRandom(); - if (std::holds_alternative<PairingFailure>(random)) { - return std::get<PairingFailure>(random); - } - Nb = std::get<PairingRandomView>(random).GetRandomValue(); - } else { - ra = remoteR; - rb = localR; - Nb = GenerateRandom<16>(); - - log::info("Peripheral waits for random"); - auto random = WaitPairingRandom(); - if (std::holds_alternative<PairingFailure>(random)) { - return std::get<PairingFailure>(random); - } - Na = std::get<PairingRandomView>(random).GetRandomValue(); - - SendL2capPacket(i, PairingRandomBuilder::Create(Nb)); - } - - return Stage1Result{Na, Nb, ra, rb}; -} - -Stage1ResultOrFailure PairingHandlerLe::SecureConnectionsPasskeyEntry(const InitialInformations& i, - const EcdhPublicKey& PKa, - const EcdhPublicKey& PKb, - IoCapability my_iocaps, - IoCapability remote_iocaps) { - log::info("Passkey Entry start"); - Octet16 Na, Nb, ra{0}, rb{0}; - - uint32_t passkey; - - if (my_iocaps == IoCapability::DISPLAY_ONLY || remote_iocaps == IoCapability::KEYBOARD_ONLY) { - // I display - passkey = GenerateRandom(); - passkey &= 0x0fffff; /* maximum 20 significant bytes */ - constexpr uint32_t PASSKEY_MAX = 999999; - while (passkey > PASSKEY_MAX) { - passkey >>= 1; - } - - ConfirmationData data(i.remote_connection_address, i.remote_name, passkey); - i.user_interface_handler->Post( - common::BindOnce(&UI::DisplayPasskey, common::Unretained(i.user_interface), data)); - - } else if (my_iocaps == IoCapability::KEYBOARD_ONLY || - remote_iocaps == IoCapability::DISPLAY_ONLY) { - ConfirmationData data(i.remote_connection_address, i.remote_name); - i.user_interface_handler->Post(common::BindOnce(&UI::DisplayEnterPasskeyDialog, - common::Unretained(i.user_interface), data)); - std::optional<PairingEvent> response = WaitUiPasskey(); - if (!response) { - return PairingFailure("Passkey did not arrive!"); - } - - passkey = response->ui_value; - - /*TODO: shall we send "Keypress Notification" after each key ? This would - * have impact on the SMP timeout*/ - - } else { - log::fatal("THIS SHOULD NEVER HAPPEN"); - return PairingFailure("FATAL!"); - } - - uint32_t bitmask = 0x01; - for (int loop = 0; loop < 20; loop++, bitmask <<= 1) { - log::info("Iteration no {}", loop); - bool bit_set = ((bitmask & passkey) != 0); - uint8_t ri = bit_set ? 0x81 : 0x80; - - Octet16 Cai, Cbi, Nai, Nbi; - if (IAmCentral(i)) { - Nai = GenerateRandom<16>(); - - Cai = crypto_toolbox::f4((uint8_t*)PKa.x.data(), (uint8_t*)PKb.x.data(), Nai, ri); - - // Send Pairing Confirm - log::info("Central sends Cai"); - SendL2capPacket(i, PairingConfirmBuilder::Create(Cai)); - - log::info("Central waits for the Cbi"); - auto confirm = WaitPairingConfirm(); - if (std::holds_alternative<PairingFailure>(confirm)) { - return std::get<PairingFailure>(confirm); - } - Cbi = std::get<PairingConfirmView>(confirm).GetConfirmValue(); - - // Send Pairing Random - SendL2capPacket(i, PairingRandomBuilder::Create(Nai)); - - log::info("Central waits for Nbi"); - auto random = WaitPairingRandom(); - if (std::holds_alternative<PairingFailure>(random)) { - return std::get<PairingFailure>(random); - } - Nbi = std::get<PairingRandomView>(random).GetRandomValue(); - - Octet16 Cbi2 = crypto_toolbox::f4((uint8_t*)PKb.x.data(), (uint8_t*)PKa.x.data(), Nbi, ri); - if (Cbi != Cbi2) { - log::info("Cai != Cbi, aborting!"); - SendL2capPacket(i, PairingFailedBuilder::Create(PairingFailedReason::CONFIRM_VALUE_FAILED)); - return PairingFailure("Cai != Cbi"); - } - } else { - Nbi = GenerateRandom<16>(); - // Compute confirm - Cbi = crypto_toolbox::f4((uint8_t*)PKb.x.data(), (uint8_t*)PKa.x.data(), Nbi, ri); - - log::info("Peripheral waits for the Cai"); - auto confirm = WaitPairingConfirm(); - if (std::holds_alternative<PairingFailure>(confirm)) { - return std::get<PairingFailure>(confirm); - } - Cai = std::get<PairingConfirmView>(confirm).GetConfirmValue(); - - // Send Pairing Confirm - log::info("Peripheral sends confirmation"); - SendL2capPacket(i, PairingConfirmBuilder::Create(Cbi)); - - log::info("Peripheral waits for random"); - auto random = WaitPairingRandom(); - if (std::holds_alternative<PairingFailure>(random)) { - return std::get<PairingFailure>(random); - } - Nai = std::get<PairingRandomView>(random).GetRandomValue(); - - Octet16 Cai2 = crypto_toolbox::f4((uint8_t*)PKa.x.data(), (uint8_t*)PKb.x.data(), Nai, ri); - if (Cai != Cai2) { - log::info("Cai != Cai2, aborting!"); - SendL2capPacket(i, PairingFailedBuilder::Create(PairingFailedReason::CONFIRM_VALUE_FAILED)); - return PairingFailure("Cai != Cai2"); - } - - // Send Pairing Random - SendL2capPacket(i, PairingRandomBuilder::Create(Nbi)); - } - - if (loop == 19) { - Na = Nai; - Nb = Nbi; - } - } - - ra[0] = (uint8_t)(passkey); - ra[1] = (uint8_t)(passkey >> 8); - ra[2] = (uint8_t)(passkey >> 16); - ra[3] = (uint8_t)(passkey >> 24); - rb = ra; - - return Stage1Result{Na, Nb, ra, rb}; -} - -Stage1ResultOrFailure PairingHandlerLe::SecureConnectionsNumericComparison( - const InitialInformations& i, const EcdhPublicKey& PKa, const EcdhPublicKey& PKb) { - log::info("Numeric Comparison start"); - Stage1ResultOrFailure result = SecureConnectionsJustWorks(i, PKa, PKb); - if (std::holds_alternative<PairingFailure>(result)) { - return std::get<PairingFailure>(result); - } - - const auto [Na, Nb, ra, rb] = std::get<Stage1Result>(result); - - uint32_t number_to_display = - crypto_toolbox::g2((uint8_t*)PKa.x.data(), (uint8_t*)PKb.x.data(), Na, Nb); - - ConfirmationData data(i.remote_connection_address, i.remote_name, number_to_display); - i.user_interface_handler->Post( - common::BindOnce(&UI::DisplayConfirmValue, common::Unretained(i.user_interface), data)); - - std::optional<PairingEvent> confirmyesno = WaitUiConfirmYesNo(); - if (!confirmyesno || confirmyesno->ui_value == 0) { - log::info("Was expecting the user value confirm"); - return PairingFailure("Was expecting the user value confirm"); - } - - return result; -} - -Stage1ResultOrFailure PairingHandlerLe::SecureConnectionsJustWorks(const InitialInformations& i, - const EcdhPublicKey& PKa, - const EcdhPublicKey& PKb) { - Octet16 Cb, Na, Nb, ra, rb; - - ra = rb = {0}; - - if (IAmCentral(i)) { - Na = GenerateRandom<16>(); - log::info("Central waits for confirmation"); - auto confirm = WaitPairingConfirm(); - if (std::holds_alternative<PairingFailure>(confirm)) { - return std::get<PairingFailure>(confirm); - } - Cb = std::get<PairingConfirmView>(confirm).GetConfirmValue(); - - // Send Pairing Random - SendL2capPacket(i, PairingRandomBuilder::Create(Na)); - - log::info("Central waits for Random"); - auto random = WaitPairingRandom(); - if (std::holds_alternative<PairingFailure>(random)) { - return std::get<PairingFailure>(random); - } - Nb = std::get<PairingRandomView>(random).GetRandomValue(); - - // Compute Cb locally - Octet16 Cb_local = crypto_toolbox::f4((uint8_t*)PKb.x.data(), (uint8_t*)PKa.x.data(), Nb, 0); - - if (Cb_local != Cb) { - log::info("Cb_local != Cb, aborting!"); - SendL2capPacket(i, PairingFailedBuilder::Create(PairingFailedReason::CONFIRM_VALUE_FAILED)); - return PairingFailure("Cb_local != Cb"); - } - } else { - Nb = GenerateRandom<16>(); - // Compute confirm - Cb = crypto_toolbox::f4((uint8_t*)PKb.x.data(), (uint8_t*)PKa.x.data(), Nb, 0); - - // Send Pairing Confirm - log::info("Peripheral sends confirmation"); - SendL2capPacket(i, PairingConfirmBuilder::Create(Cb)); - - log::info("Peripheral waits for random"); - auto random = WaitPairingRandom(); - if (std::holds_alternative<PairingFailure>(random)) { - return std::get<PairingFailure>(random); - } - Na = std::get<PairingRandomView>(random).GetRandomValue(); - - // Send Pairing Random - SendL2capPacket(i, PairingRandomBuilder::Create(Nb)); - } - - return Stage1Result{Na, Nb, ra, rb}; -} - -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/pairing_handler_le_unittest.cc b/system/gd/security/pairing_handler_le_unittest.cc deleted file mode 100644 index 44ea7d511e..0000000000 --- a/system/gd/security/pairing_handler_le_unittest.cc +++ /dev/null @@ -1,384 +0,0 @@ -/****************************************************************************** - * - * Copyright 2019 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 "security/pairing_handler_le.h" - -#include <bluetooth/log.h> -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include <memory> - -#include "os/rand.h" -#include "security/test/mocks.h" - -using ::testing::_; -using ::testing::Eq; -using ::testing::Field; -using ::testing::VariantWith; - -using bluetooth::os::GenerateRandom; -using bluetooth::security::CommandView; - -namespace bluetooth { -namespace security { - -namespace { - -CommandView BuilderToView(std::unique_ptr<BasePacketBuilder> builder) { - std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>(); - BitInserter it(*packet_bytes); - builder->Serialize(it); - PacketView<kLittleEndian> packet_bytes_view(packet_bytes); - auto temp_cmd_view = CommandView::Create(packet_bytes_view); - return CommandView::Create(temp_cmd_view); -} - -class PairingResultHandlerMock { -public: - MOCK_CONST_METHOD1(OnPairingFinished, void(PairingResultOrFailure)); -}; - -std::unique_ptr<PairingResultHandlerMock> pairingResult; -LeSecurityInterfaceMock leSecurityMock; -UIMock uiMock; - -void OnPairingFinished(PairingResultOrFailure r) { - if (std::holds_alternative<PairingResult>(r)) { - log::info("pairing with {} finished successfully!", - std::get<PairingResult>(r).connection_address); - } else { - log::info("pairing with ... failed!"); - } - pairingResult->OnPairingFinished(r); -} -} // namespace - -class PairingHandlerUnitTest : public testing::Test { -protected: - void SetUp() { - thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL); - handler_ = new os::Handler(thread_); - - bidi_queue_ = std::make_unique<common::BidiQueue<packet::PacketView<packet::kLittleEndian>, - packet::BasePacketBuilder>>(10); - up_buffer_ = - std::make_unique<os::EnqueueBuffer<packet::BasePacketBuilder>>(bidi_queue_->GetUpEnd()); - - bidi_queue_->GetDownEnd()->RegisterDequeue( - handler_, - common::Bind(&PairingHandlerUnitTest::L2CAP_SendSmp, common::Unretained(this))); - - pairingResult.reset(new PairingResultHandlerMock); - } - void TearDown() { - pairingResult.reset(); - bidi_queue_->GetDownEnd()->UnregisterDequeue(); - handler_->Clear(); - delete handler_; - delete thread_; - - ::testing::Mock::VerifyAndClearExpectations(&leSecurityMock); - ::testing::Mock::VerifyAndClearExpectations(&uiMock); - } - - void L2CAP_SendSmp() { - std::unique_ptr<packet::BasePacketBuilder> builder = bidi_queue_->GetDownEnd()->TryDequeue(); - - outgoing_l2cap_packet_ = BuilderToView(std::move(builder)); - outgoing_l2cap_packet_->IsValid(); - - outgoing_l2cap_blocker_.notify_one(); - } - - std::optional<bluetooth::security::CommandView> WaitForOutgoingL2capPacket() { - std::mutex mutex; - std::unique_lock<std::mutex> lock(mutex); - - // It is possible that we lost wakeup from condition_variable, check if data is already waiting - // to be processed - if (outgoing_l2cap_packet_ != std::nullopt) { - std::optional<bluetooth::security::CommandView> tmp = std::nullopt; - outgoing_l2cap_packet_.swap(tmp); - return tmp; - } - - // Data not ready yet, wait for it. - if (outgoing_l2cap_blocker_.wait_for(lock, std::chrono::seconds(5)) == - std::cv_status::timeout) { - return std::nullopt; - } - - std::optional<bluetooth::security::CommandView> tmp = std::nullopt; - outgoing_l2cap_packet_.swap(tmp); - return tmp; - } - -public: - os::Thread* thread_; - os::Handler* handler_; - std::unique_ptr< - common::BidiQueue<packet::PacketView<packet::kLittleEndian>, packet::BasePacketBuilder>> - bidi_queue_; - std::unique_ptr<os::EnqueueBuffer<packet::BasePacketBuilder>> up_buffer_; - std::condition_variable outgoing_l2cap_blocker_; - std::optional<bluetooth::security::CommandView> outgoing_l2cap_packet_ = std::nullopt; -}; - -InitialInformations initial_informations{ - .my_role = hci::Role::CENTRAL, - .my_connection_address = {{}, hci::AddressType::PUBLIC_DEVICE_ADDRESS}, - .my_identity_address = {{}, hci::AddressType::PUBLIC_DEVICE_ADDRESS}, - .my_identity_resolving_key = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, - 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}, - - .myPairingCapabilities = {.io_capability = IoCapability::NO_INPUT_NO_OUTPUT, - .oob_data_flag = OobDataFlag::NOT_PRESENT, - .auth_req = - AuthReqMaskBondingFlag | AuthReqMaskMitm | AuthReqMaskSc, - .maximum_encryption_key_size = 16, - .initiator_key_distribution = 0x03, - .responder_key_distribution = 0x03}, - - .remotely_initiated = false, - .remote_connection_address = {{}, hci::AddressType::RANDOM_DEVICE_ADDRESS}, - .user_interface = &uiMock, - .le_security_interface = &leSecurityMock, - .OnPairingFinished = OnPairingFinished, -}; - -TEST_F(PairingHandlerUnitTest, test_phase_1_failure) { - initial_informations.proper_l2cap_interface = up_buffer_.get(); - initial_informations.l2cap_handler = handler_; - initial_informations.user_interface_handler = handler_; - - std::unique_ptr<PairingHandlerLe> pairing_handler = - std::make_unique<PairingHandlerLe>(PairingHandlerLe::PHASE1, initial_informations); - - std::optional<bluetooth::security::CommandView> pairing_request = WaitForOutgoingL2capPacket(); - EXPECT_TRUE(pairing_request.has_value()); - EXPECT_EQ(pairing_request->GetCode(), Code::PAIRING_REQUEST); - - EXPECT_CALL(*pairingResult, OnPairingFinished(VariantWith<PairingFailure>(_))).Times(1); - - // SMP will waith for Pairing Response, once bad packet is received, it should stop the Pairing - CommandView bad_pairing_response = BuilderToView(PairingRandomBuilder::Create({})); - bad_pairing_response.IsValid(); - pairing_handler->OnCommandView(bad_pairing_response); - - std::optional<bluetooth::security::CommandView> pairing_failure = WaitForOutgoingL2capPacket(); - EXPECT_TRUE(pairing_failure.has_value()); - EXPECT_EQ(pairing_failure->GetCode(), Code::PAIRING_FAILED); -} - -TEST_F(PairingHandlerUnitTest, test_secure_connections_just_works) { - initial_informations.proper_l2cap_interface = up_buffer_.get(); - initial_informations.l2cap_handler = handler_; - initial_informations.user_interface_handler = handler_; - - // we keep the pairing_handler as unique_ptr to better mimick how it's used - // in the real world - std::unique_ptr<PairingHandlerLe> pairing_handler = - std::make_unique<PairingHandlerLe>(PairingHandlerLe::PHASE1, initial_informations); - - std::optional<bluetooth::security::CommandView> pairing_request_pkt = - WaitForOutgoingL2capPacket(); - EXPECT_TRUE(pairing_request_pkt.has_value()); - EXPECT_EQ(pairing_request_pkt->GetCode(), Code::PAIRING_REQUEST); - CommandView pairing_request = pairing_request_pkt.value(); - - auto pairing_response = BuilderToView(PairingResponseBuilder::Create( - IoCapability::KEYBOARD_DISPLAY, OobDataFlag::NOT_PRESENT, - AuthReqMaskBondingFlag | AuthReqMaskMitm | AuthReqMaskSc, 16, 0x03, 0x03)); - pairing_handler->OnCommandView(pairing_response); - // Phase 1 finished. - - // pairing public key - std::optional<bluetooth::security::CommandView> public_key_pkt = WaitForOutgoingL2capPacket(); - EXPECT_TRUE(public_key_pkt.has_value()); - EXPECT_EQ(Code::PAIRING_PUBLIC_KEY, public_key_pkt->GetCode()); - EcdhPublicKey my_public_key; - auto ppkv = PairingPublicKeyView::Create(public_key_pkt.value()); - ppkv.IsValid(); - my_public_key.x = ppkv.GetPublicKeyX(); - my_public_key.y = ppkv.GetPublicKeyY(); - - const auto [private_key, public_key] = GenerateECDHKeyPair(); - - pairing_handler->OnCommandView( - BuilderToView(PairingPublicKeyBuilder::Create(public_key.x, public_key.y))); - // DHKey exchange finished - std::array<uint8_t, 32> dhkey = ComputeDHKey(private_key, my_public_key); - - // Phasae 2 Stage 1 start - Octet16 ra, rb; - ra = rb = {0}; - - Octet16 Nb = GenerateRandom<16>(); - - // Compute confirm - Octet16 Cb = crypto_toolbox::f4((uint8_t*)public_key.x.data(), (uint8_t*)my_public_key.x.data(), - Nb, 0); - - pairing_handler->OnCommandView(BuilderToView(PairingConfirmBuilder::Create(Cb))); - - // random - std::optional<bluetooth::security::CommandView> random_pkt = WaitForOutgoingL2capPacket(); - EXPECT_TRUE(random_pkt.has_value()); - EXPECT_EQ(Code::PAIRING_RANDOM, random_pkt->GetCode()); - auto prv = PairingRandomView::Create(random_pkt.value()); - prv.IsValid(); - Octet16 Na = prv.GetRandomValue(); - - pairing_handler->OnCommandView(BuilderToView(PairingRandomBuilder::Create(Nb))); - - // Start of authentication stage 2 - uint8_t a[7]; - uint8_t b[7]; - memcpy(b, initial_informations.remote_connection_address.GetAddress().data(), - hci::Address::kLength); - b[6] = (uint8_t)initial_informations.remote_connection_address.GetAddressType(); - memcpy(a, initial_informations.my_connection_address.GetAddress().data(), hci::Address::kLength); - a[6] = (uint8_t)initial_informations.my_connection_address.GetAddressType(); - - Octet16 ltk, mac_key; - crypto_toolbox::f5(dhkey.data(), Na, Nb, a, b, &mac_key, <k); - - PairingRequestView preqv = PairingRequestView::Create(pairing_request); - PairingResponseView prspv = PairingResponseView::Create(pairing_response); - - preqv.IsValid(); - prspv.IsValid(); - std::array<uint8_t, 3> iocapA{static_cast<uint8_t>(preqv.GetIoCapability()), - static_cast<uint8_t>(preqv.GetOobDataFlag()), preqv.GetAuthReq()}; - std::array<uint8_t, 3> iocapB{static_cast<uint8_t>(prspv.GetIoCapability()), - static_cast<uint8_t>(prspv.GetOobDataFlag()), prspv.GetAuthReq()}; - - Octet16 Ea = crypto_toolbox::f6(mac_key, Na, Nb, rb, iocapA.data(), a, b); - Octet16 Eb = crypto_toolbox::f6(mac_key, Nb, Na, ra, iocapB.data(), b, a); - - std::optional<bluetooth::security::CommandView> dh_key_pkt = WaitForOutgoingL2capPacket(); - EXPECT_TRUE(dh_key_pkt.has_value()); - EXPECT_EQ(Code::PAIRING_DH_KEY_CHECK, dh_key_pkt->GetCode()); - auto pdhkcv = PairingDhKeyCheckView::Create(dh_key_pkt.value()); - pdhkcv.IsValid(); - EXPECT_EQ(pdhkcv.GetDhKeyCheck(), Ea); - - pairing_handler->OnCommandView(BuilderToView(PairingDhKeyCheckBuilder::Create(Eb))); - - // Phase 2 finished - // We don't care for the rest of the flow, let it die. -} - -InitialInformations initial_informations_trsi{ - .my_role = hci::Role::CENTRAL, - .my_connection_address = hci::AddressWithType(), - .my_identity_address = {{}, hci::AddressType::PUBLIC_DEVICE_ADDRESS}, - .my_identity_resolving_key = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, - 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}, - - .myPairingCapabilities = {.io_capability = IoCapability::NO_INPUT_NO_OUTPUT, - .oob_data_flag = OobDataFlag::NOT_PRESENT, - .auth_req = - AuthReqMaskBondingFlag | AuthReqMaskMitm | AuthReqMaskSc, - .maximum_encryption_key_size = 16, - .initiator_key_distribution = 0x03, - .responder_key_distribution = 0x03}, - - .remotely_initiated = true, - .remote_connection_address = hci::AddressWithType(), - .user_interface = &uiMock, - .le_security_interface = &leSecurityMock, - .OnPairingFinished = OnPairingFinished, -}; - -/* This test verifies that when remote peripheral device sends security request , and user - * does accept the prompt, we do send pairing request */ -TEST_F(PairingHandlerUnitTest, test_remote_peripheral_initiating) { - initial_informations_trsi.proper_l2cap_interface = up_buffer_.get(); - initial_informations_trsi.l2cap_handler = handler_; - initial_informations_trsi.user_interface_handler = handler_; - - std::unique_ptr<PairingHandlerLe> pairing_handler = std::make_unique<PairingHandlerLe>( - PairingHandlerLe::ACCEPT_PROMPT, initial_informations_trsi); - - // Simulate user accepting the pairing in UI - pairing_handler->OnUiAction(PairingEvent::PAIRING_ACCEPTED, - 0x01 /* Non-zero value means success */); - - std::optional<bluetooth::security::CommandView> pairing_request_pkt = - WaitForOutgoingL2capPacket(); - EXPECT_TRUE(pairing_request_pkt.has_value()); - EXPECT_EQ(Code::PAIRING_REQUEST, pairing_request_pkt->GetCode()); - - // We don't care for the rest of the flow, let it die. - pairing_handler.reset(); -} - -InitialInformations initial_informations_trmi{ - .my_role = hci::Role::PERIPHERAL, - .my_connection_address = hci::AddressWithType(), - .my_identity_address = {{}, hci::AddressType::PUBLIC_DEVICE_ADDRESS}, - .my_identity_resolving_key = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, - 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}, - - .myPairingCapabilities = {.io_capability = IoCapability::NO_INPUT_NO_OUTPUT, - .oob_data_flag = OobDataFlag::NOT_PRESENT, - .auth_req = - AuthReqMaskBondingFlag | AuthReqMaskMitm | AuthReqMaskSc, - .maximum_encryption_key_size = 16, - .initiator_key_distribution = 0x03, - .responder_key_distribution = 0x03}, - - .remotely_initiated = true, - .remote_connection_address = hci::AddressWithType(), - .pairing_request = PairingRequestView::Create(BuilderToView(PairingRequestBuilder::Create( - IoCapability::NO_INPUT_NO_OUTPUT, OobDataFlag::NOT_PRESENT, - AuthReqMaskBondingFlag | AuthReqMaskMitm | AuthReqMaskSc, 16, 0x03, 0x03))), - .user_interface = &uiMock, - .le_security_interface = &leSecurityMock, - - .OnPairingFinished = OnPairingFinished, -}; - -/* This test verifies that when remote device sends pairing request, and user does accept the - * prompt, we do send proper reply back */ -TEST_F(PairingHandlerUnitTest, test_remote_central_initiating) { - initial_informations_trmi.proper_l2cap_interface = up_buffer_.get(); - initial_informations_trmi.l2cap_handler = handler_; - initial_informations_trmi.user_interface_handler = handler_; - - std::unique_ptr<PairingHandlerLe> pairing_handler = std::make_unique<PairingHandlerLe>( - PairingHandlerLe::ACCEPT_PROMPT, initial_informations_trmi); - - // Simulate user accepting the pairing in UI - pairing_handler->OnUiAction(PairingEvent::PAIRING_ACCEPTED, - 0x01 /* Non-zero value means success */); - - std::optional<bluetooth::security::CommandView> pairing_response_pkt = - WaitForOutgoingL2capPacket(); - EXPECT_TRUE(pairing_response_pkt.has_value()); - EXPECT_EQ(Code::PAIRING_RESPONSE, pairing_response_pkt->GetCode()); - // Phase 1 finished. - - // We don't care for the rest of the flow, it's handled in in other tests. let it die. - pairing_handler.reset(); -} - -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/record/Android.bp b/system/gd/security/record/Android.bp deleted file mode 100644 index 1fb0c8504e..0000000000 --- a/system/gd/security/record/Android.bp +++ /dev/null @@ -1,22 +0,0 @@ -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "system_bt_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["system_bt_license"], -} - -filegroup { - name: "BluetoothSecurityRecordSources", - srcs: [ - "security_record_storage.cc", - ], -} - -filegroup { - name: "BluetoothSecurityRecordTestSources", - srcs: [ - "security_record_storage_test.cc", - ], -} diff --git a/system/gd/security/record/security_record.h b/system/gd/security/record/security_record.h deleted file mode 100644 index 8b7d31023c..0000000000 --- a/system/gd/security/record/security_record.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * - * Copyright 2019 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. - * - */ - -#pragma once - -#include "hci/address_with_type.h" -#include "hci/octets.h" - -namespace bluetooth { -namespace security { -namespace record { - -class SecurityRecord { -public: - explicit SecurityRecord(hci::AddressWithType address) : pseudo_address_(address) {} - - SecurityRecord& operator=(const SecurityRecord& other) = default; - - /** - * Returns true if a device is currently pairing to another device - */ - bool IsPairing() const { return pairing_; } - - /* Link key has been exchanged, but not stored */ - bool IsPaired() const { return IsClassicLinkKeyValid(); } - - void SetLinkKey(std::array<uint8_t, 16> link_key, hci::KeyType key_type) { - link_key_ = link_key; - key_type_ = key_type; - CancelPairing(); - } - - void CancelPairing() { pairing_ = false; } - - std::array<uint8_t, 16> GetLinkKey() { - log::assert_that(IsClassicLinkKeyValid(), "assert failed: IsClassicLinkKeyValid()"); - return link_key_; - } - - hci::KeyType GetKeyType() { - log::assert_that(IsClassicLinkKeyValid(), "assert failed: IsClassicLinkKeyValid()"); - return key_type_; - } - - std::optional<hci::AddressWithType> GetPseudoAddress() { return pseudo_address_; } - - void SetAuthenticated(bool is_authenticated) { this->is_authenticated_ = is_authenticated; } - - bool IsAuthenticated() { return this->is_authenticated_; } - - void SetRequiresMitmProtection(bool requires_mitm_protection) { - this->requires_mitm_protection_ = requires_mitm_protection; - } - - bool RequiresMitmProtection() { return this->requires_mitm_protection_; } - - void SetIsEncryptionRequired(bool is_encryption_required) { - this->is_encryption_required_ = is_encryption_required; - } - - bool IsEncryptionRequired() { return this->is_encryption_required_; } - - bool IsClassicLinkKeyValid() const { - return !std::all_of(link_key_.begin(), link_key_.end(), [](uint8_t b) { return b == 0; }); - } - - void SetIsTemporary(bool is_temp) { this->is_temporary_ = is_temp; } - - bool IsTemporary() { return this->is_temporary_; } - -private: - std::array<uint8_t, 16> link_key_ = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - hci::KeyType key_type_ = hci::KeyType::DEBUG_COMBINATION; - - bool is_temporary_ = false; - bool pairing_ = false; - bool is_authenticated_ = false; - bool requires_mitm_protection_ = false; - bool is_encryption_required_ = false; - -public: - /* First address we have ever seen this device with, that we used to create bond */ - std::optional<hci::AddressWithType> pseudo_address_; - - /* Identity Address */ - std::optional<hci::AddressWithType> identity_address_; - - std::optional<hci::Octet16> remote_ltk; - uint8_t key_size; - uint8_t security_level; - std::optional<uint16_t> remote_ediv; - std::optional<std::array<uint8_t, 8>> remote_rand; - std::optional<hci::Octet16> remote_irk; - std::optional<hci::Octet16> remote_signature_key; - - std::optional<hci::Octet16> local_ltk; - std::optional<uint16_t> local_ediv; - std::optional<std::array<uint8_t, 8>> local_rand; -}; - -} // namespace record -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/record/security_record_database.h b/system/gd/security/record/security_record_database.h deleted file mode 100644 index e8309e27b1..0000000000 --- a/system/gd/security/record/security_record_database.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <set> - -#include "hci/address_with_type.h" -#include "security/record/security_record.h" -#include "security/record/security_record_storage.h" - -namespace bluetooth { -namespace security { -namespace record { - -class SecurityRecordDatabase { -public: - SecurityRecordDatabase(record::SecurityRecordStorage security_record_storage) - : security_record_storage_(security_record_storage) {} - - using iterator = std::set<std::shared_ptr<SecurityRecord>>::iterator; - - std::shared_ptr<SecurityRecord> FindOrCreate(hci::AddressWithType address) { - auto it = Find(address); - // Security record check - if (it != records_.end()) { - return *it; - } - - // No security record, create one - auto record_ptr = std::make_shared<SecurityRecord>(address); - records_.insert(record_ptr); - return record_ptr; - } - - void Remove(const hci::AddressWithType& address) { - auto it = Find(address); - - // No record exists - if (it == records_.end()) { - return; - } - - records_.erase(it); - security_record_storage_.RemoveDevice(address); - } - - iterator Find(hci::AddressWithType address) { - for (auto it = records_.begin(); it != records_.end(); ++it) { - std::shared_ptr<SecurityRecord> record = *it; - if (record->identity_address_.has_value() && record->identity_address_.value() == address) { - return it; - } - if (record->GetPseudoAddress() == address) { - return it; - } - if (record->remote_irk.has_value() && - address.IsRpaThatMatchesIrk(record->remote_irk.value())) { - return it; - } - } - return records_.end(); - } - - void LoadRecordsFromStorage() { security_record_storage_.LoadSecurityRecords(&records_); } - - void SaveRecordsToStorage() { security_record_storage_.SaveSecurityRecords(&records_); } - - std::set<std::shared_ptr<SecurityRecord>> records_; - record::SecurityRecordStorage security_record_storage_; -}; - -} // namespace record -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/record/security_record_storage.cc b/system/gd/security/record/security_record_storage.cc deleted file mode 100644 index 6a7bb881ca..0000000000 --- a/system/gd/security/record/security_record_storage.cc +++ /dev/null @@ -1,211 +0,0 @@ -/* - * - * Copyright 2019 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 "security/record/security_record_storage.h" - -#include <bluetooth/log.h> - -#include "storage/classic_device.h" -#include "storage/le_device.h" -#include "storage/mutation.h" - -namespace bluetooth { -namespace security { -namespace record { - -namespace { -void SetClassicData(storage::Mutation& mutation, std::shared_ptr<record::SecurityRecord> record, - storage::Device& device) { - if (*device.GetDeviceType() == hci::DeviceType::LE) { - return; - } - if (record->IsClassicLinkKeyValid()) { - log::warn("Type: {}", static_cast<int>(*device.GetDeviceType())); - mutation.Add(device.Classic().SetLinkKey(record->GetLinkKey())); - mutation.Add(device.Classic().SetLinkKeyType(record->GetKeyType())); - } -} - -void SetLeData(storage::Mutation& mutation, std::shared_ptr<record::SecurityRecord> record, - storage::Device& device) { - if (*device.GetDeviceType() == hci::DeviceType::BR_EDR) { - return; - } - - auto le_device = device.Le(); - - if (record->identity_address_) { - mutation.Add(le_device.SetAddressType(record->identity_address_->GetAddressType())); - } - - if (record->remote_irk) { - std::array<uint8_t, 23> peerid; - std::copy_n(record->remote_irk->data(), record->remote_irk->size(), peerid.data()); - peerid[16] = static_cast<uint8_t>(record->identity_address_->GetAddressType()); - std::copy_n(record->identity_address_->GetAddress().data(), 6, peerid.data() + 17); - - common::ByteArray<23> byte_array(peerid); - mutation.Add(le_device.SetPeerId(byte_array.ToString())); - } - - if (record->pseudo_address_) { - mutation.Add(le_device.SetLegacyPseudoAddress(record->pseudo_address_->GetAddress())); - } - - if (record->remote_ltk) { - std::array<uint8_t, 28> penc_keys; - - std::copy_n(record->remote_ltk->data(), record->remote_ltk->size(), penc_keys.data()); - std::copy_n(record->remote_rand->data(), record->remote_rand->size(), penc_keys.data() + 16); - uint16_t* ediv_location = (uint16_t*)(penc_keys.data() + 24); - *ediv_location = *record->remote_ediv; - penc_keys[26] = record->security_level; - penc_keys[27] = record->key_size; - - common::ByteArray<28> byte_array(penc_keys); - mutation.Add(le_device.SetPeerEncryptionKeys(byte_array.ToString())); - } - - if (record->remote_signature_key) { - std::array<uint8_t, 21> psrk_keys; - - // four bytes counter, all zeros - *psrk_keys.data() = 0; - *(psrk_keys.data() + 1) = 0; - *(psrk_keys.data() + 2) = 0; - *(psrk_keys.data() + 3) = 0; - std::copy_n(record->remote_signature_key->data(), record->remote_signature_key->size(), - psrk_keys.data() + 4); - *(psrk_keys.data() + 20) = record->security_level; - - common::ByteArray<21> byte_array(psrk_keys); - mutation.Add(le_device.SetPeerSignatureResolvingKeys(byte_array.ToString())); - } -} - -void SetAuthenticationData(storage::Mutation& /* mutation */, - std::shared_ptr<record::SecurityRecord> record, - storage::Device& device) { - device.SetIsAuthenticated(record->IsAuthenticated() ? 1 : 0); - device.SetIsEncryptionRequired(record->IsEncryptionRequired() ? 1 : 0); - device.SetRequiresMitmProtection(record->RequiresMitmProtection() ? 1 : 0); -} -} // namespace - -SecurityRecordStorage::SecurityRecordStorage(storage::StorageModule* storage_module, - os::Handler* handler) - : storage_module_(storage_module), handler_(handler) {} - -void SecurityRecordStorage::SaveSecurityRecords( - std::set<std::shared_ptr<record::SecurityRecord>>* records) { - for (auto record : *records) { - if (record->IsTemporary()) { - continue; - } - storage::Device device = - storage_module_->GetDeviceByClassicMacAddress(record->GetPseudoAddress()->GetAddress()); - auto mutation = storage_module_->Modify(); - - if (record->IsClassicLinkKeyValid() && !record->identity_address_) { - mutation.Add(device.SetDeviceType(hci::DeviceType::BR_EDR)); - } else if (record->IsClassicLinkKeyValid() && record->remote_ltk) { - mutation.Add(device.SetDeviceType(hci::DeviceType::DUAL)); - } else if (!record->IsClassicLinkKeyValid() && record->remote_ltk) { - mutation.Add(device.SetDeviceType(hci::DeviceType::LE)); - } else { - mutation.Add(device.SetDeviceType(hci::DeviceType::LE)); - log::warn("Cannot determine device type from security record for '{}'; defaulting to LE", - *record->GetPseudoAddress()); - } - mutation.Commit(); - SetClassicData(mutation, record, device); - SetLeData(mutation, record, device); - SetAuthenticationData(mutation, record, device); - mutation.Commit(); - } -} - -void SecurityRecordStorage::LoadSecurityRecords( - std::set<std::shared_ptr<record::SecurityRecord>>* records) { - for (auto device : storage_module_->GetBondedDevices()) { - auto address_type = (device.GetDeviceType() == hci::DeviceType::BR_EDR) - ? hci::AddressType::PUBLIC_DEVICE_ADDRESS - : device.Le().GetAddressType(); - auto address_with_type = hci::AddressWithType(device.GetAddress(), *address_type); - - auto record = std::make_shared<record::SecurityRecord>(address_with_type); - if (device.GetDeviceType() != hci::DeviceType::LE) { - record->SetLinkKey(device.Classic().GetLinkKey()->bytes, *device.Classic().GetLinkKeyType()); - } - if (device.GetDeviceType() != hci::DeviceType::BR_EDR) { - record->pseudo_address_ = std::make_optional<hci::AddressWithType>( - *device.Le().GetLegacyPseudoAddress(), *device.Le().GetAddressType()); - - if (device.Le().GetPeerId()) { - auto peerid = common::ByteArray<23>::FromString(*device.Le().GetPeerId()); - record->remote_irk = std::make_optional<std::array<uint8_t, 16>>(); - std::copy_n(peerid->data(), record->remote_irk->size(), record->remote_irk->data()); - - uint8_t idaddress_type; - hci::Address idaddress; - std::copy_n(peerid->data() + 16, 1, &idaddress_type); - std::copy_n(peerid->data() + 17, 6, idaddress.data()); - record->identity_address_ = std::make_optional<hci::AddressWithType>( - idaddress, static_cast<hci::AddressType>(idaddress_type)); - } - - if (device.Le().GetPeerEncryptionKeys()) { - auto peer_encryption_keys = - common::ByteArray<28>::FromString(*device.Le().GetPeerEncryptionKeys()); - record->remote_ltk = std::make_optional<std::array<uint8_t, 16>>(); - record->remote_rand = std::make_optional<std::array<uint8_t, 8>>(); - record->remote_ediv = std::make_optional(0); - - std::copy_n(peer_encryption_keys->data(), 16, record->remote_ltk->data()); - std::copy_n(peer_encryption_keys->data() + 16, 8, record->remote_rand->data()); - std::copy_n(peer_encryption_keys->data() + 24, 2, &(*record->remote_ediv)); - record->security_level = peer_encryption_keys->data()[26]; - record->key_size = peer_encryption_keys->data()[27]; - } - - if (device.Le().GetPeerSignatureResolvingKeys()) { - auto peer_signature_resolving_keys = - common::ByteArray<21>::FromString(*device.Le().GetPeerSignatureResolvingKeys()); - record->remote_signature_key = std::make_optional<std::array<uint8_t, 16>>(); - - std::copy_n(peer_signature_resolving_keys->data() + 4, 16, - record->remote_signature_key->data()); - record->security_level = peer_signature_resolving_keys->data()[20]; - } - } - record->SetIsEncryptionRequired(device.GetIsEncryptionRequired() == 1 ? true : false); - record->SetAuthenticated(device.GetIsAuthenticated() == 1 ? true : false); - record->SetRequiresMitmProtection(device.GetRequiresMitmProtection() == 1 ? true : false); - records->insert(record); - } -} - -void SecurityRecordStorage::RemoveDevice(hci::AddressWithType address) { - storage::Device device = storage_module_->GetDeviceByClassicMacAddress(address.GetAddress()); - auto mutation = storage_module_->Modify(); - mutation.Add(device.RemoveFromConfig()); - mutation.Commit(); -} - -} // namespace record -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/record/security_record_storage.h b/system/gd/security/record/security_record_storage.h deleted file mode 100644 index 97f478b2a3..0000000000 --- a/system/gd/security/record/security_record_storage.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * - * Copyright 2019 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. - * - */ -#pragma once - -#include <set> - -#include "os/handler.h" -#include "security/record/security_record.h" -#include "storage/storage_module.h" - -namespace bluetooth { -namespace security { -namespace record { - -#ifdef __ANDROID__ -static const char* CONFIG_FILE_PATH = "/data/misc/bluedroid/bt_config.conf"; -#else // !__ANDROID__ -static const char* CONFIG_FILE_PATH = "bt_config.conf"; -#endif // __ANDROID__ - -class SecurityRecordStorage { -public: - SecurityRecordStorage(storage::StorageModule* storage_module, os::Handler* handler); - - /** - * Iterates through given vector and stores each record's metadata to disk. - * - * <p>Job gets posted to the Handler. - * - * @param records set of shared pointers to records. - */ - void SaveSecurityRecords(std::set<std::shared_ptr<record::SecurityRecord>>* records); - - /** - * Reads the record metadata from disk and converts each item into a SecurityRecord. - * - * <p>Job gets posted to the Handler. - * - * @param records set of shared pointers to records. - */ - void LoadSecurityRecords(std::set<std::shared_ptr<record::SecurityRecord>>* records); - - /** - * Removes a device from the storage - * - * @param address of device to remove - */ - void RemoveDevice(hci::AddressWithType address); - -private: - storage::StorageModule* storage_module_ __attribute__((unused)); - os::Handler* handler_ __attribute__((unused)); -}; - -} // namespace record -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/record/security_record_storage_test.cc b/system/gd/security/record/security_record_storage_test.cc deleted file mode 100644 index 9b327755b8..0000000000 --- a/system/gd/security/record/security_record_storage_test.cc +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright 2020 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 "security/record/security_record_storage.h" - -#include <gtest/gtest.h> - -#include "storage/storage_module.h" - -namespace bluetooth { -namespace security { -namespace record { -namespace { - -static const std::chrono::milliseconds kTestConfigSaveDelay = std::chrono::milliseconds(100); - -using storage::StorageModule; - -class DISABLED_SecurityRecordStorageTest : public ::testing::Test { -protected: - void SetUp() override { - // Make storage module - storage_module_ = - new StorageModule("/tmp/temp_config.txt", kTestConfigSaveDelay, 100, false, false); - - // Inject - fake_registry_.InjectTestModule(&StorageModule::Factory, storage_module_); - - // Make storage - record_storage_ = new record::SecurityRecordStorage(storage_module_, handler_); - } - - void TearDown() override { - synchronize(); - fake_registry_.StopAll(); - delete record_storage_; - } - - void synchronize() { - fake_registry_.SynchronizeModuleHandler(&StorageModule::Factory, std::chrono::milliseconds(20)); - } - - TestModuleRegistry fake_registry_; - os::Thread& thread_ = fake_registry_.GetTestThread(); - os::Handler* handler_ = nullptr; - StorageModule* storage_module_; - record::SecurityRecordStorage* record_storage_; -}; - -TEST_F(DISABLED_SecurityRecordStorageTest, setup_teardown) {} - -TEST_F(DISABLED_SecurityRecordStorageTest, store_security_record) { - hci::AddressWithType remote(hci::Address({0x01, 0x02, 0x03, 0x04, 0x05, 0x06}), - hci::AddressType::PUBLIC_DEVICE_ADDRESS); - std::array<uint8_t, 16> link_key = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0}; - std::shared_ptr<record::SecurityRecord> record = std::make_shared<record::SecurityRecord>(remote); - - record->SetLinkKey(link_key, hci::KeyType::DEBUG_COMBINATION); - std::set<std::shared_ptr<record::SecurityRecord>> record_set; - record_set.insert(record); - record_storage_->SaveSecurityRecords(&record_set); - - auto device = storage_module_->GetDeviceByClassicMacAddress(remote.GetAddress()); - ASSERT_TRUE(device.GetDeviceType()); - ASSERT_EQ(device.Classic().GetLinkKeyType(), record->GetKeyType()); - int i = 0; - for (i = 0; i < 16; ++i) { - ASSERT_EQ(link_key[i], device.Classic().GetLinkKey()->bytes[i]); - } -} - -TEST_F(DISABLED_SecurityRecordStorageTest, store_le_security_record) { - hci::AddressWithType identity_address(hci::Address({0x01, 0x02, 0x03, 0x04, 0x05, 0x06}), - hci::AddressType::RANDOM_DEVICE_ADDRESS); - std::array<uint8_t, 16> remote_ltk{0x07, 0x0c, 0x0e, 0x16, 0x18, 0x55, 0xc6, 0x72, - 0x64, 0x5a, 0xd8, 0xb1, 0xf6, 0x93, 0x94, 0xa7}; - uint16_t remote_ediv = 0x28; - std::array<uint8_t, 8> remote_rand{0x48, 0xac, 0x91, 0xf4, 0xef, 0x6d, 0x41, 0x10}; - std::array<uint8_t, 16> remote_irk{0x66, 0x90, 0x40, 0x76, 0x27, 0x69, 0x57, 0x71, - 0x0d, 0x39, 0xf7, 0x80, 0x9e, 0x2f, 0x49, 0xcf}; - std::array<uint8_t, 16> remote_signature_key{0x08, 0x83, 0xae, 0x44, 0xd6, 0x77, 0x9e, 0x90, - 0x1d, 0x25, 0xcd, 0xd7, 0xb6, 0xf4, 0x57, 0x85}; - std::shared_ptr<record::SecurityRecord> record = - std::make_shared<record::SecurityRecord>(identity_address); - - record->identity_address_ = identity_address; - record->remote_ltk = remote_ltk; - record->key_size = 16; - record->security_level = 2; - record->remote_ediv = remote_ediv; - record->remote_rand = remote_rand; - record->remote_irk = remote_irk; - record->remote_signature_key = remote_signature_key; - - std::set<std::shared_ptr<record::SecurityRecord>> record_set; - record_set.insert(record); - record_storage_->SaveSecurityRecords(&record_set); - - auto device = storage_module_->GetDeviceByClassicMacAddress(identity_address.GetAddress()); - ASSERT_EQ(hci::DeviceType::LE, device.GetDeviceType()); - ASSERT_EQ(device.Le().GetAddressType(), identity_address.GetAddressType()); - - // IRK, address type, and address glued together - ASSERT_EQ(*device.Le().GetPeerId(), "66904076276957710d39f7809e2f49cf01010203040506"); - - // LTK, RAND, EDIV and sec level glued together - ASSERT_EQ(*device.Le().GetPeerEncryptionKeys(), - "070c0e161855c672645ad8b1f69394a748ac91f4ef6d411028000210"); - - // Counter, signature key, and security level glued together - ASSERT_EQ(device.Le().GetPeerSignatureResolvingKeys(), - "000000000883ae44d6779e901d25cdd7b6f4578502"); -} - -TEST_F(DISABLED_SecurityRecordStorageTest, load_security_record) { - hci::AddressWithType remote(hci::Address({0x01, 0x02, 0x03, 0x04, 0x05, 0x06}), - hci::AddressType::PUBLIC_DEVICE_ADDRESS); - std::array<uint8_t, 16> link_key = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0}; - std::shared_ptr<record::SecurityRecord> record = std::make_shared<record::SecurityRecord>(remote); - - record->SetLinkKey(link_key, hci::KeyType::DEBUG_COMBINATION); - std::set<std::shared_ptr<record::SecurityRecord>> record_set; - record_set.insert(record); - record_storage_->SaveSecurityRecords(&record_set); - - auto device = storage_module_->GetDeviceByClassicMacAddress(remote.GetAddress()); - ASSERT_TRUE(device.GetDeviceType()); - - ASSERT_EQ(device.Classic().GetLinkKeyType(), record->GetKeyType()); - int i = 0; - for (i = 0; i < 16; ++i) { - ASSERT_EQ(link_key[i], device.Classic().GetLinkKey()->bytes[i]); - } - - record_set.clear(); - record_storage_->LoadSecurityRecords(&record_set); - record = *record_set.begin(); - link_key = record->GetLinkKey(); - - ASSERT_EQ(device.Classic().GetLinkKeyType(), record->GetKeyType()); - ASSERT_TRUE(device.GetDeviceType()); - for (i = 0; i < 16; ++i) { - ASSERT_EQ(link_key[i], device.Classic().GetLinkKey()->bytes[i]); - } -} - -TEST_F(DISABLED_SecurityRecordStorageTest, dont_save_temporary_records) { - hci::AddressWithType remote(hci::Address({0x01, 0x02, 0x03, 0x04, 0x05, 0x06}), - hci::AddressType::PUBLIC_DEVICE_ADDRESS); - std::array<uint8_t, 16> link_key = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0}; - std::shared_ptr<record::SecurityRecord> record = std::make_shared<record::SecurityRecord>(remote); - - record->SetLinkKey(link_key, hci::KeyType::DEBUG_COMBINATION); - record->SetIsTemporary(true); - std::set<std::shared_ptr<record::SecurityRecord>> record_set; - record_set.insert(record); - record_storage_->SaveSecurityRecords(&record_set); - - auto device = storage_module_->GetDeviceByClassicMacAddress(remote.GetAddress()); - ASSERT_FALSE(device.GetDeviceType()); - - record_set.clear(); - record_storage_->LoadSecurityRecords(&record_set); - ASSERT_EQ(record_set.size(), 0); -} - -TEST_F(DISABLED_SecurityRecordStorageTest, test_remove) { - hci::AddressWithType remote(hci::Address({0x01, 0x02, 0x03, 0x04, 0x05, 0x06}), - hci::AddressType::PUBLIC_DEVICE_ADDRESS); - std::array<uint8_t, 16> link_key = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0}; - std::shared_ptr<record::SecurityRecord> record = std::make_shared<record::SecurityRecord>(remote); - - record->SetLinkKey(link_key, hci::KeyType::DEBUG_COMBINATION); - std::set<std::shared_ptr<record::SecurityRecord>> record_set; - record_set.insert(record); - record_storage_->SaveSecurityRecords(&record_set); - - auto device = storage_module_->GetDeviceByClassicMacAddress(remote.GetAddress()); - ASSERT_TRUE(device.GetDeviceType()); - - ASSERT_EQ(device.Classic().GetLinkKeyType(), record->GetKeyType()); - int i = 0; - for (i = 0; i < 16; ++i) { - ASSERT_EQ(link_key[i], device.Classic().GetLinkKey()->bytes[i]); - } - - record_storage_->RemoveDevice(remote); - - record_set.clear(); - record_storage_->LoadSecurityRecords(&record_set); - ASSERT_EQ(record_set.size(), 0); -} - -} // namespace -} // namespace record -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/security_manager.cc b/system/gd/security/security_manager.cc deleted file mode 100644 index 5d7164fe22..0000000000 --- a/system/gd/security/security_manager.cc +++ /dev/null @@ -1,132 +0,0 @@ -/* - * - * Copyright 2019 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 "security_manager.h" - -#include "hci/octets.h" - -namespace bluetooth { -namespace security { - -// Definition of Pure Virtual Destructor -ISecurityManagerListener::~ISecurityManagerListener() {} - -void SecurityManager::Init() { - security_handler_->Post(common::BindOnce(&internal::SecurityManagerImpl::Init, - common::Unretained(security_manager_impl_))); -} - -void SecurityManager::CreateBond(hci::AddressWithType device) { - security_handler_->Post(common::BindOnce(&internal::SecurityManagerImpl::CreateBond, - common::Unretained(security_manager_impl_), - std::forward<hci::AddressWithType>(device))); -} - -void SecurityManager::CreateBondOutOfBand(hci::AddressWithType device, - pairing::OobData remote_p192_oob_data, - pairing::OobData remote_p256_oob_data) { - security_handler_->Post(common::BindOnce(&internal::SecurityManagerImpl::CreateBondOutOfBand, - common::Unretained(security_manager_impl_), - std::forward<hci::AddressWithType>(device), - remote_p192_oob_data, remote_p256_oob_data)); -} - -void SecurityManager::GetOutOfBandData(channel::SecurityCommandStatusCallback callback) { - security_handler_->Post( - common::BindOnce(&internal::SecurityManagerImpl::GetOutOfBandData, - common::Unretained(security_manager_impl_), - std::forward<channel::SecurityCommandStatusCallback>(callback))); -} - -void SecurityManager::CreateBondLe(hci::AddressWithType device) { - security_handler_->Post(common::BindOnce(&internal::SecurityManagerImpl::CreateBondLe, - common::Unretained(security_manager_impl_), - std::forward<hci::AddressWithType>(device))); -} - -void SecurityManager::CancelBond(hci::AddressWithType device) { - security_handler_->Post(common::BindOnce(&internal::SecurityManagerImpl::CancelBond, - common::Unretained(security_manager_impl_), - std::forward<hci::AddressWithType>(device))); -} - -void SecurityManager::RemoveBond(hci::AddressWithType device) { - security_handler_->Post(common::BindOnce(&internal::SecurityManagerImpl::RemoveBond, - common::Unretained(security_manager_impl_), - std::forward<hci::AddressWithType>(device))); -} - -void SecurityManager::SetUserInterfaceHandler(UI* user_interface, os::Handler* handler) { - security_handler_->Post(common::BindOnce(&internal::SecurityManagerImpl::SetUserInterfaceHandler, - common::Unretained(security_manager_impl_), - user_interface, handler)); -} - -// TODO(jpawlowski): remove once we have config file abstraction in cert tests -void SecurityManager::SetLeInitiatorAddressPolicyForTest( - hci::LeAddressManager::AddressPolicy address_policy, hci::AddressWithType fixed_address, - hci::Octet16 rotation_irk, std::chrono::milliseconds minimum_rotation_time, - std::chrono::milliseconds maximum_rotation_time) { - security_handler_->Post(common::BindOnce( - &internal::SecurityManagerImpl::SetLeInitiatorAddressPolicyForTest, - common::Unretained(security_manager_impl_), address_policy, fixed_address, rotation_irk, - minimum_rotation_time, maximum_rotation_time)); -} - -void SecurityManager::RegisterCallbackListener(ISecurityManagerListener* listener, - os::Handler* handler) { - security_handler_->Post(common::BindOnce(&internal::SecurityManagerImpl::RegisterCallbackListener, - common::Unretained(security_manager_impl_), listener, - handler)); -} - -void SecurityManager::UnregisterCallbackListener(ISecurityManagerListener* listener) { - security_handler_->Post( - common::BindOnce(&internal::SecurityManagerImpl::UnregisterCallbackListener, - common::Unretained(security_manager_impl_), listener)); -} - -void SecurityManager::OnPairingPromptAccepted(const bluetooth::hci::AddressWithType& address, - bool confirmed) { - security_handler_->Post(common::BindOnce(&internal::SecurityManagerImpl::OnPairingPromptAccepted, - common::Unretained(security_manager_impl_), address, - confirmed)); -} - -void SecurityManager::OnConfirmYesNo(const bluetooth::hci::AddressWithType& address, - bool confirmed) { - security_handler_->Post(common::BindOnce(&internal::SecurityManagerImpl::OnConfirmYesNo, - common::Unretained(security_manager_impl_), address, - confirmed)); -} - -void SecurityManager::OnPasskeyEntry(const bluetooth::hci::AddressWithType& address, - uint32_t passkey) { - security_handler_->Post(common::BindOnce(&internal::SecurityManagerImpl::OnPasskeyEntry, - common::Unretained(security_manager_impl_), address, - passkey)); -} - -void SecurityManager::OnPinEntry(const bluetooth::hci::AddressWithType& address, - std::vector<uint8_t> pin) { - security_handler_->Post(common::BindOnce(&internal::SecurityManagerImpl::OnPinEntry, - common::Unretained(security_manager_impl_), address, - std::move(pin))); -} - -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/security_manager.h b/system/gd/security/security_manager.h deleted file mode 100644 index b4ac6e620b..0000000000 --- a/system/gd/security/security_manager.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * - * Copyright 2019 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. - * - */ - -#pragma once - -#include <vector> - -#include "hci/address_with_type.h" -#include "hci/le_address_manager.h" -#include "security/internal/security_manager_impl.h" -#include "security/pairing/oob_data.h" -#include "security/security_manager_listener.h" - -namespace bluetooth { -namespace security { - -/** - * Manages the security attributes, pairing, bonding of devices, and the - * encryption/decryption of communications. - */ -class SecurityManager : public UICallbacks { -public: - SecurityManager(const SecurityManager&) = delete; - SecurityManager& operator=(const SecurityManager&) = delete; - - friend class SecurityModule; - - /** - * Initialize the security record map from an internal device database. - */ - void Init(); - - /** - * Initiates bond over Classic transport with device, if not bonded yet. - * - * This will initiate the Numeric Comparison bonding method - * - * @param address device address we want to bond with - */ - void CreateBond(hci::AddressWithType address); - - /** - * Initiates bond over Classic transport with device, if not bonded yet. - * - * This will initiate the Out of Band bonding method - * - * @param address device address we want to bond with - * @param remote_p192_oob_data comparison and random for p192 - * @param remote_p256_oob_data comparison and random for p256 - */ - void CreateBondOutOfBand(hci::AddressWithType address, pairing::OobData remote_p192_oob_data, - pairing::OobData remote_p256_oob_data); - - /** - * Get the out of band data from the controller to send to another device - * - * @param callback pointer to callback used for notifying that a security HCI command completed - */ - void GetOutOfBandData(channel::SecurityCommandStatusCallback callback); - - /** - * Initiates bond over Low Energy transport with device, if not bonded yet. - * - * @param address device address we want to bond with - */ - void CreateBondLe(hci::AddressWithType address); - - /** - * Cancels the pairing process for this device. - * - * @param device pointer to device with which we want to cancel our bond - */ - void CancelBond(hci::AddressWithType device); - - /** - * Disassociates the device and removes the persistent LTK - * - * @param device pointer to device we want to forget - */ - void RemoveBond(hci::AddressWithType device); - - /** - * Register Security UI handler, for handling prompts around the Pairing process. - */ - void SetUserInterfaceHandler(UI* user_interface, os::Handler* handler); - - /** - * Specify the initiator address policy used for LE transport. Can only be called once. - */ - void SetLeInitiatorAddressPolicyForTest(hci::LeAddressManager::AddressPolicy address_policy, - hci::AddressWithType fixed_address, - hci::Octet16 rotation_irk, - std::chrono::milliseconds minimum_rotation_time, - std::chrono::milliseconds maximum_rotation_time); - - /** - * Register to listen for callback events from SecurityManager - * - * @param listener ISecurityManagerListener instance to handle callbacks - */ - void RegisterCallbackListener(ISecurityManagerListener* listener, os::Handler* handler); - - /** - * Unregister listener for callback events from SecurityManager - * - * @param listener ISecurityManagerListener instance to unregister - */ - void UnregisterCallbackListener(ISecurityManagerListener* listener); - - void OnPairingPromptAccepted(const bluetooth::hci::AddressWithType& address, - bool confirmed) override; - void OnConfirmYesNo(const bluetooth::hci::AddressWithType& address, bool confirmed) override; - void OnPasskeyEntry(const bluetooth::hci::AddressWithType& address, uint32_t passkey) override; - void OnPinEntry(const bluetooth::hci::AddressWithType& address, - std::vector<uint8_t> pin) override; - -protected: - SecurityManager(os::Handler* security_handler, - internal::SecurityManagerImpl* security_manager_impl) - : security_handler_(security_handler), security_manager_impl_(security_manager_impl) {} - -private: - os::Handler* security_handler_ = nullptr; - internal::SecurityManagerImpl* security_manager_impl_; -}; - -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/security_manager_listener.h b/system/gd/security/security_manager_listener.h deleted file mode 100644 index d3ea55155c..0000000000 --- a/system/gd/security/security_manager_listener.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * - * Copyright 2019 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. - * - */ - -#pragma once - -#include "security/pairing_failure.h" - -namespace bluetooth { -namespace security { - -/** - * Callback interface from SecurityManager. - */ -class ISecurityManagerListener { -public: - virtual ~ISecurityManagerListener() = 0; - - /** - * Called when a device is successfully bonded. - * - * @param address of the newly bonded device - */ - virtual void OnDeviceBonded(bluetooth::hci::AddressWithType device) = 0; - - /** - * Called when a device is successfully un-bonded. - * - * @param address of device that is no longer bonded - */ - virtual void OnDeviceUnbonded(bluetooth::hci::AddressWithType device) = 0; - - /** - * Called as a result of a failure during the bonding process. - * - * @param address of the device that failed to bond - */ - virtual void OnDeviceBondFailed(bluetooth::hci::AddressWithType device, - PairingFailure status) = 0; - - /** - * Called as a result of a failure during the bonding process. - * - * @param address of the device that failed to bond - */ - virtual void OnEncryptionStateChanged(hci::EncryptionChangeView encryption_change_view) = 0; -}; - -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/security_module.cc b/system/gd/security/security_module.cc deleted file mode 100644 index 2a953633ad..0000000000 --- a/system/gd/security/security_module.cc +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#define LOG_TAG "security" - -#include "security/security_module.h" - -#include <memory> - -#include "hci/acl_manager.h" -#include "hci/hci_layer.h" -#include "l2cap/classic/l2cap_classic_module.h" -#include "l2cap/le/l2cap_le_module.h" -#include "module.h" -#include "neighbor/name_db.h" -#include "os/handler.h" -#include "security/channel/security_manager_channel.h" -#include "security/facade_configuration_api.h" -#include "security/internal/security_manager_impl.h" -#include "security/l2cap_security_module_interface.h" -#include "storage/storage_module.h" - -namespace bluetooth { -namespace security { - -const ModuleFactory SecurityModule::Factory = ModuleFactory([]() { return new SecurityModule(); }); - -struct SecurityModule::impl { - impl(os::Handler* security_handler, l2cap::le::L2capLeModule* l2cap_le_module, - l2cap::classic::L2capClassicModule* l2cap_classic_module, hci::HciLayer* hci_layer, - hci::AclManager* acl_manager, hci::Controller* controller, - storage::StorageModule* storage_module, neighbor::NameDbModule* name_db_module) - : security_handler_(security_handler), - l2cap_classic_module_(l2cap_classic_module), - l2cap_le_module_(l2cap_le_module), - security_manager_channel_( - new channel::SecurityManagerChannel(security_handler_, hci_layer)), - hci_layer_(hci_layer), - acl_manager_(acl_manager), - controller_(controller), - storage_module_(storage_module), - l2cap_security_interface_(&security_manager_impl, security_handler), - name_db_module_(name_db_module) { - l2cap_classic_module->InjectSecurityEnforcementInterface(&l2cap_security_interface_); - l2cap_le_module->InjectSecurityEnforcementInterface(&l2cap_security_interface_); - security_manager_channel_->SetSecurityInterface(l2cap_classic_module->GetSecurityInterface( - security_handler_, security_manager_channel_)); - } - - os::Handler* security_handler_; - l2cap::classic::L2capClassicModule* l2cap_classic_module_; - l2cap::le::L2capLeModule* l2cap_le_module_; - channel::SecurityManagerChannel* security_manager_channel_; - hci::HciLayer* hci_layer_; - hci::AclManager* acl_manager_; - hci::Controller* controller_; - storage::StorageModule* storage_module_; - L2capSecurityModuleInterface l2cap_security_interface_; - neighbor::NameDbModule* name_db_module_; - - internal::SecurityManagerImpl security_manager_impl{ - security_handler_, l2cap_le_module_, security_manager_channel_, hci_layer_, - acl_manager_, controller_, storage_module_, name_db_module_}; - - ~impl() { - delete security_manager_channel_; - l2cap_classic_module_->InjectSecurityEnforcementInterface(nullptr); - l2cap_le_module_->InjectSecurityEnforcementInterface(nullptr); - } -}; - -void SecurityModule::ListDependencies(ModuleList* list) const { - list->add<l2cap::le::L2capLeModule>(); - list->add<l2cap::classic::L2capClassicModule>(); - list->add<hci::HciLayer>(); - list->add<hci::AclManager>(); - list->add<hci::Controller>(); - list->add<storage::StorageModule>(); - list->add<neighbor::NameDbModule>(); -} - -void SecurityModule::Start() { - pimpl_ = std::make_unique<impl>( - GetHandler(), GetDependency<l2cap::le::L2capLeModule>(), - GetDependency<l2cap::classic::L2capClassicModule>(), GetDependency<hci::HciLayer>(), - GetDependency<hci::AclManager>(), GetDependency<hci::Controller>(), - GetDependency<storage::StorageModule>(), GetDependency<neighbor::NameDbModule>()); -} - -void SecurityModule::Stop() { pimpl_.reset(); } - -std::string SecurityModule::ToString() const { return "Security Module"; } - -std::unique_ptr<SecurityManager> SecurityModule::GetSecurityManager() { - return std::unique_ptr<SecurityManager>( - new SecurityManager(pimpl_->security_handler_, &pimpl_->security_manager_impl)); -} - -std::unique_ptr<FacadeConfigurationApi> SecurityModule::GetFacadeConfigurationApi() { - return std::unique_ptr<FacadeConfigurationApi>( - new FacadeConfigurationApi(pimpl_->security_handler_, &pimpl_->security_manager_impl)); -} - -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/security_module.h b/system/gd/security/security_module.h deleted file mode 100644 index 3caa8921a9..0000000000 --- a/system/gd/security/security_module.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2019 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. - */ -#pragma once - -#include <memory> - -#include "module.h" -#include "security/facade_configuration_api.h" -#include "security/security_manager.h" - -namespace bluetooth { -namespace security { - -class SecurityModule : public bluetooth::Module { -public: - SecurityModule() = default; - SecurityModule(const SecurityModule&) = delete; - SecurityModule& operator=(const SecurityModule&) = delete; - - ~SecurityModule() = default; - - /** - * Get the api to the SecurityManager - */ - std::unique_ptr<SecurityManager> GetSecurityManager(); - - /** - * Facade configuration API. - * - * <p> This allows you to set thins like IO Capabilities, Authentication Requirements, and OOB - * Data. - */ - std::unique_ptr<FacadeConfigurationApi> GetFacadeConfigurationApi(); - - static const ModuleFactory Factory; - -protected: - void ListDependencies(ModuleList* list) const override; - - void Start() override; - - void Stop() override; - - std::string ToString() const override; - -private: - struct impl; - std::unique_ptr<impl> pimpl_; -}; - -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/test/ecdh_keys_test.cc b/system/gd/security/test/ecdh_keys_test.cc deleted file mode 100644 index 3927e7f8ce..0000000000 --- a/system/gd/security/test/ecdh_keys_test.cc +++ /dev/null @@ -1,126 +0,0 @@ -/****************************************************************************** - * - * Copyright 2020 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 "security/ecdh_keys.h" - -#include <base/strings/string_number_conversions.h> -#include <bluetooth/log.h> -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include <memory> - -#include "hci/le_security_interface.h" -#include "os/log.h" -#include "security/ecc/p_256_ecc_pp.h" -#include "security/test/mocks.h" - -using namespace std::chrono_literals; - -namespace bluetooth { -namespace security { - -class EcdhKeysTest : public testing::Test { -protected: - void SetUp() {} - - void TearDown() {} - -public: -}; - -/* This test generates two pairs of keys, computes the Diffie–Hellman key using both, and verifies - * that they match */ -TEST_F(EcdhKeysTest, test_generated) { - std::srand(std::time(nullptr)); - - auto [private_key_a, public_key_a] = GenerateECDHKeyPair(); - auto [private_key_b, public_key_b] = GenerateECDHKeyPair(); - - std::array<uint8_t, 32> dhkeya = ComputeDHKey(private_key_a, public_key_b); - std::array<uint8_t, 32> dhkeyb = ComputeDHKey(private_key_b, public_key_a); - - EXPECT_EQ(dhkeya, dhkeyb); - - if (dhkeya != dhkeyb) { - log::error("private key a : {}", base::HexEncode(private_key_a.data(), private_key_a.size())); - log::error("public key a.x : {}", - base::HexEncode(public_key_a.x.data(), public_key_a.x.size())); - log::error("public key a.y : {}", - base::HexEncode(public_key_a.y.data(), public_key_a.y.size())); - - log::error("private key b : {}", base::HexEncode(private_key_b.data(), private_key_b.size())); - log::error("public key b.x : {}", - base::HexEncode(public_key_b.x.data(), public_key_b.x.size())); - log::error("public key b.y : {}", - base::HexEncode(public_key_b.y.data(), public_key_b.y.size())); - - log::error("dhkeya : {}", base::HexEncode(dhkeya.data(), dhkeya.size())); - log::error("dhkeyb : {}", base::HexEncode(dhkeyb.data(), dhkeyb.size())); - } -} - -/* This test uses two fixed pairs of keys, computes the Diffie–Hellman key using both, and verifies -that they match precomputed value. - -This code is also useful during debugging - one can replace fixed values with values from failed -exchange to verify which side did bad computation. */ -TEST_F(EcdhKeysTest, test_static) { - std::array<uint8_t, 32> private_key_a = {0x3E, 0xC8, 0x2A, 0x32, 0xB3, 0x75, 0x76, 0xBA, - 0x7D, 0xB8, 0xB4, 0x7B, 0xA0, 0x8A, 0xA3, 0xC3, - 0xF2, 0x03, 0x1A, 0x53, 0xF6, 0x52, 0x26, 0x32, - 0xB6, 0xAE, 0x57, 0x3F, 0x13, 0x15, 0x29, 0x51}; - bluetooth::security::EcdhPublicKey public_key_a; - uint8_t ax[32] = {0xDC, 0x88, 0xD0, 0xE5, 0x59, 0x73, 0xF2, 0x41, 0x88, 0x6C, 0xB4, - 0x45, 0x8B, 0x61, 0x3B, 0x10, 0xF5, 0xD4, 0xD2, 0x5B, 0x4E, 0xA1, - 0x7F, 0x94, 0xE3, 0xA9, 0x38, 0xF8, 0x84, 0xD4, 0x98, 0x10}; - uint8_t ay[32] = {0x3D, 0x13, 0x76, 0x4F, 0xD1, 0x29, 0x6E, 0xEC, 0x8D, 0xF6, 0x70, - 0x33, 0x8B, 0xA7, 0x18, 0xEA, 0x84, 0x15, 0xE8, 0x8C, 0x4A, 0xC8, - 0x76, 0x45, 0x90, 0x98, 0xBA, 0x52, 0x8B, 0x00, 0x69, 0xAF}; - memcpy(public_key_a.x.data(), ax, 32); - memcpy(public_key_a.y.data(), ay, 32); - - std::array<uint8_t, 32> private_key_b = {0xDD, 0x53, 0x84, 0x91, 0xC8, 0xFA, 0x4B, 0x45, - 0xB2, 0xFF, 0xC0, 0x53, 0x89, 0x64, 0x16, 0x7B, - 0x67, 0x30, 0xCE, 0x5D, 0x82, 0xF4, 0x8F, 0x38, - 0xA2, 0xE6, 0x78, 0xB6, 0xFB, 0xA1, 0x07, 0xD8}; - bluetooth::security::EcdhPublicKey public_key_b; - uint8_t bx[32] = {0x23, 0x1A, 0xEC, 0xFE, 0x7D, 0xC1, 0x20, 0x2F, 0x03, 0x3E, 0x9A, - 0xAA, 0x99, 0x55, 0x78, 0x86, 0x58, 0xCB, 0x37, 0x68, 0x7D, 0xE1, - 0xFF, 0x19, 0x33, 0xF8, 0xCB, 0x7A, 0x17, 0xAB, 0x0B, 0x73}; - uint8_t by[32] = {0x4C, 0x25, 0xE2, 0x42, 0x3C, 0x69, 0x0E, 0x3B, 0xC0, 0xEF, 0x94, - 0x09, 0x4D, 0x3F, 0x96, 0xBB, 0x18, 0xF2, 0x55, 0x81, 0x71, 0x5A, - 0xDE, 0xC4, 0x3E, 0xF9, 0x6F, 0xA9, 0xAF, 0x04, 0x4E, 0x86}; - memcpy(public_key_b.x.data(), bx, 32); - memcpy(public_key_b.y.data(), by, 32); - - std::array<uint8_t, 32> dhkey; - uint8_t dhkey_val[32] = {0x3B, 0xF8, 0xDF, 0x33, 0x99, 0x94, 0x66, 0x55, 0x4F, 0x2C, 0x4A, - 0x78, 0x2B, 0x51, 0xD1, 0x49, 0x0F, 0xF1, 0x96, 0x63, 0x51, 0x75, - 0x9E, 0x65, 0x7F, 0x3C, 0xFE, 0x77, 0xB4, 0x3F, 0x7A, 0x93}; - memcpy(dhkey.data(), dhkey_val, 32); - - std::array<uint8_t, 32> dhkey_a = ComputeDHKey(private_key_a, public_key_b); - std::array<uint8_t, 32> dhkey_b = ComputeDHKey(private_key_b, public_key_a); - - EXPECT_EQ(dhkey_a, dhkey); - EXPECT_EQ(dhkey_b, dhkey); -} - -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/test/fake_hci_layer.h b/system/gd/security/test/fake_hci_layer.h deleted file mode 100644 index 70b6facb05..0000000000 --- a/system/gd/security/test/fake_hci_layer.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * - * Copyright 2019 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 "hci/hci_layer.h" - -namespace bluetooth { -namespace security { - -using common::ContextualOnceCallback; -using hci::BitInserter; -using hci::CommandCompleteView; -using hci::CommandStatusView; -using hci::EventBuilder; -using hci::EventCode; -using hci::EventView; -using hci::HciLayer; -using hci::kLittleEndian; -using hci::PacketView; - -namespace { - -PacketView<kLittleEndian> GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet) { - auto bytes = std::make_shared<std::vector<uint8_t>>(); - BitInserter i(*bytes); - bytes->reserve(packet->size()); - packet->Serialize(i); - return packet::PacketView<packet::kLittleEndian>(bytes); -} - -class CommandQueueEntry { -public: - CommandQueueEntry(std::unique_ptr<hci::CommandBuilder> command_packet, - ContextualOnceCallback<void(CommandCompleteView)> on_complete_function) - : command(std::move(command_packet)), - waiting_for_status_(false), - on_complete(std::move(on_complete_function)) {} - - CommandQueueEntry(std::unique_ptr<hci::CommandBuilder> command_packet, - ContextualOnceCallback<void(CommandStatusView)> on_status_function) - : command(std::move(command_packet)), - waiting_for_status_(true), - on_status(std::move(on_status_function)) {} - - std::unique_ptr<hci::CommandBuilder> command; - bool waiting_for_status_; - ContextualOnceCallback<void(CommandStatusView)> on_status; - ContextualOnceCallback<void(CommandCompleteView)> on_complete; -}; - -} // namespace - -class FakeHciLayer : public HciLayer { -public: - void EnqueueCommand(std::unique_ptr<hci::CommandBuilder> command, - ContextualOnceCallback<void(CommandStatusView)> on_status) override { - auto command_queue_entry = - std::make_unique<CommandQueueEntry>(std::move(command), std::move(on_status)); - command_queue_.push(std::move(command_queue_entry)); - } - - void EnqueueCommand(std::unique_ptr<hci::CommandBuilder> command, - ContextualOnceCallback<void(CommandCompleteView)> on_complete) override { - auto command_queue_entry = - std::make_unique<CommandQueueEntry>(std::move(command), std::move(on_complete)); - command_queue_.push(std::move(command_queue_entry)); - } - - std::unique_ptr<CommandQueueEntry> GetLastCommand() { - EXPECT_FALSE(command_queue_.empty()); - auto last = std::move(command_queue_.front()); - command_queue_.pop(); - return last; - } - - void RegisterEventHandler(EventCode event_code, - common::ContextualCallback<void(EventView)> event_handler) override { - registered_events_[event_code] = event_handler; - } - - void UnregisterEventHandler(EventCode event_code) override { - registered_events_.erase(event_code); - } - - void IncomingEvent(std::unique_ptr<EventBuilder> event_builder) { - auto packet = GetPacketView(std::move(event_builder)); - EventView event = EventView::Create(packet); - ASSERT_TRUE(event.IsValid()); - EventCode event_code = event.GetEventCode(); - ASSERT_TRUE(registered_events_.find(event_code) != registered_events_.end()); - registered_events_[event_code].Invoke(event); - } - - void ListDependencies(ModuleList* /* list */) const override {} - void Start() override {} - void Stop() override {} - -private: - std::map<EventCode, common::ContextualCallback<void(EventView)>> registered_events_; - std::queue<std::unique_ptr<CommandQueueEntry>> command_queue_; -}; - -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/test/fake_l2cap_test.cc b/system/gd/security/test/fake_l2cap_test.cc deleted file mode 100644 index 9da4064476..0000000000 --- a/system/gd/security/test/fake_l2cap_test.cc +++ /dev/null @@ -1,134 +0,0 @@ -/****************************************************************************** - * - * Copyright 2019 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 <bluetooth/log.h> -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include <memory> - -#include "hci/le_security_interface.h" -#include "os/handler.h" -#include "os/queue.h" -#include "os/thread.h" -#include "packet/raw_builder.h" -#include "security/pairing_handler_le.h" -#include "security/test/mocks.h" - -using namespace std::chrono_literals; -using testing::_; -using testing::Invoke; -using testing::InvokeWithoutArgs; -using testing::Matcher; -using testing::SaveArg; - -using bluetooth::hci::CommandCompleteView; -using bluetooth::hci::CommandStatusView; -using bluetooth::hci::EncryptionChangeBuilder; -using bluetooth::hci::EncryptionEnabled; -using bluetooth::hci::ErrorCode; -using bluetooth::hci::EventBuilder; -using bluetooth::hci::EventView; -using bluetooth::hci::LeSecurityCommandBuilder; - -namespace bluetooth { -namespace security { - -namespace { - -template <class T> -PacketView<kLittleEndian> GetPacketView(std::unique_ptr<T> packet) { - auto bytes = std::make_shared<std::vector<uint8_t>>(); - BitInserter i(*bytes); - bytes->reserve(packet->size()); - packet->Serialize(i); - return packet::PacketView<packet::kLittleEndian>(bytes); -} - -void sync_handler(os::Handler* handler) { - std::promise<void> promise; - auto future = promise.get_future(); - handler->Post(common::BindOnce(&std::promise<void>::set_value, common::Unretained(&promise))); - auto status = future.wait_for(std::chrono::milliseconds(3)); - EXPECT_EQ(status, std::future_status::ready); -} -} // namespace - -class FakeL2capTest : public testing::Test { -protected: - void SetUp() {} - - void TearDown() {} - -public: -}; - -void my_enqueue_callback() { log::info("packet ready for dequeue!"); } - -/* This test verifies that Just Works pairing flow works. - * Both simulated devices specify capabilities as NO_INPUT_NO_OUTPUT, and secure connections support - */ -TEST_F(FakeL2capTest, test_bidi_queue_example) { - os::Thread* thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL); - os::Handler* handler_ = new os::Handler(thread_); - - common::BidiQueue<packet::BasePacketBuilder, packet::PacketView<packet::kLittleEndian>> - bidi_queue{10}; - - os::EnqueueBuffer<packet::BasePacketBuilder> enqueue_buffer{bidi_queue.GetDownEnd()}; - - // This is test packet we are sending down the queue to the other end; - auto test_packet = - EncryptionChangeBuilder::Create(ErrorCode::SUCCESS, 0x0020, EncryptionEnabled::ON); - - // send the packet through the queue - enqueue_buffer.Enqueue(std::move(test_packet), handler_); - - // give queue some time to push the packet through - sync_handler(handler_); - - // packet is through the queue, receive it on the other end. - auto test_packet_from_other_end = bidi_queue.GetUpEnd()->TryDequeue(); - - EXPECT_TRUE(test_packet_from_other_end != nullptr); - - // This is how we receive data - os::EnqueueBuffer<packet::PacketView<packet::kLittleEndian>> up_end_enqueue_buffer{ - bidi_queue.GetUpEnd()}; - bidi_queue.GetDownEnd()->RegisterDequeue(handler_, common::Bind(&my_enqueue_callback)); - - auto packet_one = std::make_unique<packet::RawBuilder>(); - packet_one->AddOctets({1, 2, 3}); - - up_end_enqueue_buffer.Enqueue( - std::make_unique<PacketView<kLittleEndian>>(GetPacketView(std::move(packet_one))), - handler_); - - sync_handler(handler_); - - auto other_end_packet = bidi_queue.GetDownEnd()->TryDequeue(); - EXPECT_TRUE(other_end_packet != nullptr); - - bidi_queue.GetDownEnd()->UnregisterDequeue(); - handler_->Clear(); - delete handler_; - delete thread_; -} - -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/test/fake_name_db.h b/system/gd/security/test/fake_name_db.h deleted file mode 100644 index 30e1a6ba4f..0000000000 --- a/system/gd/security/test/fake_name_db.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * - * Copyright 2019 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 "neighbor/name_db.h" - -namespace bluetooth { -namespace security { - -class FakeNameDbModule : public neighbor::NameDbModule { -public: - FakeNameDbModule() {} - - void ListDependencies(ModuleList* /* list */) const override {} - void Start() override {} - void Stop() override {} - std::string ToString() const override { return std::string("FakeNameDbModule"); } - - void ReadRemoteNameRequest(hci::Address address, neighbor::ReadRemoteNameDbCallback callback, - os::Handler* handler) override { - handler->Call(std::move(callback), address, true); - } - - bool IsNameCached(hci::Address /* address */) const { return true; } - - neighbor::RemoteName ReadCachedRemoteName(hci::Address /* address */) const { - neighbor::RemoteName name = {'t', 'e', 's', 't'}; - return name; - } -}; - -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/test/fake_security_interface.h b/system/gd/security/test/fake_security_interface.h deleted file mode 100644 index 4d29a8f182..0000000000 --- a/system/gd/security/test/fake_security_interface.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * - * Copyright 2020 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 "l2cap/classic/link_security_interface.h" -#include "os/handler.h" - -namespace bluetooth { -namespace security { - -class FakeLinkSecurityInterface : public l2cap::classic::LinkSecurityInterface { -public: - FakeLinkSecurityInterface(l2cap::classic::LinkSecurityInterfaceListener* listener, - hci::Address address) - : listener_(listener), address_(address) {} - - hci::Address GetRemoteAddress() { return address_; } - void Hold() override {} - void EnsureAuthenticated() override {} - - void EnsureEncrypted() override {} - - void Release() override { - // TODO(optedoblivion): Simulate the delay - listener_->OnLinkDisconnected(address_); - } - void Disconnect() override { listener_->OnLinkDisconnected(address_); } - uint16_t GetAclHandle() override { return 0; } - -private: - l2cap::classic::LinkSecurityInterfaceListener* listener_ = nullptr; - hci::Address address_; -}; - -class FakeSecurityInterface : public l2cap::classic::SecurityInterface { -public: - FakeSecurityInterface(os::Handler* handler, - l2cap::classic::LinkSecurityInterfaceListener* listener) - : handler_(handler), listener_(listener) {} - ~FakeSecurityInterface() {} - void InitiateConnectionForSecurity(hci::Address remote) override { - listener_->OnLinkConnected(std::make_unique<FakeLinkSecurityInterface>(listener_, remote)); - } - void Unregister() override {} - -private: - os::Handler* handler_ __attribute__((unused)); - l2cap::classic::LinkSecurityInterfaceListener* listener_ __attribute__((unused)); -}; - -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/test/mocks.h b/system/gd/security/test/mocks.h deleted file mode 100644 index dcf4e29189..0000000000 --- a/system/gd/security/test/mocks.h +++ /dev/null @@ -1,60 +0,0 @@ -/****************************************************************************** - * - * Copyright 2019 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. - * - ******************************************************************************/ - -#pragma once - -#include <gmock/gmock.h> - -#include "hci/address_with_type.h" -#include "hci/le_security_interface.h" -#include "security/ui.h" - -namespace bluetooth { -namespace security { - -class UIMock : public UI { -public: - UIMock() = default; - UIMock(const UIMock&) = delete; - UIMock& operator=(const UIMock&) = delete; - - ~UIMock() = default; - - // Convert these to accept ConfirmationData - MOCK_METHOD2(DisplayPairingPrompt, - void(const bluetooth::hci::AddressWithType& address, std::string name)); - MOCK_METHOD1(Cancel, void(const bluetooth::hci::AddressWithType& address)); - MOCK_METHOD1(DisplayConfirmValue, void(ConfirmationData)); - MOCK_METHOD1(DisplayYesNoDialog, void(ConfirmationData)); - MOCK_METHOD1(DisplayEnterPasskeyDialog, void(ConfirmationData)); - MOCK_METHOD1(DisplayPasskey, void(ConfirmationData)); - MOCK_METHOD1(DisplayEnterPinDialog, void(ConfirmationData)); -}; - -class LeSecurityInterfaceMock : public hci::LeSecurityInterface { -public: - MOCK_METHOD2(EnqueueCommand, - void(std::unique_ptr<hci::LeSecurityCommandBuilder> command, - common::ContextualOnceCallback<void(hci::CommandCompleteView)> on_complete)); - MOCK_METHOD2(EnqueueCommand, - void(std::unique_ptr<hci::LeSecurityCommandBuilder> command, - common::ContextualOnceCallback<void(hci::CommandStatusView)> on_status)); -}; - -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/test/pairing_handler_le_pair_test.cc b/system/gd/security/test/pairing_handler_le_pair_test.cc deleted file mode 100644 index 96d1351733..0000000000 --- a/system/gd/security/test/pairing_handler_le_pair_test.cc +++ /dev/null @@ -1,749 +0,0 @@ -/****************************************************************************** - * - * Copyright 2019 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 <bluetooth/log.h> -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include <memory> - -#include "common/testing/wired_pair_of_bidi_queues.h" -#include "hci/le_security_interface.h" -#include "hci/octets.h" -#include "packet/raw_builder.h" -#include "security/pairing_handler_le.h" -#include "security/test/mocks.h" - -using namespace std::chrono_literals; -using testing::_; -using testing::Invoke; -using testing::InvokeWithoutArgs; -using testing::Matcher; -using testing::SaveArg; - -using bluetooth::hci::Address; -using bluetooth::hci::AddressType; -using bluetooth::hci::CommandCompleteView; -using bluetooth::hci::CommandStatusView; -using bluetooth::hci::EncryptionChangeBuilder; -using bluetooth::hci::EncryptionEnabled; -using bluetooth::hci::ErrorCode; -using bluetooth::hci::EventBuilder; -using bluetooth::hci::EventView; -using bluetooth::hci::LeSecurityCommandBuilder; - -// run: -// out/host/linux-x86/nativetest/bluetooth_test_gd/bluetooth_test_gd --gtest_filter=Pairing* -// adb shell /data/nativetest/bluetooth_test_gd/bluetooth_test_gd -// --gtest_filter=PairingHandlerPairTest.* -// --gtest_repeat=10 --gtest_shuffle - -namespace bluetooth { -namespace security { -CommandView CommandBuilderToView(std::unique_ptr<BasePacketBuilder> builder) { - std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>(); - BitInserter it(*packet_bytes); - builder->Serialize(it); - PacketView<kLittleEndian> packet_bytes_view(packet_bytes); - auto temp_cmd_view = CommandView::Create(packet_bytes_view); - return CommandView::Create(temp_cmd_view); -} - -EventView EventBuilderToView(std::unique_ptr<EventBuilder> builder) { - std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>(); - BitInserter it(*packet_bytes); - builder->Serialize(it); - PacketView<kLittleEndian> packet_bytes_view(packet_bytes); - auto temp_evt_view = EventView::Create(packet_bytes_view); - return EventView::Create(temp_evt_view); -} -} // namespace security -} // namespace bluetooth - -namespace { - -constexpr uint16_t CONN_HANDLE_CENTRAL = 0x31, CONN_HANDLE_PERIPHERAL = 0x32; -std::unique_ptr<bluetooth::security::PairingHandlerLe> pairing_handler_a, pairing_handler_b; - -} // namespace - -namespace bluetooth { -namespace security { - -namespace { -Address ADDRESS_CENTRAL{{0x26, 0x64, 0x76, 0x86, 0xab, 0xba}}; -AddressType ADDRESS_TYPE_CENTRAL = AddressType::RANDOM_DEVICE_ADDRESS; -Address IDENTITY_ADDRESS_CENTRAL{{0x12, 0x34, 0x56, 0x78, 0x90, 0xaa}}; -AddressType IDENTITY_ADDRESS_TYPE_CENTRAL = AddressType::PUBLIC_DEVICE_ADDRESS; -hci::Octet16 IRK_CENTRAL = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; - -Address ADDRESS_PERIPHERAL{{0x33, 0x58, 0x24, 0x76, 0x11, 0x89}}; -AddressType ADDRESS_TYPE_PERIPHERAL = AddressType::RANDOM_DEVICE_ADDRESS; -Address IDENTITY_ADDRESS_PERIPHERAL{{0x21, 0x43, 0x65, 0x87, 0x09, 0x44}}; -AddressType IDENTITY_ADDRESS_TYPE_PERIPHERAL = AddressType::PUBLIC_DEVICE_ADDRESS; -hci::Octet16 IRK_PERIPHERAL = {0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, - 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01}; - -std::optional<PairingResultOrFailure> pairing_result_central; -std::optional<PairingResultOrFailure> pairing_result_peripheral; - -void OnPairingFinishedCentral(PairingResultOrFailure r) { - pairing_result_central = r; - if (std::holds_alternative<PairingResult>(r)) { - log::info("pairing finished successfully with {}", - std::get<PairingResult>(r).connection_address); - } else { - log::info("pairing with ... failed: {}", std::get<PairingFailure>(r).message); - } -} - -void OnPairingFinishedPeripheral(PairingResultOrFailure r) { - pairing_result_peripheral = r; - if (std::holds_alternative<PairingResult>(r)) { - log::info("pairing finished successfully with {}", - std::get<PairingResult>(r).connection_address); - } else { - log::info("pairing with ... failed: {}", std::get<PairingFailure>(r).message); - } -} - -}; // namespace - -// We obtain this mutex when we start initializing the handlers, and relese it when both handlers -// are initialized -std::mutex handlers_initialization_guard; - -class PairingHandlerPairTest : public testing::Test { - void dequeue_callback_central() { - auto packet_bytes_view = l2cap_->GetQueueAUpEnd()->TryDequeue(); - if (!packet_bytes_view) { - log::error("Received dequeue, but no data ready..."); - } - - auto temp_cmd_view = CommandView::Create(*packet_bytes_view); - if (!first_command_sent) { - first_command = std::make_unique<CommandView>(CommandView::Create(temp_cmd_view)); - first_command_sent = true; - return; - } - - if (!pairing_handler_a) { - log::fatal("Peripheral handler not initialized yet!"); - } - - pairing_handler_a->OnCommandView(CommandView::Create(temp_cmd_view)); - } - - void dequeue_callback_peripheral() { - auto packet_bytes_view = l2cap_->GetQueueBUpEnd()->TryDequeue(); - if (!packet_bytes_view) { - log::error("Received dequeue, but no data ready..."); - } - - auto temp_cmd_view = CommandView::Create(*packet_bytes_view); - if (!first_command_sent) { - first_command = std::make_unique<CommandView>(CommandView::Create(temp_cmd_view)); - first_command_sent = true; - return; - } - - if (!pairing_handler_b) { - log::fatal("Central handler not initialized yet!"); - } - - pairing_handler_b->OnCommandView(CommandView::Create(temp_cmd_view)); - } - -protected: - void SetUp() { - thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL); - handler_ = new os::Handler(thread_); - - l2cap_ = new common::testing::WiredPairOfL2capQueues(handler_); - // central sends it's packet into l2cap->down_buffer_b_ - // peripheral sends it's packet into l2cap->down_buffer_a_ - l2cap_->GetQueueAUpEnd()->RegisterDequeue( - handler_, common::Bind(&PairingHandlerPairTest::dequeue_callback_central, - common::Unretained(this))); - l2cap_->GetQueueBUpEnd()->RegisterDequeue( - handler_, common::Bind(&PairingHandlerPairTest::dequeue_callback_peripheral, - common::Unretained(this))); - - up_buffer_a_ = std::make_unique<os::EnqueueBuffer<packet::BasePacketBuilder>>( - l2cap_->GetQueueAUpEnd()); - up_buffer_b_ = std::make_unique<os::EnqueueBuffer<packet::BasePacketBuilder>>( - l2cap_->GetQueueBUpEnd()); - - central_setup = { - .my_role = hci::Role::CENTRAL, - .my_connection_address = {ADDRESS_CENTRAL, ADDRESS_TYPE_CENTRAL}, - .my_identity_address = {IDENTITY_ADDRESS_CENTRAL, IDENTITY_ADDRESS_TYPE_CENTRAL}, - .my_identity_resolving_key = IRK_CENTRAL, - - .myPairingCapabilities = {.io_capability = IoCapability::NO_INPUT_NO_OUTPUT, - .oob_data_flag = OobDataFlag::NOT_PRESENT, - .auth_req = AuthReqMaskBondingFlag | AuthReqMaskMitm | - AuthReqMaskSc, - .maximum_encryption_key_size = 16, - .initiator_key_distribution = KeyMaskId | KeyMaskSign, - .responder_key_distribution = KeyMaskId | KeyMaskSign}, - - .remotely_initiated = false, - .connection_handle = CONN_HANDLE_CENTRAL, - .remote_connection_address = {ADDRESS_PERIPHERAL, ADDRESS_TYPE_PERIPHERAL}, - .user_interface = ¢ral_user_interface, - .user_interface_handler = handler_, - .le_security_interface = ¢ral_le_security_mock, - .proper_l2cap_interface = up_buffer_a_.get(), - .l2cap_handler = handler_, - .OnPairingFinished = OnPairingFinishedCentral, - }; - - peripheral_setup = { - .my_role = hci::Role::PERIPHERAL, - - .my_connection_address = {ADDRESS_PERIPHERAL, ADDRESS_TYPE_PERIPHERAL}, - .my_identity_address = {IDENTITY_ADDRESS_PERIPHERAL, IDENTITY_ADDRESS_TYPE_PERIPHERAL}, - .my_identity_resolving_key = IRK_PERIPHERAL, - - .myPairingCapabilities = {.io_capability = IoCapability::NO_INPUT_NO_OUTPUT, - .oob_data_flag = OobDataFlag::NOT_PRESENT, - .auth_req = AuthReqMaskBondingFlag | AuthReqMaskMitm | - AuthReqMaskSc, - .maximum_encryption_key_size = 16, - .initiator_key_distribution = KeyMaskId | KeyMaskSign, - .responder_key_distribution = KeyMaskId | KeyMaskSign}, - .remotely_initiated = true, - .connection_handle = CONN_HANDLE_PERIPHERAL, - .remote_connection_address = {ADDRESS_CENTRAL, ADDRESS_TYPE_CENTRAL}, - .user_interface = &peripheral_user_interface, - .user_interface_handler = handler_, - .le_security_interface = &peripheral_le_security_mock, - .proper_l2cap_interface = up_buffer_b_.get(), - .l2cap_handler = handler_, - .OnPairingFinished = OnPairingFinishedPeripheral, - }; - - RecordSuccessfulEncryptionComplete(); - } - - void TearDown() { - ::testing::Mock::VerifyAndClearExpectations(&peripheral_user_interface); - ::testing::Mock::VerifyAndClearExpectations(¢ral_user_interface); - ::testing::Mock::VerifyAndClearExpectations(&peripheral_le_security_mock); - ::testing::Mock::VerifyAndClearExpectations(¢ral_le_security_mock); - - pairing_handler_a.reset(); - pairing_handler_b.reset(); - pairing_result_central.reset(); - pairing_result_peripheral.reset(); - - first_command_sent = false; - first_command.reset(); - - l2cap_->GetQueueAUpEnd()->UnregisterDequeue(); - l2cap_->GetQueueBUpEnd()->UnregisterDequeue(); - - delete l2cap_; - handler_->Clear(); - delete handler_; - delete thread_; - } - - void RecordPairingPromptHandling(UIMock& ui_mock, std::unique_ptr<PairingHandlerLe>* handler) { - EXPECT_CALL(ui_mock, DisplayPairingPrompt(_, _)) - .Times(1) - .WillOnce(InvokeWithoutArgs([handler]() { - log::info("UI mock received pairing prompt"); - - { - // By grabbing the lock, we ensure initialization of both pairing handlers is - // finished. - std::lock_guard<std::mutex> lock(handlers_initialization_guard); - } - - if (!(*handler)) { - log::fatal("handler not initialized yet!"); - } - // Simulate user accepting the pairing in UI - (*handler)->OnUiAction(PairingEvent::PAIRING_ACCEPTED, - 0x01 /* Non-zero value means success */); - })); - } - - void RecordSuccessfulEncryptionComplete() { - // For now, all tests are succeeding to go through Encryption. Record that in the setup. - // Once we test failure cases, move this to each test - EXPECT_CALL( - central_le_security_mock, - EnqueueCommand(_, Matcher<common::ContextualOnceCallback<void(CommandStatusView)>>(_))) - .Times(1) - .WillOnce([](std::unique_ptr<LeSecurityCommandBuilder> command, - common::ContextualOnceCallback<void(CommandStatusView)> on_status) { - // TODO: on_status.Run(); - - pairing_handler_a->OnHciEvent(EventBuilderToView(EncryptionChangeBuilder::Create( - ErrorCode::SUCCESS, CONN_HANDLE_CENTRAL, EncryptionEnabled::ON))); - - pairing_handler_b->OnHciEvent( - EventBuilderToView(hci::LeLongTermKeyRequestBuilder::Create( - CONN_HANDLE_PERIPHERAL, {0, 0, 0, 0, 0, 0, 0, 0}, 0))); - - pairing_handler_b->OnHciEvent(EventBuilderToView(EncryptionChangeBuilder::Create( - ErrorCode::SUCCESS, CONN_HANDLE_PERIPHERAL, EncryptionEnabled::ON))); - }); - } - -public: - std::unique_ptr<bluetooth::security::CommandView> WaitFirstL2capCommand() { - while (!first_command_sent) { - std::this_thread::sleep_for(1ms); - log::info("waiting for first command..."); - } - - return std::move(first_command); - } - - InitialInformations central_setup; - InitialInformations peripheral_setup; - UIMock central_user_interface; - UIMock peripheral_user_interface; - LeSecurityInterfaceMock central_le_security_mock; - LeSecurityInterfaceMock peripheral_le_security_mock; - - uint16_t first_command_sent = false; - std::unique_ptr<bluetooth::security::CommandView> first_command; - - os::Thread* thread_; - os::Handler* handler_; - common::testing::WiredPairOfL2capQueues* l2cap_; - - std::unique_ptr<os::EnqueueBuffer<packet::BasePacketBuilder>> up_buffer_a_; - std::unique_ptr<os::EnqueueBuffer<packet::BasePacketBuilder>> up_buffer_b_; -}; - -/* This test verifies that Just Works pairing flow works. - * Both simulated devices specify capabilities as NO_INPUT_NO_OUTPUT, and secure connections support - */ -TEST_F(PairingHandlerPairTest, test_secure_connections_just_works) { - central_setup.myPairingCapabilities.io_capability = IoCapability::NO_INPUT_NO_OUTPUT; - central_setup.myPairingCapabilities.oob_data_flag = OobDataFlag::NOT_PRESENT; - peripheral_setup.myPairingCapabilities.io_capability = IoCapability::NO_INPUT_NO_OUTPUT; - peripheral_setup.myPairingCapabilities.oob_data_flag = OobDataFlag::NOT_PRESENT; - - { - std::unique_lock<std::mutex> lock(handlers_initialization_guard); - - pairing_handler_a = std::make_unique<PairingHandlerLe>(PairingHandlerLe::PHASE1, central_setup); - - auto first_pkt = WaitFirstL2capCommand(); - peripheral_setup.pairing_request = PairingRequestView::Create(*first_pkt); - - EXPECT_CALL(peripheral_user_interface, DisplayPairingPrompt(_, _)) - .Times(1) - .WillOnce(InvokeWithoutArgs([] { - log::info("UI mock received pairing prompt"); - - { - // By grabbing the lock, we ensure initialization of both pairing handlers is - // finished. - std::lock_guard<std::mutex> lock(handlers_initialization_guard); - } - - if (!pairing_handler_b) { - log::fatal("handler not initialized yet!"); - } - - // Simulate user accepting the pairing in UI - pairing_handler_b->OnUiAction(PairingEvent::PAIRING_ACCEPTED, - 0x01 /* Non-zero value means success */); - })); - - pairing_handler_b = - std::make_unique<PairingHandlerLe>(PairingHandlerLe::PHASE1, peripheral_setup); - } - - pairing_handler_a->WaitUntilPairingFinished(); - pairing_handler_b->WaitUntilPairingFinished(); - - EXPECT_TRUE(std::holds_alternative<PairingResult>(pairing_result_central.value())); - EXPECT_TRUE(std::holds_alternative<PairingResult>(pairing_result_peripheral.value())); - - auto central_result = std::get<PairingResult>(pairing_result_central.value()); - ASSERT_EQ(central_result.distributed_keys.remote_identity_address->GetAddress(), - IDENTITY_ADDRESS_PERIPHERAL); - ASSERT_EQ(central_result.distributed_keys.remote_identity_address->GetAddressType(), - IDENTITY_ADDRESS_TYPE_PERIPHERAL); - ASSERT_EQ(*central_result.distributed_keys.remote_irk, IRK_PERIPHERAL); - - auto peripheral_result = std::get<PairingResult>(pairing_result_peripheral.value()); - ASSERT_EQ(peripheral_result.distributed_keys.remote_identity_address->GetAddress(), - IDENTITY_ADDRESS_CENTRAL); - ASSERT_EQ(peripheral_result.distributed_keys.remote_identity_address->GetAddressType(), - IDENTITY_ADDRESS_TYPE_CENTRAL); - ASSERT_EQ(*peripheral_result.distributed_keys.remote_irk, IRK_CENTRAL); -} - -TEST_F(PairingHandlerPairTest, test_secure_connections_just_works_peripheral_initiated) { - central_setup = { - .my_role = hci::Role::CENTRAL, - .my_connection_address = {ADDRESS_CENTRAL, ADDRESS_TYPE_CENTRAL}, - .my_identity_address = {IDENTITY_ADDRESS_CENTRAL, IDENTITY_ADDRESS_TYPE_CENTRAL}, - .my_identity_resolving_key = IRK_CENTRAL, - .myPairingCapabilities = {.io_capability = IoCapability::NO_INPUT_NO_OUTPUT, - .oob_data_flag = OobDataFlag::NOT_PRESENT, - .auth_req = AuthReqMaskBondingFlag | AuthReqMaskMitm | - AuthReqMaskSc, - .maximum_encryption_key_size = 16, - .initiator_key_distribution = KeyMaskId | KeyMaskSign, - .responder_key_distribution = KeyMaskId | KeyMaskSign}, - .remotely_initiated = true, - .connection_handle = CONN_HANDLE_CENTRAL, - .remote_connection_address = {ADDRESS_PERIPHERAL, ADDRESS_TYPE_PERIPHERAL}, - .user_interface = ¢ral_user_interface, - .user_interface_handler = handler_, - .le_security_interface = ¢ral_le_security_mock, - .proper_l2cap_interface = up_buffer_a_.get(), - .l2cap_handler = handler_, - .OnPairingFinished = OnPairingFinishedCentral, - }; - - peripheral_setup = { - .my_role = hci::Role::PERIPHERAL, - .my_connection_address = {ADDRESS_PERIPHERAL, ADDRESS_TYPE_PERIPHERAL}, - .my_identity_address = {IDENTITY_ADDRESS_PERIPHERAL, IDENTITY_ADDRESS_TYPE_PERIPHERAL}, - .my_identity_resolving_key = IRK_PERIPHERAL, - .myPairingCapabilities = {.io_capability = IoCapability::NO_INPUT_NO_OUTPUT, - .oob_data_flag = OobDataFlag::NOT_PRESENT, - .auth_req = AuthReqMaskBondingFlag | AuthReqMaskMitm | - AuthReqMaskSc, - .maximum_encryption_key_size = 16, - .initiator_key_distribution = KeyMaskId | KeyMaskSign, - .responder_key_distribution = KeyMaskId | KeyMaskSign}, - .remotely_initiated = false, - .connection_handle = CONN_HANDLE_PERIPHERAL, - .remote_connection_address = {ADDRESS_CENTRAL, ADDRESS_TYPE_CENTRAL}, - .user_interface = &peripheral_user_interface, - .user_interface_handler = handler_, - .le_security_interface = &peripheral_le_security_mock, - .proper_l2cap_interface = up_buffer_b_.get(), - .l2cap_handler = handler_, - .OnPairingFinished = OnPairingFinishedPeripheral, - }; - - std::unique_ptr<bluetooth::security::CommandView> first_pkt; - { - std::unique_lock<std::mutex> lock(handlers_initialization_guard); - pairing_handler_b = - std::make_unique<PairingHandlerLe>(PairingHandlerLe::PHASE1, peripheral_setup); - - first_pkt = WaitFirstL2capCommand(); - - EXPECT_CALL(central_user_interface, DisplayPairingPrompt(_, _)) - .Times(1) - .WillOnce(InvokeWithoutArgs([&first_pkt, this] { - log::info("UI mock received pairing prompt"); - - { - // By grabbing the lock, we ensure initialization of both pairing handlers is - // finished. - std::lock_guard<std::mutex> lock(handlers_initialization_guard); - } - if (!pairing_handler_a) { - log::fatal("handler not initialized yet!"); - } - // Simulate user accepting the pairing in UI - pairing_handler_a->OnUiAction(PairingEvent::PAIRING_ACCEPTED, - 0x01 /* Non-zero value means success */); - - // Send the first packet from the peripheral to central - auto view_to_packet = std::make_unique<packet::RawBuilder>(); - view_to_packet->AddOctets(std::vector(first_pkt->begin(), first_pkt->end())); - up_buffer_b_->Enqueue(std::move(view_to_packet), handler_); - })); - pairing_handler_a = std::make_unique<PairingHandlerLe>(PairingHandlerLe::PHASE1, central_setup); - } - - pairing_handler_a->WaitUntilPairingFinished(); - pairing_handler_b->WaitUntilPairingFinished(); - - EXPECT_TRUE(std::holds_alternative<PairingResult>(pairing_result_central.value())); - EXPECT_TRUE(std::holds_alternative<PairingResult>(pairing_result_peripheral.value())); -} - -TEST_F(PairingHandlerPairTest, test_secure_connections_numeric_comparison) { - central_setup.myPairingCapabilities.io_capability = IoCapability::DISPLAY_YES_NO; - central_setup.myPairingCapabilities.oob_data_flag = OobDataFlag::NOT_PRESENT; - central_setup.myPairingCapabilities.auth_req = - AuthReqMaskBondingFlag | AuthReqMaskMitm | AuthReqMaskSc; - - peripheral_setup.myPairingCapabilities.io_capability = IoCapability::DISPLAY_YES_NO; - peripheral_setup.myPairingCapabilities.oob_data_flag = OobDataFlag::NOT_PRESENT; - peripheral_setup.myPairingCapabilities.auth_req = - AuthReqMaskBondingFlag | AuthReqMaskMitm | AuthReqMaskSc; - - ConfirmationData data_peripheral; - { - std::unique_lock<std::mutex> lock(handlers_initialization_guard); - // Initiator must be initialized after the responder. - pairing_handler_a = std::make_unique<PairingHandlerLe>(PairingHandlerLe::PHASE1, central_setup); - - while (!first_command_sent) { - std::this_thread::sleep_for(1ms); - log::info("waiting for first command..."); - } - peripheral_setup.pairing_request = PairingRequestView::Create(*first_command); - - RecordPairingPromptHandling(peripheral_user_interface, &pairing_handler_b); - - EXPECT_CALL(peripheral_user_interface, DisplayConfirmValue(_)) - .WillOnce(SaveArg<0>(&data_peripheral)); - EXPECT_CALL(central_user_interface, DisplayConfirmValue(_)) - .WillOnce(Invoke([&](ConfirmationData data) { - EXPECT_EQ(data_peripheral.GetNumericValue(), data.GetNumericValue()); - if (data_peripheral.GetNumericValue() == data.GetNumericValue()) { - pairing_handler_a->OnUiAction(PairingEvent::CONFIRM_YESNO, 0x01); - pairing_handler_b->OnUiAction(PairingEvent::CONFIRM_YESNO, 0x01); - } - })); - - pairing_handler_b = - std::make_unique<PairingHandlerLe>(PairingHandlerLe::PHASE1, peripheral_setup); - } - pairing_handler_a->WaitUntilPairingFinished(); - pairing_handler_b->WaitUntilPairingFinished(); - - EXPECT_TRUE(std::holds_alternative<PairingResult>(pairing_result_central.value())); - EXPECT_TRUE(std::holds_alternative<PairingResult>(pairing_result_peripheral.value())); -} - -TEST_F(PairingHandlerPairTest, test_secure_connections_passkey_entry) { - central_setup.myPairingCapabilities.io_capability = IoCapability::KEYBOARD_ONLY; - central_setup.myPairingCapabilities.oob_data_flag = OobDataFlag::NOT_PRESENT; - central_setup.myPairingCapabilities.auth_req = - AuthReqMaskBondingFlag | AuthReqMaskMitm | AuthReqMaskSc; - - peripheral_setup.myPairingCapabilities.io_capability = IoCapability::DISPLAY_ONLY; - peripheral_setup.myPairingCapabilities.oob_data_flag = OobDataFlag::NOT_PRESENT; - peripheral_setup.myPairingCapabilities.auth_req = - AuthReqMaskBondingFlag | AuthReqMaskMitm | AuthReqMaskSc; - - // In this test either central or peripheral display the UI prompt first. This variable makes sure - // both prompts are displayed before passkey is confirmed. Since both UI handlers are same thread, - // it's safe. - int ui_prompts_count = 0; - uint32_t passkey_ = std::numeric_limits<uint32_t>::max(); - { - std::unique_lock<std::mutex> lock(handlers_initialization_guard); - pairing_handler_a = std::make_unique<PairingHandlerLe>(PairingHandlerLe::PHASE1, central_setup); - - while (!first_command_sent) { - std::this_thread::sleep_for(1ms); - log::info("waiting for first command..."); - } - peripheral_setup.pairing_request = PairingRequestView::Create(*first_command); - - RecordPairingPromptHandling(peripheral_user_interface, &pairing_handler_b); - - EXPECT_CALL(peripheral_user_interface, DisplayPasskey(_)) - .WillOnce(Invoke([&](ConfirmationData data) { - passkey_ = data.GetNumericValue(); - ui_prompts_count++; - if (ui_prompts_count == 2) { - pairing_handler_a->OnUiAction(PairingEvent::PASSKEY, passkey_); - } - })); - - EXPECT_CALL(central_user_interface, DisplayEnterPasskeyDialog(_)) - .WillOnce(Invoke([&](ConfirmationData data) { - ui_prompts_count++; - if (ui_prompts_count == 2) { - pairing_handler_a->OnUiAction(PairingEvent::PASSKEY, passkey_); - } - })); - - pairing_handler_b = - std::make_unique<PairingHandlerLe>(PairingHandlerLe::PHASE1, peripheral_setup); - } - // Initiator must be initialized after the responder. - pairing_handler_a->WaitUntilPairingFinished(); - pairing_handler_b->WaitUntilPairingFinished(); - - EXPECT_TRUE(std::holds_alternative<PairingResult>(pairing_result_central.value())); - EXPECT_TRUE(std::holds_alternative<PairingResult>(pairing_result_peripheral.value())); -} - -TEST_F(PairingHandlerPairTest, test_secure_connections_out_of_band) { - central_setup.myPairingCapabilities.io_capability = IoCapability::KEYBOARD_ONLY; - central_setup.myPairingCapabilities.oob_data_flag = OobDataFlag::NOT_PRESENT; - central_setup.myPairingCapabilities.auth_req = - AuthReqMaskBondingFlag | AuthReqMaskMitm | AuthReqMaskSc, - - peripheral_setup.myPairingCapabilities.io_capability = IoCapability::DISPLAY_ONLY; - peripheral_setup.myPairingCapabilities.oob_data_flag = OobDataFlag::PRESENT; - peripheral_setup.myPairingCapabilities.auth_req = - AuthReqMaskBondingFlag | AuthReqMaskMitm | AuthReqMaskSc, - - central_setup.my_oob_data = std::make_optional<MyOobData>(PairingHandlerLe::GenerateOobData()); - peripheral_setup.remote_oob_data = std::make_optional<InitialInformations::out_of_band_data>( - InitialInformations::out_of_band_data{ - .le_sc_c = central_setup.my_oob_data->c, - .le_sc_r = central_setup.my_oob_data->r, - }); - - { - std::unique_lock<std::mutex> lock(handlers_initialization_guard); - pairing_handler_a = std::make_unique<PairingHandlerLe>(PairingHandlerLe::PHASE1, central_setup); - while (!first_command_sent) { - std::this_thread::sleep_for(1ms); - log::info("waiting for first command..."); - } - peripheral_setup.pairing_request = PairingRequestView::Create(*first_command); - - RecordPairingPromptHandling(peripheral_user_interface, &pairing_handler_b); - - pairing_handler_b = - std::make_unique<PairingHandlerLe>(PairingHandlerLe::PHASE1, peripheral_setup); - } - pairing_handler_a->WaitUntilPairingFinished(); - pairing_handler_b->WaitUntilPairingFinished(); - - EXPECT_TRUE(std::holds_alternative<PairingResult>(pairing_result_central.value())); - EXPECT_TRUE(std::holds_alternative<PairingResult>(pairing_result_peripheral.value())); -} - -TEST_F(PairingHandlerPairTest, test_secure_connections_out_of_band_two_way) { - central_setup.myPairingCapabilities.io_capability = IoCapability::KEYBOARD_ONLY; - central_setup.myPairingCapabilities.oob_data_flag = OobDataFlag::PRESENT; - central_setup.myPairingCapabilities.auth_req = - AuthReqMaskBondingFlag | AuthReqMaskMitm | AuthReqMaskSc, - - peripheral_setup.myPairingCapabilities.io_capability = IoCapability::DISPLAY_ONLY; - peripheral_setup.myPairingCapabilities.oob_data_flag = OobDataFlag::PRESENT; - peripheral_setup.myPairingCapabilities.auth_req = - AuthReqMaskBondingFlag | AuthReqMaskMitm | AuthReqMaskSc, - - central_setup.my_oob_data = std::make_optional<MyOobData>(PairingHandlerLe::GenerateOobData()); - peripheral_setup.remote_oob_data = std::make_optional<InitialInformations::out_of_band_data>( - InitialInformations::out_of_band_data{ - .le_sc_c = central_setup.my_oob_data->c, - .le_sc_r = central_setup.my_oob_data->r, - }); - - peripheral_setup.my_oob_data = std::make_optional<MyOobData>(PairingHandlerLe::GenerateOobData()); - central_setup.remote_oob_data = std::make_optional<InitialInformations::out_of_band_data>( - InitialInformations::out_of_band_data{ - .le_sc_c = peripheral_setup.my_oob_data->c, - .le_sc_r = peripheral_setup.my_oob_data->r, - }); - - { - std::unique_lock<std::mutex> lock(handlers_initialization_guard); - pairing_handler_a = std::make_unique<PairingHandlerLe>(PairingHandlerLe::PHASE1, central_setup); - while (!first_command_sent) { - std::this_thread::sleep_for(1ms); - log::info("waiting for first command..."); - } - peripheral_setup.pairing_request = PairingRequestView::Create(*first_command); - - RecordPairingPromptHandling(peripheral_user_interface, &pairing_handler_b); - - pairing_handler_b = - std::make_unique<PairingHandlerLe>(PairingHandlerLe::PHASE1, peripheral_setup); - } - pairing_handler_a->WaitUntilPairingFinished(); - pairing_handler_b->WaitUntilPairingFinished(); - - EXPECT_TRUE(std::holds_alternative<PairingResult>(pairing_result_central.value())); - EXPECT_TRUE(std::holds_alternative<PairingResult>(pairing_result_peripheral.value())); -} - -TEST_F(PairingHandlerPairTest, test_legacy_just_works) { - central_setup.myPairingCapabilities.io_capability = IoCapability::NO_INPUT_NO_OUTPUT; - central_setup.myPairingCapabilities.oob_data_flag = OobDataFlag::NOT_PRESENT; - central_setup.myPairingCapabilities.auth_req = AuthReqMaskBondingFlag | AuthReqMaskMitm, - - peripheral_setup.myPairingCapabilities.io_capability = IoCapability::NO_INPUT_NO_OUTPUT; - peripheral_setup.myPairingCapabilities.oob_data_flag = OobDataFlag::NOT_PRESENT; - peripheral_setup.myPairingCapabilities.auth_req = AuthReqMaskBondingFlag | AuthReqMaskMitm; - - { - std::unique_lock<std::mutex> lock(handlers_initialization_guard); - pairing_handler_a = std::make_unique<PairingHandlerLe>(PairingHandlerLe::PHASE1, central_setup); - while (!first_command_sent) { - std::this_thread::sleep_for(1ms); - log::info("waiting for first command..."); - } - peripheral_setup.pairing_request = PairingRequestView::Create(*first_command); - - RecordPairingPromptHandling(peripheral_user_interface, &pairing_handler_b); - - pairing_handler_b = - std::make_unique<PairingHandlerLe>(PairingHandlerLe::PHASE1, peripheral_setup); - } - pairing_handler_a->WaitUntilPairingFinished(); - pairing_handler_b->WaitUntilPairingFinished(); - - EXPECT_TRUE(std::holds_alternative<PairingResult>(pairing_result_central.value())); - EXPECT_TRUE(std::holds_alternative<PairingResult>(pairing_result_peripheral.value())); -} - -TEST_F(PairingHandlerPairTest, test_legacy_passkey_entry) { - central_setup.myPairingCapabilities.io_capability = IoCapability::KEYBOARD_DISPLAY; - central_setup.myPairingCapabilities.oob_data_flag = OobDataFlag::NOT_PRESENT; - central_setup.myPairingCapabilities.auth_req = AuthReqMaskBondingFlag | AuthReqMaskMitm, - - peripheral_setup.myPairingCapabilities.io_capability = IoCapability::KEYBOARD_ONLY; - peripheral_setup.myPairingCapabilities.oob_data_flag = OobDataFlag::NOT_PRESENT; - peripheral_setup.myPairingCapabilities.auth_req = AuthReqMaskBondingFlag | AuthReqMaskMitm; - - { - std::unique_lock<std::mutex> lock(handlers_initialization_guard); - pairing_handler_a = std::make_unique<PairingHandlerLe>(PairingHandlerLe::PHASE1, central_setup); - while (!first_command_sent) { - std::this_thread::sleep_for(1ms); - log::info("waiting for first command..."); - } - peripheral_setup.pairing_request = PairingRequestView::Create(*first_command); - - RecordPairingPromptHandling(peripheral_user_interface, &pairing_handler_b); - - EXPECT_CALL(peripheral_user_interface, DisplayEnterPasskeyDialog(_)); - EXPECT_CALL(central_user_interface, DisplayConfirmValue(_)) - .WillOnce(Invoke([&](ConfirmationData data) { - log::info("Passkey prompt displayed entering passkey: {:08x}", - data.GetNumericValue()); - std::this_thread::sleep_for(1ms); - - // TODO: handle case where prompts are displayed in different order in the test! - pairing_handler_b->OnUiAction(PairingEvent::PASSKEY, data.GetNumericValue()); - })); - - pairing_handler_b = - std::make_unique<PairingHandlerLe>(PairingHandlerLe::PHASE1, peripheral_setup); - } - pairing_handler_a->WaitUntilPairingFinished(); - pairing_handler_b->WaitUntilPairingFinished(); - - EXPECT_TRUE(std::holds_alternative<PairingResult>(pairing_result_central.value())); - EXPECT_TRUE(std::holds_alternative<PairingResult>(pairing_result_peripheral.value())); -} - -} // namespace security -} // namespace bluetooth diff --git a/system/gd/security/ui.h b/system/gd/security/ui.h deleted file mode 100644 index 0b2b286773..0000000000 --- a/system/gd/security/ui.h +++ /dev/null @@ -1,129 +0,0 @@ -/****************************************************************************** - * - * Copyright 2019 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. - * - ******************************************************************************/ - -#pragma once - -#include <string> -#include <vector> - -#include "hci/address_with_type.h" - -namespace bluetooth { -namespace security { - -class ConfirmationData { -public: - ConfirmationData() : address_with_type_(hci::AddressWithType()), name_("No name set") {} - ConfirmationData(bluetooth::hci::AddressWithType address_with_type, std::string name) - : address_with_type_(address_with_type), name_(name) {} - ConfirmationData(bluetooth::hci::AddressWithType address_with_type, std::string name, - uint32_t numeric_value) - : address_with_type_(address_with_type), name_(name), numeric_value_(numeric_value) {} - - const bluetooth::hci::AddressWithType& GetAddressWithType() { return address_with_type_; } - - std::string GetName() { return name_; } - - uint32_t GetNumericValue() { return numeric_value_; } - - hci::IoCapability GetRemoteIoCaps() const { return remote_io_caps_; } - void SetRemoteIoCaps(hci::IoCapability remote_io_caps) { remote_io_caps_ = remote_io_caps; } - - hci::AuthenticationRequirements GetRemoteAuthReqs() const { return remote_auth_reqs_; } - - void SetRemoteAuthReqs(hci::AuthenticationRequirements remote_auth_reqs) { - remote_auth_reqs_ = remote_auth_reqs; - } - - hci::OobDataPresent GetRemoteOobDataPresent() const { return remote_oob_data_present_; } - - void SetRemoteOobDataPresent(hci::OobDataPresent remote_oob_data_present) { - remote_oob_data_present_ = remote_oob_data_present; - } - - bool IsJustWorks() const { return just_works_; } - - void SetJustWorks(bool just_works) { just_works_ = just_works; } - -private: - bluetooth::hci::AddressWithType address_with_type_; - std::string name_; - // Can either be the confirmation value or the passkey - uint32_t numeric_value_ = 0; - - // TODO(optedoblivion): Revisit after shim/BTA layer is gone - // Extra data is a hack to get data from the module to the shim - hci::IoCapability remote_io_caps_ = hci::IoCapability::DISPLAY_YES_NO; - hci::AuthenticationRequirements remote_auth_reqs_ = - hci::AuthenticationRequirements::DEDICATED_BONDING; - hci::OobDataPresent remote_oob_data_present_ = hci::OobDataPresent::NOT_PRESENT; - bool just_works_ = false; -}; - -// Through this interface we talk to the user, asking for confirmations/acceptance. -class UI { -public: - virtual ~UI() = default; - - /* Remote LE device tries to initiate pairing, ask user to confirm */ - virtual void DisplayPairingPrompt(const bluetooth::hci::AddressWithType& address, - std::string name) = 0; - - /* Remove the pairing prompt from DisplayPairingPrompt, i.e. remote device disconnected, or some - * application requested bond with this device */ - virtual void Cancel(const bluetooth::hci::AddressWithType& address) = 0; - - /* Display value for Comparison, user responds yes/no */ - virtual void DisplayConfirmValue(ConfirmationData data) = 0; - - /* Display Yes/No dialog, Classic pairing, numeric comparison with NoInputNoOutput device */ - virtual void DisplayYesNoDialog(ConfirmationData data) = 0; - - /* Display a dialog box that will let user enter the Passkey */ - virtual void DisplayEnterPasskeyDialog(ConfirmationData data) = 0; - - /* Present the passkey value to the user, user compares with other device */ - virtual void DisplayPasskey(ConfirmationData data) = 0; - - /* Ask the user to enter a PIN */ - virtual void DisplayEnterPinDialog(ConfirmationData data) = 0; -}; - -/* Through this interface, UI provides us with user choices. */ -class UICallbacks { -public: - virtual ~UICallbacks() = default; - - /* User accepted pairing prompt */ - virtual void OnPairingPromptAccepted(const bluetooth::hci::AddressWithType& address, - bool confirmed) = 0; - - /* User confirmed that displayed value matches the value on the other device */ - virtual void OnConfirmYesNo(const bluetooth::hci::AddressWithType& address, bool confirmed) = 0; - - /* User typed the value displayed on the other device. This is either Passkey or the Confirm value - */ - virtual void OnPasskeyEntry(const bluetooth::hci::AddressWithType& address, uint32_t passkey) = 0; - - /* User typed the PIN for the other device. */ - virtual void OnPinEntry(const bluetooth::hci::AddressWithType& address, - std::vector<uint8_t> pin) = 0; -}; - -} // namespace security -} // namespace bluetooth |