Merge "Packet: Add tests for RawBuilder, fix max"
diff --git a/btif/co/bta_av_co.cc b/btif/co/bta_av_co.cc
index 0621bc8..f3d39e2 100644
--- a/btif/co/bta_av_co.cc
+++ b/btif/co/bta_av_co.cc
@@ -1005,6 +1005,11 @@
memcpy(p_codec_info, p_peer->codec_config, AVDT_CODEC_SIZE);
}
+ // report this peer selectable codecs after retrieved all its capabilities.
+ LOG(INFO) << __func__ << ": retrieved " << +p_peer->num_rx_sinks
+ << " capabilities from peer " << p_peer->addr;
+ ReportSourceCodecState(p_peer);
+
return A2DP_SUCCESS;
}
@@ -1402,8 +1407,7 @@
}
bool BtaAvCo::SetActivePeer(const RawAddress& peer_address) {
- APPL_TRACE_DEBUG("%s: peer_address=%s", __func__,
- peer_address.ToString().c_str());
+ VLOG(1) << __func__ << ": peer_address=" << peer_address;
std::lock_guard<std::recursive_mutex> lock(codec_lock_);
@@ -1422,8 +1426,8 @@
active_peer_ = p_peer;
memcpy(codec_config_, active_peer_->codec_config, AVDT_CODEC_SIZE);
- APPL_TRACE_DEBUG("%s: codec = %s", __func__,
- A2DP_CodecInfoString(codec_config_).c_str());
+ LOG(INFO) << __func__ << ": codec = " << A2DP_CodecInfoString(codec_config_);
+ // report the selected codec configuration of this new active peer.
ReportSourceCodecState(active_peer_);
return true;
}
@@ -1476,12 +1480,12 @@
bool config_updated = false;
bool success = true;
- VLOG(1) << __func__ << ": peer_address=" << peer_address.ToString()
- << " codec_user_config=" << codec_user_config.ToString();
+ VLOG(1) << __func__ << ": peer_address=" << peer_address
+ << " codec_user_config={" << codec_user_config.ToString() << "}";
BtaAvCoPeer* p_peer = FindPeer(peer_address);
if (p_peer == nullptr) {
- LOG(ERROR) << __func__ << ": cannot find peer " << peer_address.ToString()
+ LOG(ERROR) << __func__ << ": cannot find peer " << peer_address
<< " to configure";
success = false;
goto done;
@@ -1490,7 +1494,7 @@
// Don't call BTA_AvReconfig() prior to retrieving all peer's capabilities
if ((p_peer->num_rx_sinks != p_peer->num_sinks) &&
(p_peer->num_sup_sinks != BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks))) {
- LOG(WARNING) << __func__ << ": peer " << p_peer->addr.ToString()
+ LOG(WARNING) << __func__ << ": peer " << p_peer->addr
<< " : not all peer's capabilities have been retrieved";
success = false;
goto done;
@@ -1504,7 +1508,7 @@
p_sink = p_peer->p_sink;
}
if (p_sink == nullptr) {
- LOG(ERROR) << __func__ << ": peer " << p_peer->addr.ToString()
+ LOG(ERROR) << __func__ << ": peer " << p_peer->addr
<< " : cannot find peer SEP to configure for codec type "
<< codec_user_config.codec_type;
success = false;
@@ -1529,7 +1533,7 @@
p_sink = SelectSourceCodec(p_peer);
if (p_sink == nullptr) {
- LOG(ERROR) << __func__ << ": peer " << p_peer->addr.ToString()
+ LOG(ERROR) << __func__ << ": peer " << p_peer->addr
<< " : cannot set up codec for the peer SINK";
success = false;
goto done;
@@ -1543,12 +1547,16 @@
}
done:
- // NOTE: We unconditionally send the upcall even if there is no change
- // or the user config failed. Thus, the caller would always know whether the
- // request succeeded or failed.
+ // We send the upcall if there is no change or the user config failed for
+ // current active peer, so the caller would know it failed. If there is no
+ // error, the new selected codec configuration would be sent after we are
+ // ready to start a new session with the audio HAL.
+ // For none active peer, we unconditionally send the upcall, so the caller
+ // would always know the result.
// NOTE: Currently, the input is restarted by sending an upcall
// and informing the Media Framework about the change.
- if (p_peer != nullptr) {
+ if (p_peer != nullptr &&
+ (!restart_output || !success || p_peer != active_peer_)) {
return ReportSourceCodecState(p_peer);
}
@@ -1574,7 +1582,7 @@
// Don't call BTA_AvReconfig() prior to retrieving all peer's capabilities
if ((p_peer->num_rx_sinks != p_peer->num_sinks) &&
(p_peer->num_sup_sinks != BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks))) {
- LOG(WARNING) << __func__ << ": peer " << p_peer->addr.ToString()
+ LOG(WARNING) << __func__ << ": peer " << p_peer->addr
<< " : not all peer's capabilities have been retrieved";
return false;
}
@@ -1582,7 +1590,7 @@
// Use the current sink codec
const BtaAvCoSep* p_sink = p_peer->p_sink;
if (p_sink == nullptr) {
- LOG(ERROR) << __func__ << ": peer " << p_peer->addr.ToString()
+ LOG(ERROR) << __func__ << ": peer " << p_peer->addr
<< " : cannot find peer SEP to configure";
return false;
}
@@ -1613,7 +1621,7 @@
if (config_updated) {
// NOTE: Currently, the input is restarted by sending an upcall
- // and informing the Media Framework about the change.
+ // and informing the Media Framework about the change of selected codec.
return ReportSourceCodecState(p_peer);
}
@@ -1625,22 +1633,19 @@
std::vector<btav_a2dp_codec_config_t> codecs_local_capabilities;
std::vector<btav_a2dp_codec_config_t> codecs_selectable_capabilities;
- APPL_TRACE_DEBUG("%s: peer_address=%s", __func__,
- p_peer->addr.ToString().c_str());
+ VLOG(1) << __func__ << ": peer_address=" << p_peer->addr;
A2dpCodecs* codecs = p_peer->GetCodecs();
CHECK(codecs != nullptr);
if (!codecs->getCodecConfigAndCapabilities(&codec_config,
&codecs_local_capabilities,
&codecs_selectable_capabilities)) {
- APPL_TRACE_WARNING(
- "%s: Peer %s : error reporting audio source codec state: "
- "cannot get codec config and capabilities",
- __func__, p_peer->addr.ToString().c_str());
+ LOG(WARNING) << __func__ << ": Peer " << p_peer->addr
+ << " : error reporting audio source codec state: cannot get "
+ "codec config and capabilities";
return false;
}
- APPL_TRACE_DEBUG("%s: peer %s codec_config=%s", __func__,
- p_peer->addr.ToString().c_str(),
- codec_config.ToString().c_str());
+ LOG(INFO) << __func__ << ": peer " << p_peer->addr << " codec_config={"
+ << codec_config.ToString() << "}";
btif_av_report_source_codec_state(p_peer->addr, codec_config,
codecs_local_capabilities,
codecs_selectable_capabilities);
@@ -1747,19 +1752,14 @@
// Select the codec
for (const auto& iter : p_peer->GetCodecs()->orderedSourceCodecs()) {
- APPL_TRACE_DEBUG("%s: trying codec %s", __func__, iter->name().c_str());
+ VLOG(1) << __func__ << ": trying codec " << iter->name();
p_sink = AttemptSourceCodecSelection(*iter, p_peer);
if (p_sink != nullptr) {
- APPL_TRACE_DEBUG("%s: selected codec %s", __func__, iter->name().c_str());
+ VLOG(1) << __func__ << ": selected codec " << iter->name();
break;
}
- APPL_TRACE_DEBUG("%s: cannot use codec %s", __func__, iter->name().c_str());
+ VLOG(1) << __func__ << ": cannot use codec " << iter->name();
}
-
- // NOTE: Unconditionally dispatch the event to make sure a callback with
- // the most recent codec info is generated.
- ReportSourceCodecState(p_peer);
-
return p_sink;
}
@@ -1999,10 +1999,8 @@
bool restart_output = false;
bool config_updated = false;
- APPL_TRACE_DEBUG("%s: peer_address=%s", __func__,
- p_peer->addr.ToString().c_str());
- APPL_TRACE_DEBUG("%s: codec: %s", __func__,
- A2DP_CodecInfoString(p_ota_codec_config).c_str());
+ LOG(INFO) << __func__ << ": peer_address=" << p_peer->addr
+ << ", codec: " << A2DP_CodecInfoString(p_ota_codec_config);
*p_restart_output = false;
@@ -2013,8 +2011,8 @@
// There are no peer SEPs if we didn't do the discovery procedure yet.
// We have all the information we need from the peer, so we can
// proceed with the OTA codec configuration.
- APPL_TRACE_ERROR("%s: peer %s : cannot find peer SEP to configure",
- __func__, p_peer->addr.ToString().c_str());
+ LOG(ERROR) << __func__ << ": peer " << p_peer->addr
+ << " : cannot find peer SEP to configure";
return false;
}
@@ -2023,15 +2021,14 @@
if (!p_peer->GetCodecs()->setCodecOtaConfig(
p_ota_codec_config, &peer_params, result_codec_config, &restart_input,
&restart_output, &config_updated)) {
- APPL_TRACE_ERROR("%s: peer %s : cannot set OTA config", __func__,
- p_peer->addr.ToString().c_str());
+ LOG(ERROR) << __func__ << ": peer " << p_peer->addr
+ << " : cannot set OTA config";
return false;
}
if (restart_output) {
- APPL_TRACE_DEBUG("%s: restart output", __func__);
- APPL_TRACE_DEBUG("%s: codec: %s", __func__,
- A2DP_CodecInfoString(result_codec_config).c_str());
+ VLOG(1) << __func__ << ": restart output for codec: "
+ << A2DP_CodecInfoString(result_codec_config);
*p_restart_output = true;
p_peer->p_sink = p_sink;
@@ -2041,7 +2038,7 @@
if (restart_input || config_updated) {
// NOTE: Currently, the input is restarted by sending an upcall
- // and informing the Media Framework about the change.
+ // and informing the Media Framework about the change of selected codec.
ReportSourceCodecState(p_peer);
}
diff --git a/gd/Android.bp b/gd/Android.bp
index 6aaf2df..46108c6 100644
--- a/gd/Android.bp
+++ b/gd/Android.bp
@@ -605,7 +605,11 @@
linux_glibc_x86_64: {
include_dirs: ["external/python/cpython3/android/linux_x86_64/pyconfig"],
cflags: ["-DSOABI=\"cpython-38android-x86_64-linux-gnu\""],
- suffix: ".cpython-38android-x86_64-linux-gnu",
+ // Commenting out the Linux suffix so that cpython-38-x86_64-linux-gnu
+ // Python 3.8 can also import the untagged .so library per PEP 3149
+ // Keep this change until Android py3-cmd can run ACTS, gRPC and can
+ // Export Python native symbols such as PyType_Type
+ // suffix: ".cpython-38android-x86_64-linux-gnu",
},
windows: {
enabled: false,
diff --git a/gd/cert/bluetooth_packets_python3_setup.py b/gd/cert/bluetooth_packets_python3_setup.py
new file mode 100644
index 0000000..bce14f0
--- /dev/null
+++ b/gd/cert/bluetooth_packets_python3_setup.py
@@ -0,0 +1,75 @@
+#!/usr/bin/env python3
+#
+# 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.
+
+
+# Usage:
+# 1. Run envsetup and lunch first in an Android checkout
+# 2. Make target bluetooth_packets_python3 that will generate C++ sources for the
+# Extension
+# 3. Build only:
+# python3 bluetooth_packets_python3_setup.py build_ext
+# Then Find the .so file in build/lib.linux-x86_64-3.X
+# 4. Install:
+# python3 bluetooth_packets_python3_setup.py install --user
+
+
+import os
+import glob
+from setuptools import setup, Extension
+
+ANDROID_BUILD_TOP = os.getenv("ANDROID_BUILD_TOP")
+PYBIND11_INCLUDE_DIR = os.path.join(ANDROID_BUILD_TOP,
+ "external/python/pybind11/include")
+GD_DIR = os.path.join(ANDROID_BUILD_TOP, "system/bt/gd")
+BT_PACKETS_GEN_DIR = os.path.join(ANDROID_BUILD_TOP,
+ "out/soong/.intermediates/system/bt/gd/BluetoothGeneratedPackets_h/gen")
+BT_PACKETS_PY3_GEN_DIR = os.path.join(ANDROID_BUILD_TOP,
+ "out/soong/.intermediates/system/bt/gd/BluetoothGeneratedPackets_python3_cc/gen")
+
+BT_PACKETS_BASE_SRCS = [
+ os.path.join(GD_DIR, "l2cap/fcs.cc"),
+ os.path.join(GD_DIR, "packet/bit_inserter.cc"),
+ os.path.join(GD_DIR, "packet/byte_inserter.cc"),
+ os.path.join(GD_DIR, "packet/byte_observer.cc"),
+ os.path.join(GD_DIR, "packet/iterator.cc"),
+ os.path.join(GD_DIR, "packet/fragmenting_inserter.cc"),
+ os.path.join(GD_DIR, "packet/packet_view.cc"),
+ os.path.join(GD_DIR, "packet/raw_builder.cc"),
+ os.path.join(GD_DIR, "packet/view.cc"),
+]
+
+BT_PACKETS_PY3_SRCs = \
+ [os.path.join(GD_DIR, "packet/python3_module.cc")] \
+ + glob.glob(os.path.join(BT_PACKETS_PY3_GEN_DIR, "hci", "*.cc")) \
+ + glob.glob(os.path.join(BT_PACKETS_PY3_GEN_DIR, "l2cap", "*.cc")) \
+ + glob.glob(os.path.join(BT_PACKETS_PY3_GEN_DIR, "security", "*.cc"))
+
+bluetooth_packets_python3_module = Extension('bluetooth_packets_python3',
+ sources=BT_PACKETS_BASE_SRCS + BT_PACKETS_PY3_SRCs,
+ include_dirs=[GD_DIR,
+ BT_PACKETS_GEN_DIR,
+ BT_PACKETS_PY3_GEN_DIR,
+ PYBIND11_INCLUDE_DIR],
+ extra_compile_args=['-std=c++17']
+ )
+
+setup(name='bluetooth_packets_python3',
+ version='1.0',
+ author="Android Open Source Project",
+ description="""Bluetooth Packet Library""",
+ ext_modules=[bluetooth_packets_python3_module],
+ py_modules=["bluetooth_packets_python3"],
+ )
diff --git a/gd/cert/grpc_root_server.cc b/gd/cert/grpc_root_server.cc
index 7281867..48b2d5a 100644
--- a/gd/cert/grpc_root_server.cc
+++ b/gd/cert/grpc_root_server.cc
@@ -59,7 +59,7 @@
break;
case BluetoothModule::L2CAP:
modules.add<::bluetooth::cert::ReadOnlyPropertyServerModule>();
- modules.add<::bluetooth::l2cap::classic::cert::L2capModuleCertModule>();
+ modules.add<::bluetooth::l2cap::classic::cert::L2capClassicModuleCertModule>();
break;
default:
return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "invalid module under test");
diff --git a/gd/cert/run_cert.sh b/gd/cert/run_cert.sh
index 81fe91e..a85b994 100755
--- a/gd/cert/run_cert.sh
+++ b/gd/cert/run_cert.sh
@@ -1,3 +1,5 @@
#! /bin/bash
-act.py -c $ANDROID_BUILD_TOP/system/bt/gd/cert/host_only_config.json -tf $ANDROID_BUILD_TOP/system/bt/gd/cert/cert_testcases -tp $ANDROID_BUILD_TOP/system/bt/gd
+# For bluetooth_packets_python3
+export PYTHONPATH=$PYTHONPATH:$ANDROID_BUILD_TOP/out/host/linux-x86/lib64
+python3.8 `which act.py` -c $ANDROID_BUILD_TOP/system/bt/gd/cert/host_only_config.json -tf $ANDROID_BUILD_TOP/system/bt/gd/cert/cert_testcases -tp $ANDROID_BUILD_TOP/system/bt/gd
diff --git a/gd/cert/run_device_cert.sh b/gd/cert/run_device_cert.sh
index 44e5a89..7566f65 100755
--- a/gd/cert/run_device_cert.sh
+++ b/gd/cert/run_device_cert.sh
@@ -1,3 +1,5 @@
#! /bin/bash
-act.py -c $ANDROID_BUILD_TOP/system/bt/gd/cert/android_devices_config.json -tf $ANDROID_BUILD_TOP/system/bt/gd/cert/cert_testcases -tp $ANDROID_BUILD_TOP/system/bt/gd
+# For bluetooth_packets_python3
+export PYTHONPATH=$PYTHONPATH:$ANDROID_BUILD_TOP/out/host/linux-x86/lib64
+python3.8 `which act.py` -c $ANDROID_BUILD_TOP/system/bt/gd/cert/android_devices_config.json -tf $ANDROID_BUILD_TOP/system/bt/gd/cert/cert_testcases -tp $ANDROID_BUILD_TOP/system/bt/gd
diff --git a/gd/cert/set_up_acts.sh b/gd/cert/set_up_acts.sh
index c8fa38b..ad4e775 100755
--- a/gd/cert/set_up_acts.sh
+++ b/gd/cert/set_up_acts.sh
@@ -46,9 +46,15 @@
popd
}
-function SetupPython3 {
- echo "Setting up python3"
- sudo apt-get install python3-dev
+function SetupPython38 {
+ echo "Setting up python3.8"
+ sudo apt-get install python3.8-dev
+}
+
+function CompileBluetoothPacketsPython3 {
+ echo "bluetooth_packets_python3 is not found, compiling"
+ croot
+ make -j bluetooth_packets_python3
}
if [[ "${BASH_SOURCE[0]}" == "${0}" ]] ; then
@@ -60,16 +66,41 @@
SetUpAndroidBuild
fi
-## Check python3 is installed properly
-dpkg -l python3-dev > /dev/null 2>&1
+## Check python3.8 is installed properly
+## Need Python 3.8 because bluetooth_packets_python3 is compiled against
+## Python 3.8 headers
+dpkg -l python3.8-dev > /dev/null 2>&1
if [[ $? -ne 0 ]] ; then
- SetupPython3
+ SetupPython38
+fi
+
+## Check bluetooth_packets_python3 is compiled succssfully
+export PYTHONPATH=$PYTHONPATH:$ANDROID_BUILD_TOP/out/host/linux-x86/lib64
+python3.8 -c "
+import bluetooth_packets_python3 as bp3
+bp3.BaseStruct
+"
+if [[ $? -ne 0 ]] ; then
+ pushd .
+ CompileBluetoothPacketsPython3
+ popd
+ python3.8 -c "
+import bluetooth_packets_python3 as bp3
+bp3.BaseStruct
+"
+ if [[ $? -ne 0 ]] ; then
+ echo "Setup failed as bluetooth_packets_python3 cannot be found"
+ else
+ echo "Found bluetooth_packets_python3 after compilation"
+ fi
+else
+ echo "Found bluetooth_packets_python3"
fi
## All is good now so go ahead with the acts setup
pushd .
cd $ANDROID_BUILD_TOP/tools/test/connectivity/acts/framework/
-sudo python3 setup.py develop
+sudo python3.8 setup.py develop
if [[ $? -eq 0 ]] ; then
echo "cert setup complete"
else
diff --git a/gd/facade/grpc_root_server.cc b/gd/facade/grpc_root_server.cc
index 29ccc59..e802dfe 100644
--- a/gd/facade/grpc_root_server.cc
+++ b/gd/facade/grpc_root_server.cc
@@ -60,7 +60,7 @@
break;
case BluetoothModule::L2CAP:
modules.add<::bluetooth::facade::ReadOnlyPropertyServerModule>();
- modules.add<::bluetooth::l2cap::classic::L2capModuleFacadeModule>();
+ modules.add<::bluetooth::l2cap::classic::L2capClassicModuleFacadeModule>();
break;
default:
return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "invalid module under test");
diff --git a/gd/hci/acl_manager.h b/gd/hci/acl_manager.h
index 27c4fb3..3706aba 100644
--- a/gd/hci/acl_manager.h
+++ b/gd/hci/acl_manager.h
@@ -151,7 +151,7 @@
private:
friend AclManager;
AclConnection(const AclManager* manager, uint16_t handle, Address address)
- : manager_(manager), handle_(handle), address_(address) {}
+ : manager_(manager), handle_(handle), address_(address), address_type_(AddressType::PUBLIC_DEVICE_ADDRESS) {}
AclConnection(const AclManager* manager, uint16_t handle, Address address, AddressType address_type, Role role)
: manager_(manager), handle_(handle), address_(address), address_type_(address_type), role_(role) {}
const AclManager* manager_;
diff --git a/gd/hci/classic_security_manager.cc b/gd/hci/classic_security_manager.cc
index 8425ae6..07aae77 100644
--- a/gd/hci/classic_security_manager.cc
+++ b/gd/hci/classic_security_manager.cc
@@ -46,6 +46,8 @@
Bind(&impl::on_request_event, common::Unretained(this)), handler_);
hci_layer_->RegisterEventHandler(EventCode::ENCRYPTION_KEY_REFRESH_COMPLETE,
Bind(&impl::on_complete_event, common::Unretained(this)), handler_);
+ hci_layer_->RegisterEventHandler(EventCode::LINK_KEY_NOTIFICATION,
+ Bind(&impl::on_link_key_notification, common::Unretained(this)), handler_);
}
void Stop() {
@@ -224,6 +226,12 @@
LOG_DEBUG("receive complete event %d", (uint8_t)event_code);
}
+ void on_link_key_notification(EventPacketView packet) {
+ auto view = LinkKeyNotificationView::Create(packet);
+ ASSERT(view.IsValid());
+ LOG_DEBUG("receive link key notification, key type %d", (uint8_t)view.GetKeyType());
+ }
+
void on_command_complete(CommandCompleteView status) {
if (client_handler_ != nullptr) {
client_handler_->Post(common::BindOnce(&ClassicSecurityCommandCallbacks::OnCommandComplete,
diff --git a/gd/hci/hci_packets.pdl b/gd/hci/hci_packets.pdl
index b591ec9..c048c80 100644
--- a/gd/hci/hci_packets.pdl
+++ b/gd/hci/hci_packets.pdl
@@ -1530,7 +1530,7 @@
authentication_enable : AuthenticationEnable,
}
-packet WriteAuthenticationEnable : CommandPacket (op_code = WRITE_AUTHENTICATION_ENABLE) {
+packet WriteAuthenticationEnable : SecurityCommand (op_code = WRITE_AUTHENTICATION_ENABLE) {
authentication_enable : AuthenticationEnable,
}
@@ -1911,7 +1911,7 @@
secure_connections_host_support : Enable,
}
-packet WriteSecureConnectionsHostSupport : CommandPacket (op_code = WRITE_SECURE_CONNECTIONS_HOST_SUPPORT) {
+packet WriteSecureConnectionsHostSupport : SecurityCommand (op_code = WRITE_SECURE_CONNECTIONS_HOST_SUPPORT) {
secure_connections_host_support : Enable,
}
@@ -2655,12 +2655,17 @@
_payload_, // placeholder (unimplemented)
}
-packet LeSetExtendedScanParameters : LeScanningCommand (op_code = LE_SET_EXTENDED_SCAN_PARAMETERS) {
+struct PhyScanParameters {
le_scan_type : LeScanType,
- le_scan_interval : 32, // 0x0004-0x00FFFFFF Default 0x10 (10ms)
- le_scan_window : 32, // 0x004-0xFFFF Default 0x10 (10ms)
+ le_scan_interval : 16, // 0x0004-0xFFFF Default 0x10 (10ms)
+ le_scan_window : 16, // 0x004-0xFFFF Default 0x10 (10ms)
+}
+
+packet LeSetExtendedScanParameters : LeScanningCommand (op_code = LE_SET_EXTENDED_SCAN_PARAMETERS) {
own_address_type : AddressType,
scanning_filter_policy : LeSetScanningFilterPolicy,
+ scanning_phys : 8,
+ parameters : PhyScanParameters[],
}
packet LeSetExtendedScanParametersComplete : CommandComplete (command_op_code = LE_SET_EXTENDED_SCAN_PARAMETERS) {
diff --git a/gd/hci/hci_packets_test.cc b/gd/hci/hci_packets_test.cc
index 729513b..6eb0d13 100644
--- a/gd/hci/hci_packets_test.cc
+++ b/gd/hci/hci_packets_test.cc
@@ -262,5 +262,161 @@
// TODO: Revisit reflection tests for EIR
// DEFINE_AND_INSTANTIATE_WriteExtendedInquiryResponseReflectionTest(pixel_3_xl_write_extended_inquiry_response,
// pixel_3_xl_write_extended_inquiry_response_no_uuids);
+
+std::vector<uint8_t> le_set_scan_parameters{
+ 0x0b, 0x20, 0x07, 0x01, 0x12, 0x00, 0x12, 0x00, 0x01, 0x00,
+};
+TEST(HciPacketsTest, testLeSetScanParameters) {
+ PacketView<kLittleEndian> packet_bytes_view(std::make_shared<std::vector<uint8_t>>(le_set_scan_parameters));
+ auto view =
+ LeSetScanParametersView::Create(LeScanningCommandView::Create(CommandPacketView::Create(packet_bytes_view)));
+
+ ASSERT(view.IsValid());
+ ASSERT_EQ(LeScanType::ACTIVE, view.GetLeScanType());
+ ASSERT_EQ(0x12, view.GetLeScanInterval());
+ ASSERT_EQ(0x12, view.GetLeScanWindow());
+ ASSERT_EQ(AddressType::RANDOM_DEVICE_ADDRESS, view.GetOwnAddressType());
+ ASSERT_EQ(LeSetScanningFilterPolicy::ACCEPT_ALL, view.GetScanningFilterPolicy());
+}
+
+DEFINE_AND_INSTANTIATE_LeSetScanParametersReflectionTest(le_set_scan_parameters);
+
+std::vector<uint8_t> le_set_scan_enable{
+ 0x0c, 0x20, 0x02, 0x01, 0x00,
+};
+TEST(HciPacketsTest, testLeSetScanEnable) {
+ PacketView<kLittleEndian> packet_bytes_view(std::make_shared<std::vector<uint8_t>>(le_set_scan_enable));
+ auto view = LeSetScanEnableView::Create(LeScanningCommandView::Create(CommandPacketView::Create(packet_bytes_view)));
+
+ ASSERT(view.IsValid());
+ ASSERT_EQ(Enable::ENABLED, view.GetLeScanEnable());
+ ASSERT_EQ(Enable::DISABLED, view.GetFilterDuplicates());
+}
+
+DEFINE_AND_INSTANTIATE_LeSetScanEnableReflectionTest(le_set_scan_enable);
+
+std::vector<uint8_t> le_get_vendor_capabilities{
+ 0x53,
+ 0xfd,
+ 0x00,
+};
+TEST(HciPacketsTest, testLeGetVendorCapabilities) {
+ PacketView<kLittleEndian> packet_bytes_view(std::make_shared<std::vector<uint8_t>>(le_get_vendor_capabilities));
+ auto view =
+ LeGetVendorCapabilitiesView::Create(VendorCommandView::Create(CommandPacketView::Create(packet_bytes_view)));
+
+ ASSERT(view.IsValid());
+}
+
+DEFINE_AND_INSTANTIATE_LeGetVendorCapabilitiesReflectionTest(le_get_vendor_capabilities);
+
+std::vector<uint8_t> le_get_vendor_capabilities_complete{
+ 0x0e, 0x0c, 0x01, 0x53, 0xfd, 0x00, 0x05, 0x01, 0x00, 0x04, 0x80, 0x01, 0x10, 0x01,
+};
+TEST(HciPacketsTest, testLeGetVendorCapabilitiesComplete) {
+ PacketView<kLittleEndian> packet_bytes_view(
+ std::make_shared<std::vector<uint8_t>>(le_get_vendor_capabilities_complete));
+ auto view = LeGetVendorCapabilitiesCompleteView::Create(
+ CommandCompleteView::Create(EventPacketView::Create(packet_bytes_view)));
+
+ ASSERT(view.IsValid());
+ auto base_capabilities = view.GetBaseVendorCapabilities();
+ ASSERT_EQ(5, base_capabilities.max_advt_instances_);
+ ASSERT_EQ(1, base_capabilities.offloaded_resolution_of_private_address_);
+ ASSERT_EQ(1024, base_capabilities.total_scan_results_storage_);
+ ASSERT_EQ(128, base_capabilities.max_irk_list_sz_);
+ ASSERT_EQ(1, base_capabilities.filtering_support_);
+ ASSERT_EQ(16, base_capabilities.max_filter_);
+ ASSERT_EQ(1, base_capabilities.activity_energy_info_support_);
+}
+
+DEFINE_AND_INSTANTIATE_LeGetVendorCapabilitiesCompleteReflectionTest(le_get_vendor_capabilities_complete);
+
+std::vector<uint8_t> le_set_extended_scan_parameters{
+ 0x41, 0x20, 0x08, 0x01, 0x00, 0x01, 0x01, 0x12, 0x00, 0x12, 0x00,
+};
+
+TEST(HciPacketsTest, testLeSetExtendedScanParameters) {
+ PacketView<kLittleEndian> packet_bytes_view(std::make_shared<std::vector<uint8_t>>(le_set_extended_scan_parameters));
+ auto view = LeSetExtendedScanParametersView::Create(
+ LeScanningCommandView::Create(CommandPacketView::Create(packet_bytes_view)));
+
+ ASSERT(view.IsValid());
+ ASSERT_EQ(1, view.GetScanningPhys());
+ auto params = view.GetParameters();
+ ASSERT_EQ(1, params.size());
+ ASSERT_EQ(LeScanType::ACTIVE, params[0].le_scan_type_);
+ ASSERT_EQ(18, params[0].le_scan_interval_);
+ ASSERT_EQ(18, params[0].le_scan_window_);
+}
+
+std::vector<uint8_t> le_set_extended_scan_parameters_6553{
+ 0x41, 0x20, 0x08, 0x01, 0x00, 0x01, 0x01, 0x99, 0x19, 0x99, 0x19,
+};
+
+TEST(HciPacketsTest, testLeSetExtendedScanParameters_6553) {
+ PacketView<kLittleEndian> packet_bytes_view(
+ std::make_shared<std::vector<uint8_t>>(le_set_extended_scan_parameters_6553));
+ auto view = LeSetExtendedScanParametersView::Create(
+ LeScanningCommandView::Create(CommandPacketView::Create(packet_bytes_view)));
+
+ ASSERT(view.IsValid());
+ ASSERT_EQ(1, view.GetScanningPhys());
+ auto params = view.GetParameters();
+ ASSERT_EQ(1, params.size());
+ ASSERT_EQ(LeScanType::ACTIVE, params[0].le_scan_type_);
+ ASSERT_EQ(6553, params[0].le_scan_interval_);
+ ASSERT_EQ(6553, params[0].le_scan_window_);
+}
+
+DEFINE_AND_INSTANTIATE_LeSetExtendedScanParametersReflectionTest(le_set_extended_scan_parameters,
+ le_set_extended_scan_parameters_6553);
+
+std::vector<uint8_t> le_set_extended_scan_parameters_complete{
+ 0x0e, 0x04, 0x01, 0x41, 0x20, 0x00,
+};
+DEFINE_AND_INSTANTIATE_LeSetExtendedScanParametersCompleteReflectionTest(le_set_extended_scan_parameters_complete);
+
+std::vector<uint8_t> le_set_extended_scan_enable{
+ 0x42, 0x20, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+TEST(HciPacketsTest, testLeSetExtendedScanEnable) {
+ PacketView<kLittleEndian> packet_bytes_view(std::make_shared<std::vector<uint8_t>>(le_set_extended_scan_enable));
+ auto view =
+ LeSetExtendedScanEnableView::Create(LeScanningCommandView::Create(CommandPacketView::Create(packet_bytes_view)));
+
+ ASSERT(view.IsValid());
+ ASSERT_EQ(FilterDuplicates::DISABLED, view.GetFilterDuplicates());
+ ASSERT_EQ(Enable::ENABLED, view.GetEnable());
+ ASSERT_EQ(0, view.GetDuration());
+ ASSERT_EQ(0, view.GetPeriod());
+}
+
+std::vector<uint8_t> le_set_extended_scan_enable_disable{
+ 0x42, 0x20, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+};
+
+TEST(HciPacketsTest, testLeSetExtendedScanEnableDisable) {
+ PacketView<kLittleEndian> packet_bytes_view(
+ std::make_shared<std::vector<uint8_t>>(le_set_extended_scan_enable_disable));
+ auto view =
+ LeSetExtendedScanEnableView::Create(LeScanningCommandView::Create(CommandPacketView::Create(packet_bytes_view)));
+
+ ASSERT(view.IsValid());
+ ASSERT_EQ(FilterDuplicates::ENABLED, view.GetFilterDuplicates());
+ ASSERT_EQ(Enable::DISABLED, view.GetEnable());
+ ASSERT_EQ(0, view.GetDuration());
+ ASSERT_EQ(0, view.GetPeriod());
+}
+
+DEFINE_AND_INSTANTIATE_LeSetExtendedScanEnableReflectionTest(le_set_extended_scan_enable,
+ le_set_extended_scan_enable_disable);
+
+std::vector<uint8_t> le_set_extended_scan_enable_complete{
+ 0x0e, 0x04, 0x01, 0x42, 0x20, 0x00,
+};
+DEFINE_AND_INSTANTIATE_LeSetExtendedScanEnableCompleteReflectionTest(le_set_extended_scan_enable_complete);
+
} // namespace hci
} // namespace bluetooth
diff --git a/gd/hci/le_scanning_manager.cc b/gd/hci/le_scanning_manager.cc
index 0b1bb62..ad88b44 100644
--- a/gd/hci/le_scanning_manager.cc
+++ b/gd/hci/le_scanning_manager.cc
@@ -107,12 +107,19 @@
}
void configure_scan() {
+ std::vector<PhyScanParameters> parameter_vector;
+ PhyScanParameters phy_scan_parameters;
+ phy_scan_parameters.le_scan_window_ = 0;
+ phy_scan_parameters.le_scan_interval_ = 0;
+ phy_scan_parameters.le_scan_type_ = LeScanType::ACTIVE;
+ parameter_vector.push_back(phy_scan_parameters);
+ uint8_t phys_in_use = 1;
+
switch (api_type_) {
case ScanApiType::LE_5_0:
- le_scanning_interface_->EnqueueCommand(
- hci::LeSetExtendedScanParametersBuilder::Create(LeScanType::ACTIVE, interval_ms_, window_ms_,
- own_address_type_, filter_policy_),
- common::BindOnce(impl::check_status), module_handler_);
+ le_scanning_interface_->EnqueueCommand(hci::LeSetExtendedScanParametersBuilder::Create(
+ own_address_type_, filter_policy_, phys_in_use, parameter_vector),
+ common::BindOnce(impl::check_status), module_handler_);
break;
case ScanApiType::ANDROID_HCI:
le_scanning_interface_->EnqueueCommand(
diff --git a/gd/hci/security_interface.h b/gd/hci/security_interface.h
index efb20d0..ea15aa0 100644
--- a/gd/hci/security_interface.h
+++ b/gd/hci/security_interface.h
@@ -43,6 +43,7 @@
hci::EventCode::IO_CAPABILITY_REQUEST, hci::EventCode::IO_CAPABILITY_RESPONSE,
hci::EventCode::REMOTE_OOB_DATA_REQUEST, hci::EventCode::SIMPLE_PAIRING_COMPLETE,
hci::EventCode::USER_PASSKEY_NOTIFICATION, hci::EventCode::KEYPRESS_NOTIFICATION,
+ hci::EventCode::USER_CONFIRMATION_REQUEST, hci::EventCode::USER_PASSKEY_REQUEST,
};
};
} // namespace hci
diff --git a/gd/l2cap/cid.h b/gd/l2cap/cid.h
index 9a21abb..729272c 100644
--- a/gd/l2cap/cid.h
+++ b/gd/l2cap/cid.h
@@ -36,5 +36,7 @@
constexpr Cid kSmpCid = 6;
constexpr Cid kSmpBrCid = 7;
+constexpr Cid kClassicPairingTriggerCid = kLastFixedChannel - 1;
+
} // namespace l2cap
} // namespace bluetooth
diff --git a/gd/l2cap/classic/cert/api.proto b/gd/l2cap/classic/cert/api.proto
index c7e68d5..687686f 100644
--- a/gd/l2cap/classic/cert/api.proto
+++ b/gd/l2cap/classic/cert/api.proto
@@ -5,7 +5,7 @@
import "google/protobuf/empty.proto";
import "facade/common.proto";
-service L2capModuleCert {
+service L2capClassicModuleCert {
rpc SendL2capPacket(L2capPacket) returns (google.protobuf.Empty) {}
rpc SetupLink(SetupLinkRequest) returns (SetupLinkResponse) {}
diff --git a/gd/l2cap/classic/cert/cert.cc b/gd/l2cap/classic/cert/cert.cc
index 63c8593..2de345c 100644
--- a/gd/l2cap/classic/cert/cert.cc
+++ b/gd/l2cap/classic/cert/cert.cc
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-#include "l2cap/classic/cert/cert.h"
-
#include <condition_variable>
#include <cstdint>
#include <memory>
@@ -29,6 +27,7 @@
#include "hci/cert/cert.h"
#include "hci/hci_packets.h"
#include "l2cap/classic/cert/api.grpc.pb.h"
+#include "l2cap/classic/cert/cert.h"
#include "l2cap/classic/l2cap_classic_module.h"
#include "l2cap/l2cap_packets.h"
#include "os/log.h"
@@ -52,9 +51,9 @@
constexpr auto kEventTimeout = std::chrono::seconds(1);
-class L2capModuleCertService : public L2capModuleCert::Service {
+class L2capClassicModuleCertService : public L2capClassicModuleCert::Service {
public:
- L2capModuleCertService(hci::AclManager* acl_manager, os::Handler* facade_handler)
+ L2capClassicModuleCertService(hci::AclManager* acl_manager, os::Handler* facade_handler)
: handler_(facade_handler), acl_manager_(acl_manager) {
ASSERT(handler_ != nullptr);
acl_manager_->RegisterCallbacks(&acl_callbacks, handler_);
@@ -323,7 +322,7 @@
void send_packet_from_queue() {
if (outgoing_packet_queue_.size() == 1) {
acl_connection_->GetAclQueueEnd()->RegisterEnqueue(
- handler_, common::Bind(&L2capModuleCertService::enqueue_packet_to_acl, common::Unretained(this)));
+ handler_, common::Bind(&L2capClassicModuleCertService::enqueue_packet_to_acl, common::Unretained(this)));
}
}
@@ -473,12 +472,13 @@
class AclCallbacks : public hci::ConnectionCallbacks {
public:
- AclCallbacks(L2capModuleCertService* module) : module_(module) {}
+ AclCallbacks(L2capClassicModuleCertService* module) : module_(module) {}
void OnConnectSuccess(std::unique_ptr<hci::AclConnection> connection) override {
module_->acl_connection_ = std::move(connection);
module_->acl_connection_->RegisterDisconnectCallback(common::BindOnce([](hci::ErrorCode) {}), module_->handler_);
module_->acl_connection_->GetAclQueueEnd()->RegisterDequeue(
- module_->handler_, common::Bind(&L2capModuleCertService::on_incoming_packet, common::Unretained(module_)));
+ module_->handler_,
+ common::Bind(&L2capClassicModuleCertService::on_incoming_packet, common::Unretained(module_)));
dequeue_registered_ = true;
FetchL2capLogResponse response;
response.mutable_link_up()->mutable_remote()->set_address(module_->acl_connection_->GetAddress().ToString());
@@ -494,36 +494,36 @@
bool dequeue_registered_ = false;
- L2capModuleCertService* module_;
+ L2capClassicModuleCertService* module_;
} acl_callbacks{this};
std::mutex mutex_;
};
-void L2capModuleCertModule::ListDependencies(ModuleList* list) {
+void L2capClassicModuleCertModule::ListDependencies(ModuleList* list) {
::bluetooth::grpc::GrpcFacadeModule::ListDependencies(list);
list->add<hci::AclManager>();
list->add<hci::HciLayer>();
}
-void L2capModuleCertModule::Start() {
+void L2capClassicModuleCertModule::Start() {
::bluetooth::grpc::GrpcFacadeModule::Start();
GetDependency<hci::HciLayer>()->EnqueueCommand(hci::WriteScanEnableBuilder::Create(hci::ScanEnable::PAGE_SCAN_ONLY),
common::BindOnce([](hci::CommandCompleteView) {}), GetHandler());
- service_ = new L2capModuleCertService(GetDependency<hci::AclManager>(), GetHandler());
+ service_ = new L2capClassicModuleCertService(GetDependency<hci::AclManager>(), GetHandler());
}
-void L2capModuleCertModule::Stop() {
+void L2capClassicModuleCertModule::Stop() {
delete service_;
::bluetooth::grpc::GrpcFacadeModule::Stop();
}
-::grpc::Service* L2capModuleCertModule::GetService() const {
+::grpc::Service* L2capClassicModuleCertModule::GetService() const {
return service_;
}
-const ModuleFactory L2capModuleCertModule::Factory =
- ::bluetooth::ModuleFactory([]() { return new L2capModuleCertModule(); });
+const ModuleFactory L2capClassicModuleCertModule::Factory =
+ ::bluetooth::ModuleFactory([]() { return new L2capClassicModuleCertModule(); });
} // namespace cert
} // namespace classic
diff --git a/gd/l2cap/classic/cert/cert.h b/gd/l2cap/classic/cert/cert.h
index c8015d6..d3108cd 100644
--- a/gd/l2cap/classic/cert/cert.h
+++ b/gd/l2cap/classic/cert/cert.h
@@ -9,9 +9,9 @@
namespace classic {
namespace cert {
-class L2capModuleCertService;
+class L2capClassicModuleCertService;
-class L2capModuleCertModule : public ::bluetooth::grpc::GrpcFacadeModule {
+class L2capClassicModuleCertModule : public ::bluetooth::grpc::GrpcFacadeModule {
public:
static const ModuleFactory Factory;
@@ -22,7 +22,7 @@
::grpc::Service* GetService() const override;
private:
- L2capModuleCertService* service_;
+ L2capClassicModuleCertService* service_;
};
} // namespace cert
diff --git a/gd/l2cap/classic/facade.cc b/gd/l2cap/classic/facade.cc
index 9613c75..64f3810 100644
--- a/gd/l2cap/classic/facade.cc
+++ b/gd/l2cap/classic/facade.cc
@@ -39,9 +39,9 @@
namespace l2cap {
namespace classic {
-class L2capModuleFacadeService : public L2capModuleFacade::Service {
+class L2capClassicModuleFacadeService : public L2capClassicModuleFacade::Service {
public:
- L2capModuleFacadeService(L2capClassicModule* l2cap_layer, os::Handler* facade_handler)
+ L2capClassicModuleFacadeService(L2capClassicModule* l2cap_layer, os::Handler* facade_handler)
: l2cap_layer_(l2cap_layer), facade_handler_(facade_handler) {
ASSERT(l2cap_layer_ != nullptr);
ASSERT(facade_handler_ != nullptr);
@@ -126,8 +126,8 @@
class L2capFixedChannelHelper {
public:
- L2capFixedChannelHelper(L2capModuleFacadeService* service, L2capClassicModule* l2cap_layer, os::Handler* handler,
- Cid cid)
+ L2capFixedChannelHelper(L2capClassicModuleFacadeService* service, L2capClassicModule* 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(
@@ -173,7 +173,7 @@
return packet_one;
};
- L2capModuleFacadeService* facade_service_;
+ L2capClassicModuleFacadeService* facade_service_;
L2capClassicModule* l2cap_layer_;
os::Handler* handler_;
std::unique_ptr<FixedChannelManager> fixed_channel_manager_;
@@ -192,8 +192,8 @@
class L2capDynamicChannelHelper {
public:
- L2capDynamicChannelHelper(L2capModuleFacadeService* service, L2capClassicModule* l2cap_layer, os::Handler* handler,
- Psm psm, RetransmissionFlowControlMode mode)
+ L2capDynamicChannelHelper(L2capClassicModuleFacadeService* service, L2capClassicModule* l2cap_layer,
+ os::Handler* handler, Psm psm, RetransmissionFlowControlMode mode)
: facade_service_(service), l2cap_layer_(l2cap_layer), handler_(handler), psm_(psm) {
dynamic_channel_manager_ = l2cap_layer_->GetDynamicChannelManager();
DynamicChannelConfigurationOption configuration_option;
@@ -255,7 +255,7 @@
return packet_one;
};
- L2capModuleFacadeService* facade_service_;
+ L2capClassicModuleFacadeService* facade_service_;
L2capClassicModule* l2cap_layer_;
os::Handler* handler_;
std::unique_ptr<DynamicChannelManager> dynamic_channel_manager_;
@@ -271,7 +271,7 @@
class L2capStreamCallback : public ::bluetooth::grpc::GrpcEventStreamCallback<L2capPacket, L2capPacket> {
public:
- L2capStreamCallback(L2capModuleFacadeService* service) : service_(service) {}
+ L2capStreamCallback(L2capClassicModuleFacadeService* service) : service_(service) {}
~L2capStreamCallback() {
for (const auto& connection : service_->fixed_channel_helper_map_) {
@@ -329,7 +329,7 @@
response->CopyFrom(event);
}
- L2capModuleFacadeService* service_;
+ L2capClassicModuleFacadeService* service_;
std::map<Cid, bool> subscribed_fixed_channel_;
std::map<Psm, bool> subscribed_dynamic_channel_;
@@ -339,30 +339,30 @@
std::mutex mutex_;
};
-void L2capModuleFacadeModule::ListDependencies(ModuleList* list) {
+void L2capClassicModuleFacadeModule::ListDependencies(ModuleList* list) {
::bluetooth::grpc::GrpcFacadeModule::ListDependencies(list);
list->add<l2cap::classic::L2capClassicModule>();
list->add<hci::HciLayer>();
}
-void L2capModuleFacadeModule::Start() {
+void L2capClassicModuleFacadeModule::Start() {
::bluetooth::grpc::GrpcFacadeModule::Start();
GetDependency<hci::HciLayer>()->EnqueueCommand(hci::WriteScanEnableBuilder::Create(hci::ScanEnable::PAGE_SCAN_ONLY),
common::BindOnce([](hci::CommandCompleteView) {}), GetHandler());
- service_ = new L2capModuleFacadeService(GetDependency<l2cap::classic::L2capClassicModule>(), GetHandler());
+ service_ = new L2capClassicModuleFacadeService(GetDependency<l2cap::classic::L2capClassicModule>(), GetHandler());
}
-void L2capModuleFacadeModule::Stop() {
+void L2capClassicModuleFacadeModule::Stop() {
delete service_;
::bluetooth::grpc::GrpcFacadeModule::Stop();
}
-::grpc::Service* L2capModuleFacadeModule::GetService() const {
+::grpc::Service* L2capClassicModuleFacadeModule::GetService() const {
return service_;
}
-const ModuleFactory L2capModuleFacadeModule::Factory =
- ::bluetooth::ModuleFactory([]() { return new L2capModuleFacadeModule(); });
+const ModuleFactory L2capClassicModuleFacadeModule::Factory =
+ ::bluetooth::ModuleFactory([]() { return new L2capClassicModuleFacadeModule(); });
} // namespace classic
} // namespace l2cap
diff --git a/gd/l2cap/classic/facade.h b/gd/l2cap/classic/facade.h
index 425940a..ebaee0d 100644
--- a/gd/l2cap/classic/facade.h
+++ b/gd/l2cap/classic/facade.h
@@ -16,15 +16,16 @@
#pragma once
#include <grpc++/grpc++.h>
+
#include "grpc/grpc_module.h"
namespace bluetooth {
namespace l2cap {
namespace classic {
-class L2capModuleFacadeService;
+class L2capClassicModuleFacadeService;
-class L2capModuleFacadeModule : public ::bluetooth::grpc::GrpcFacadeModule {
+class L2capClassicModuleFacadeModule : public ::bluetooth::grpc::GrpcFacadeModule {
public:
static const ModuleFactory Factory;
@@ -35,7 +36,7 @@
::grpc::Service* GetService() const override;
private:
- L2capModuleFacadeService* service_;
+ L2capClassicModuleFacadeService* service_;
};
} // namespace classic
diff --git a/gd/l2cap/classic/facade.proto b/gd/l2cap/classic/facade.proto
index 7eb780d..ab2a911 100644
--- a/gd/l2cap/classic/facade.proto
+++ b/gd/l2cap/classic/facade.proto
@@ -5,7 +5,7 @@
import "google/protobuf/empty.proto";
import "facade/common.proto";
-service L2capModuleFacade {
+service L2capClassicModuleFacade {
rpc RegisterChannel(RegisterChannelRequest) returns (google.protobuf.Empty) {
// Testing Android Bluetooth stack only. Optional for other stack.
}
diff --git a/gd/l2cap/classic/fixed_channel_manager.h b/gd/l2cap/classic/fixed_channel_manager.h
index 69812df..5e8f6ab 100644
--- a/gd/l2cap/classic/fixed_channel_manager.h
+++ b/gd/l2cap/classic/fixed_channel_manager.h
@@ -31,6 +31,10 @@
class L2capClassicModule;
+namespace testing {
+class MockFixedChannelManager;
+}
+
namespace internal {
class LinkManager;
class FixedChannelServiceManagerImpl;
@@ -102,7 +106,7 @@
*
* Returns: true if connection was able to be initiated, false otherwise.
*/
- bool ConnectServices(hci::Address device, OnConnectionFailureCallback on_fail_callback, os::Handler* handler);
+ 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.
@@ -124,11 +128,14 @@
* @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, const SecurityPolicy& security_policy,
- OnRegistrationCompleteCallback on_registration_complete,
- OnConnectionOpenCallback on_connection_open, os::Handler* handler);
+ virtual bool RegisterService(Cid cid, const SecurityPolicy& security_policy,
+ OnRegistrationCompleteCallback on_registration_complete,
+ OnConnectionOpenCallback on_connection_open, os::Handler* handler);
+
+ virtual ~FixedChannelManager() = default;
friend class L2capClassicModule;
+ friend class testing::MockFixedChannelManager;
private:
// The constructor is not to be used by user code
diff --git a/gd/l2cap/classic/fixed_channel_manager_mock.h b/gd/l2cap/classic/fixed_channel_manager_mock.h
new file mode 100644
index 0000000..5ead957
--- /dev/null
+++ b/gd/l2cap/classic/fixed_channel_manager_mock.h
@@ -0,0 +1,42 @@
+/*
+ * 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_manager.h"
+
+#include <gmock/gmock.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, const SecurityPolicy& security_policy, OnRegistrationCompleteCallback on_registration_complete,
+ OnConnectionOpenCallback on_connection_open, os::Handler* handler),
+ (override));
+};
+
+} // namespace testing
+} // namespace classic
+} // namespace l2cap
+} // namespace bluetooth
diff --git a/gd/l2cap/classic/internal/dynamic_channel_impl.cc b/gd/l2cap/classic/internal/dynamic_channel_impl.cc
index ba613a6..c0614f9 100644
--- a/gd/l2cap/classic/internal/dynamic_channel_impl.cc
+++ b/gd/l2cap/classic/internal/dynamic_channel_impl.cc
@@ -102,21 +102,17 @@
sender_ = sender;
}
-Mtu DynamicChannelImpl::GetIncomingMtu() const {
- return incoming_mtu_;
-}
-
void DynamicChannelImpl::SetIncomingMtu(Mtu mtu) {
- incoming_mtu_ = mtu;
+ sender_->SetIncomingMtu(mtu);
}
void DynamicChannelImpl::SetRetransmissionFlowControlConfig(
const RetransmissionAndFlowControlConfigurationOption& option) {
- sender_->SetChannelRetransmissionFlowControlMode(option.mode_);
+ sender_->SetChannelRetransmissionFlowControlMode(option);
}
void DynamicChannelImpl::SetFcsType(FcsType fcs_type) {
- fcs_type_ = fcs_type;
+ sender_->SetFcsType(fcs_type);
}
} // namespace internal
diff --git a/gd/l2cap/classic/internal/dynamic_channel_impl.h b/gd/l2cap/classic/internal/dynamic_channel_impl.h
index ac1f02c..95be5c7 100644
--- a/gd/l2cap/classic/internal/dynamic_channel_impl.h
+++ b/gd/l2cap/classic/internal/dynamic_channel_impl.h
@@ -82,7 +82,6 @@
*/
void SetSender(l2cap::internal::Sender* sender) override;
- virtual Mtu GetIncomingMtu() const;
virtual void SetIncomingMtu(Mtu mtu);
virtual void SetRetransmissionFlowControlConfig(const RetransmissionAndFlowControlConfigurationOption& mode);
@@ -114,9 +113,6 @@
ConfigurationStatus incoming_configuration_status_ = ConfigurationStatus::NOT_CONFIGURED;
l2cap::internal::Sender* sender_ = nullptr;
- Mtu incoming_mtu_ = kDefaultClassicMtu;
- // TODO: Add all RetransmissionAndFlowControlConfigurationOptions
- FcsType fcs_type_ = FcsType::DEFAULT;
DISALLOW_COPY_AND_ASSIGN(DynamicChannelImpl);
};
diff --git a/gd/l2cap/classic/internal/link.h b/gd/l2cap/classic/internal/link.h
index 2c6c1b8..09d7eb9 100644
--- a/gd/l2cap/classic/internal/link.h
+++ b/gd/l2cap/classic/internal/link.h
@@ -99,7 +99,7 @@
virtual void NotifyChannelCreation(Cid cid, std::unique_ptr<DynamicChannel> channel);
virtual void NotifyChannelFail(Cid cid);
- // Information received from signalling channel
+ // Information received from signaling channel
virtual void SetRemoteConnectionlessMtu(Mtu mtu);
virtual Mtu GetRemoteConnectionlessMtu() const;
virtual void SetRemoteSupportsErtm(bool supported);
@@ -107,6 +107,10 @@
virtual void SetRemoteSupportsFcs(bool supported);
virtual bool GetRemoteSupportsFcs() const;
+ virtual std::string ToString() {
+ return GetDevice().ToString();
+ }
+
private:
os::Handler* l2cap_handler_;
l2cap::internal::FixedChannelAllocator<FixedChannelImpl, Link> fixed_channel_allocator_{this, l2cap_handler_};
diff --git a/gd/l2cap/classic/internal/signalling_manager.cc b/gd/l2cap/classic/internal/signalling_manager.cc
index 66a3f51..7398c17 100644
--- a/gd/l2cap/classic/internal/signalling_manager.cc
+++ b/gd/l2cap/classic/internal/signalling_manager.cc
@@ -310,7 +310,6 @@
return;
}
- RetransmissionAndFlowControlConfigurationOption rfc_option;
channel->SetOutgoingConfigurationStatus(DynamicChannelImpl::ConfigurationStatus::CONFIGURED);
if (channel->GetIncomingConfigurationStatus() == DynamicChannelImpl::ConfigurationStatus::CONFIGURED) {
std::unique_ptr<DynamicChannel> user_channel = std::make_unique<DynamicChannel>(channel, handler_);
diff --git a/gd/l2cap/classic/l2cap_classic_module.cc b/gd/l2cap/classic/l2cap_classic_module.cc
index bc30c86..ca5a0d5 100644
--- a/gd/l2cap/classic/l2cap_classic_module.cc
+++ b/gd/l2cap/classic/l2cap_classic_module.cc
@@ -50,6 +50,10 @@
&dynamic_channel_service_manager_impl_, ¶meter_provider_};
};
+L2capClassicModule::L2capClassicModule() {}
+
+L2capClassicModule::~L2capClassicModule() {}
+
void L2capClassicModule::ListDependencies(ModuleList* list) {
list->add<hci::AclManager>();
}
@@ -78,4 +82,4 @@
} // namespace classic
} // namespace l2cap
-} // namespace bluetooth
\ No newline at end of file
+} // namespace bluetooth
diff --git a/gd/l2cap/classic/l2cap_classic_module.h b/gd/l2cap/classic/l2cap_classic_module.h
index 7255bc3..388cae2 100644
--- a/gd/l2cap/classic/l2cap_classic_module.h
+++ b/gd/l2cap/classic/l2cap_classic_module.h
@@ -27,18 +27,18 @@
class L2capClassicModule : public bluetooth::Module {
public:
- L2capClassicModule() = default;
- ~L2capClassicModule() = default;
+ L2capClassicModule();
+ virtual ~L2capClassicModule();
/**
* Get the api to the classic fixed channel l2cap module
*/
- std::unique_ptr<FixedChannelManager> GetFixedChannelManager();
+ virtual std::unique_ptr<FixedChannelManager> GetFixedChannelManager();
/**
* Get the api to the classic dynamic channel l2cap module
*/
- std::unique_ptr<DynamicChannelManager> GetDynamicChannelManager();
+ virtual std::unique_ptr<DynamicChannelManager> GetDynamicChannelManager();
static const ModuleFactory Factory;
@@ -59,4 +59,4 @@
} // namespace classic
} // namespace l2cap
-} // namespace bluetooth
\ No newline at end of file
+} // namespace bluetooth
diff --git a/gd/l2cap/classic/l2cap_classic_module_mock.h b/gd/l2cap/classic/l2cap_classic_module_mock.h
new file mode 100644
index 0000000..1252854
--- /dev/null
+++ b/gd/l2cap/classic/l2cap_classic_module_mock.h
@@ -0,0 +1,37 @@
+/*
+ * 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/l2cap_classic_module.h"
+
+#include <gmock/gmock.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/gd/l2cap/internal/basic_mode_channel_data_controller.cc b/gd/l2cap/internal/basic_mode_channel_data_controller.cc
index 1a049aa..3575e25 100644
--- a/gd/l2cap/internal/basic_mode_channel_data_controller.cc
+++ b/gd/l2cap/internal/basic_mode_channel_data_controller.cc
@@ -16,6 +16,8 @@
#include "l2cap/internal/basic_mode_channel_data_controller.h"
+#include "l2cap/l2cap_packets.h"
+
namespace bluetooth {
namespace l2cap {
namespace internal {
@@ -31,11 +33,15 @@
scheduler_->OnPacketsReady(cid_, 1);
}
-void BasicModeDataController::OnPdu(BasicFrameView pdu) {
- enqueue_buffer_.Enqueue(std::make_unique<PacketView<kLittleEndian>>(pdu.GetPayload()), handler_);
+void BasicModeDataController::OnPdu(packet::PacketView<true> pdu) {
+ auto basic_frame_view = BasicFrameView::Create(pdu);
+ if (!basic_frame_view.IsValid()) {
+ return;
+ }
+ enqueue_buffer_.Enqueue(std::make_unique<PacketView<kLittleEndian>>(basic_frame_view.GetPayload()), handler_);
}
-std::unique_ptr<BasicFrameBuilder> BasicModeDataController::GetNextPacket() {
+std::unique_ptr<packet::BasePacketBuilder> BasicModeDataController::GetNextPacket() {
auto next = std::move(pdu_queue_.front());
pdu_queue_.pop();
return next;
diff --git a/gd/l2cap/internal/basic_mode_channel_data_controller.h b/gd/l2cap/internal/basic_mode_channel_data_controller.h
index c19fb93..8e40402 100644
--- a/gd/l2cap/internal/basic_mode_channel_data_controller.h
+++ b/gd/l2cap/internal/basic_mode_channel_data_controller.h
@@ -46,16 +46,19 @@
void OnSdu(std::unique_ptr<packet::BasePacketBuilder> sdu) override;
- void OnPdu(BasicFrameView pdu) override;
+ void OnPdu(packet::PacketView<true> pdu) override;
- std::unique_ptr<BasicFrameBuilder> GetNextPacket() 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<BasicFrameBuilder>> pdu_queue_;
+ std::queue<std::unique_ptr<packet::BasePacketBuilder>> pdu_queue_;
Scheduler* scheduler_;
};
diff --git a/gd/l2cap/internal/basic_mode_channel_data_controller_test.cc b/gd/l2cap/internal/basic_mode_channel_data_controller_test.cc
index 35c3002..c4cc56d 100644
--- a/gd/l2cap/internal/basic_mode_channel_data_controller_test.cc
+++ b/gd/l2cap/internal/basic_mode_channel_data_controller_test.cc
@@ -74,22 +74,28 @@
testing::MockScheduler scheduler;
BasicModeDataController controller{1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
EXPECT_CALL(scheduler, OnPacketsReady(1, 1));
- controller.OnSdu(CreateSdu({1, 2, 3}));
+ 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(CreateSdu({0, 0, 1, 0}));
- auto basic_frame_view = BasicFrameView::Create(base_view);
- EXPECT_TRUE(basic_frame_view.IsValid());
- controller.OnPdu(basic_frame_view);
+ 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
diff --git a/gd/l2cap/internal/data_controller.h b/gd/l2cap/internal/data_controller.h
index 18cff2a..bc7c2e5 100644
--- a/gd/l2cap/internal/data_controller.h
+++ b/gd/l2cap/internal/data_controller.h
@@ -34,10 +34,18 @@
virtual void OnSdu(std::unique_ptr<packet::BasePacketBuilder> sdu) = 0;
// PDUs -> SDU and enqueue to channel queue end
- virtual void OnPdu(BasicFrameView pdu) = 0;
+ virtual void OnPdu(packet::PacketView<true> pdu) = 0;
// Used by Scheduler to get next PDU
- virtual std::unique_ptr<BasicFrameBuilder> GetNextPacket() = 0;
+ 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
diff --git a/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.cc b/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.cc
index 3e5042d..2a1b930 100644
--- a/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.cc
+++ b/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.cc
@@ -555,13 +555,23 @@
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<EnhancedInformationFrameBuilder> builder;
+ std::unique_ptr<packet::BasePacketBuilder> builder;
if (sar == SegmentationAndReassembly::START) {
- builder = EnhancedInformationStartFrameBuilder::Create(controller_->remote_cid_, tx_seq, f, req_seq, sdu_size,
- std::move(segment));
+ 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 {
- builder = EnhancedInformationFrameBuilder::Create(controller_->remote_cid_, tx_seq, f, req_seq, sar,
- std::move(segment));
+ 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));
}
@@ -575,7 +585,6 @@
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);
- // TODO hsz fix me
unacked_frames_++;
frames_sent_++;
retry_i_frames_[next_tx_seq_] = 1;
@@ -599,7 +608,12 @@
}
void _send_s_frame(SupervisoryFunction s, uint8_t req_seq, Poll p, Final f) {
- auto builder = EnhancedSupervisoryFrameBuilder::Create(controller_->remote_cid_, s, p, f, req_seq);
+ 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));
}
@@ -770,13 +784,9 @@
// Segmentation is handled here
void ErtmController::OnSdu(std::unique_ptr<packet::BasePacketBuilder> sdu) {
- // TODO: Optimize the calculation. We don't need to count for SDU length in CONTINUATION or END packets. We don't need
- // to FCS when disabled.
- size_t size_each_packet =
- (remote_mps_ - 4 /* basic L2CAP header */ - 2 /* SDU length */ - 2 /* Extended control */ - 2 /* FCS */);
auto sdu_size = sdu->size();
std::vector<std::unique_ptr<packet::RawBuilder>> segments;
- packet::FragmentingInserter fragmenting_inserter(size_each_packet, std::back_insert_iterator(segments));
+ packet::FragmentingInserter fragmenting_inserter(size_each_packet_, std::back_insert_iterator(segments));
sdu->Serialize(fragmenting_inserter);
fragmenting_inserter.finalize();
if (segments.size() == 1) {
@@ -790,8 +800,20 @@
pimpl_->data_request(SegmentationAndReassembly::END, std::move(segments.back()));
}
-void ErtmController::OnPdu(BasicFrameView pdu) {
- auto standard_frame_view = StandardFrameView::Create(pdu);
+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;
@@ -833,7 +855,54 @@
}
}
-std::unique_ptr<BasicFrameBuilder> ErtmController::GetNextPacket() {
+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;
+ }
+ pimpl_->recv_i_frame(i_frame_view.GetF(), i_frame_view.GetTxSeq(), i_frame_view.GetReqSeq(), i_frame_view.GetSar(),
+ 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;
@@ -875,11 +944,23 @@
}
}
-void ErtmController::send_pdu(std::unique_ptr<BasicFrameBuilder> pdu) {
+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) {
+ local_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_;
+}
+
void ErtmController::close_channel() {
// TODO: Get a reference to signalling manager
}
diff --git a/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.h b/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.h
index 0566e0b..14deea3 100644
--- a/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.h
+++ b/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.h
@@ -47,18 +47,19 @@
~ErtmController();
// Segmentation is handled here
void OnSdu(std::unique_ptr<packet::BasePacketBuilder> sdu) override;
- void OnPdu(BasicFrameView pdu) override;
- std::unique_ptr<BasicFrameBuilder> GetNextPacket() 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:
- [[maybe_unused]] Cid cid_;
- [[maybe_unused]] Cid remote_cid_;
- [[maybe_unused]] os::EnqueueBuffer<UpperEnqueue> enqueue_buffer_;
- [[maybe_unused]] os::Handler* handler_;
- std::queue<std::unique_ptr<BasicFrameBuilder>> pdu_queue_;
- [[maybe_unused]] Scheduler* scheduler_;
- // TODO: Support FCS
- [[maybe_unused]] FcsType fcs_type_ = FcsType::NO_FCS;
+ Cid cid_;
+ Cid remote_cid_;
+ os::EnqueueBuffer<UpperEnqueue> enqueue_buffer_;
+ os::Handler* handler_;
+ std::queue<std::unique_ptr<packet::BasePacketBuilder>> pdu_queue_;
+ Scheduler* scheduler_;
+ bool fcs_enabled_ = false;
class PacketViewForReassembly : public packet::PacketView<kLittleEndian> {
public:
@@ -84,12 +85,14 @@
SegmentationAndReassembly sar_state_ = SegmentationAndReassembly::END;
void stage_for_reassembly(SegmentationAndReassembly sar, const packet::PacketView<kLittleEndian>& payload);
- void send_pdu(std::unique_ptr<BasicFrameBuilder> pdu);
+ 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);
+
// Configuration options
- // TODO: Configure these number
uint16_t local_tx_window_ = 10;
uint16_t local_max_transmit_ = 20;
uint16_t local_retransmit_timeout_ms_ = 2000;
@@ -98,6 +101,9 @@
uint16_t remote_tx_window_ = 10;
uint16_t remote_mps_ = 1010;
+ uint16_t size_each_packet_ =
+ (remote_mps_ - 4 /* basic L2CAP header */ - 2 /* SDU length */ - 2 /* Extended control */ - 2 /* FCS */);
+
struct impl;
std::unique_ptr<impl> pimpl_;
};
diff --git a/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller_test.cc b/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller_test.cc
index dd87e36..04ef82b 100644
--- a/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller_test.cc
+++ b/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller_test.cc
@@ -70,7 +70,29 @@
os::Handler* queue_handler_ = nullptr;
};
-TEST_F(ErtmDataControllerTest, receive) {
+TEST_F(ErtmDataControllerTest, transmit_no_fcs) {
+ common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10};
+ testing::MockScheduler scheduler;
+ ErtmController 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 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;
ErtmController controller{1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
@@ -78,9 +100,47 @@
auto builder = EnhancedInformationFrameBuilder::Create(1, 0, Final::NOT_SET, 0,
SegmentationAndReassembly::UNSEGMENTED, std::move(segment));
auto base_view = GetPacketView(std::move(builder));
- auto basic_frame_view = BasicFrameView::Create(base_view);
- EXPECT_TRUE(basic_frame_view.IsValid());
- controller.OnPdu(basic_frame_view);
+ 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, transmit_with_fcs) {
+ common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10};
+ testing::MockScheduler scheduler;
+ ErtmController controller{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;
+ ErtmController controller{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);
diff --git a/gd/l2cap/internal/fixed_channel_allocator.h b/gd/l2cap/internal/fixed_channel_allocator.h
index a421c91..b821cb1 100644
--- a/gd/l2cap/internal/fixed_channel_allocator.h
+++ b/gd/l2cap/internal/fixed_channel_allocator.h
@@ -44,20 +44,17 @@
// 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, SecurityPolicy security_policy) {
- ASSERT_LOG(!IsChannelAllocated((cid)), "Cid 0x%x for device %s is already in use", cid,
- link_->GetDevice().ToString().c_str());
+ ASSERT_LOG(!IsChannelAllocated((cid)), "Cid 0x%x for link %s is already in use", cid, link_->ToString().c_str());
ASSERT_LOG(cid >= kFirstFixedChannel && cid <= kLastFixedChannel, "Cid %d out of bound", cid);
auto elem = channels_.try_emplace(cid, std::make_shared<FixedChannelImplType>(cid, link_, l2cap_handler_));
- ASSERT_LOG(elem.second, "Failed to create channel for cid 0x%x device %s", cid,
- link_->GetDevice().ToString().c_str());
+ ASSERT_LOG(elem.second, "Failed to create channel for cid 0x%x link %s", cid, link_->ToString().c_str());
ASSERT(elem.first->second != nullptr);
return elem.first->second;
}
// Frees a channel. If cid doesn't exist, it will crash
virtual void FreeChannel(Cid cid) {
- ASSERT_LOG(IsChannelAllocated(cid), "Channel is not in use: cid %d, device %s", cid,
- link_->GetDevice().ToString().c_str());
+ ASSERT_LOG(IsChannelAllocated(cid), "Channel is not in use: cid %d, link %s", cid, link_->ToString().c_str());
channels_.erase(cid);
}
@@ -66,8 +63,7 @@
}
virtual std::shared_ptr<FixedChannelImplType> FindChannel(Cid cid) {
- ASSERT_LOG(IsChannelAllocated(cid), "Channel is not in use: cid %d, device %s", cid,
- link_->GetDevice().ToString().c_str());
+ ASSERT_LOG(IsChannelAllocated(cid), "Channel is not in use: cid %d, link %s", cid, link_->ToString().c_str());
return channels_.find(cid)->second;
}
diff --git a/gd/l2cap/internal/receiver.cc b/gd/l2cap/internal/receiver.cc
index 437064e..e92de0b 100644
--- a/gd/l2cap/internal/receiver.cc
+++ b/gd/l2cap/internal/receiver.cc
@@ -48,7 +48,7 @@
LOG_WARN("Received a packet with invalid cid: %d", cid);
return;
}
- data_controller->OnPdu(basic_frame_view);
+ data_controller->OnPdu(*packet);
}
} // namespace internal
diff --git a/gd/l2cap/internal/sender.cc b/gd/l2cap/internal/sender.cc
index ffe2755..7fe1dd7 100644
--- a/gd/l2cap/internal/sender.cc
+++ b/gd/l2cap/internal/sender.cc
@@ -55,22 +55,28 @@
return data_controller_->GetNextPacket();
}
-void Sender::SetChannelRetransmissionFlowControlMode(RetransmissionAndFlowControlModeOption mode) {
- if (mode_ == mode) {
+void Sender::SetChannelRetransmissionFlowControlMode(const RetransmissionAndFlowControlConfigurationOption& option) {
+ if (mode_ == option.mode_) {
return;
}
- if (mode == RetransmissionAndFlowControlModeOption::L2CAP_BASIC) {
+ if (option.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) {
+ if (option.mode_ == RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION) {
data_controller_ =
std::make_unique<ErtmController>(channel_id_, remote_channel_id_, queue_end_, handler_, scheduler_);
+ data_controller_->SetRetransmissionAndFlowControlOptions(option);
return;
}
}
+void Sender::SetFcsType(FcsType fcs_type) {
+ // TODO: FCS is enabled when "not both side explicitly disable it".
+ data_controller_->EnableFcs(fcs_type == FcsType::DEFAULT);
+}
+
void Sender::SetIncomingMtu(Mtu mtu) {
// TODO: Enforce MTU
}
diff --git a/gd/l2cap/internal/sender.h b/gd/l2cap/internal/sender.h
index 22f7737..850a88d 100644
--- a/gd/l2cap/internal/sender.h
+++ b/gd/l2cap/internal/sender.h
@@ -25,6 +25,7 @@
#include "l2cap/cid.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"
@@ -60,8 +61,8 @@
*/
std::unique_ptr<UpperDequeue> GetNextPacket();
- void SetChannelRetransmissionFlowControlMode(RetransmissionAndFlowControlModeOption mode);
-
+ void SetChannelRetransmissionFlowControlMode(const RetransmissionAndFlowControlConfigurationOption& option);
+ void SetFcsType(FcsType fcs_type);
void SetIncomingMtu(Mtu mtu);
DataController* GetDataController();
diff --git a/gd/l2cap/le/fixed_channel.cc b/gd/l2cap/le/fixed_channel.cc
index 1e6a163..d02dad6 100644
--- a/gd/l2cap/le/fixed_channel.cc
+++ b/gd/l2cap/le/fixed_channel.cc
@@ -49,4 +49,4 @@
}
} // namespace le
} // namespace l2cap
-} // namespace bluetooth
\ No newline at end of file
+} // namespace bluetooth
diff --git a/gd/l2cap/le/fixed_channel_manager.h b/gd/l2cap/le/fixed_channel_manager.h
index ea1a346..4583310 100644
--- a/gd/l2cap/le/fixed_channel_manager.h
+++ b/gd/l2cap/le/fixed_channel_manager.h
@@ -50,9 +50,9 @@
hci::ErrorCode hci_error = hci::ErrorCode::SUCCESS;
};
/**
- * OnConnectionFailureCallback(std::string failure_reason);
+ * OnConnectionFailureCallback(ConnectionResult failure_reason);
*/
- using OnConnectionFailureCallback = common::OnceCallback<void(ConnectionResult result)>;
+ using OnConnectionFailureCallback = common::OnceCallback<void(ConnectionResult)>;
/**
* OnConnectionOpenCallback(FixedChannel channel);
diff --git a/gd/l2cap/le/internal/fixed_channel_impl_test.cc b/gd/l2cap/le/internal/fixed_channel_impl_test.cc
index 9874936..a4270b4 100644
--- a/gd/l2cap/le/internal/fixed_channel_impl_test.cc
+++ b/gd/l2cap/le/internal/fixed_channel_impl_test.cc
@@ -14,8 +14,8 @@
* limitations under the License.
*/
#include "l2cap/le/internal/fixed_channel_impl.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"
diff --git a/gd/l2cap/le/internal/link.h b/gd/l2cap/le/internal/link.h
index 5dc8ae4..783e03b 100644
--- a/gd/l2cap/le/internal/link.h
+++ b/gd/l2cap/le/internal/link.h
@@ -90,6 +90,10 @@
}
}
+ virtual std::string ToString() {
+ return GetDevice().ToString();
+ }
+
private:
os::Handler* l2cap_handler_;
l2cap::internal::FixedChannelAllocator<FixedChannelImpl, Link> fixed_channel_allocator_{this, l2cap_handler_};
diff --git a/gd/l2cap/le/internal/link_mock.h b/gd/l2cap/le/internal/link_mock.h
index 3411c95..08ea629 100644
--- a/gd/l2cap/le/internal/link_mock.h
+++ b/gd/l2cap/le/internal/link_mock.h
@@ -16,7 +16,7 @@
#pragma once
#include "hci/acl_manager_mock.h"
-#include "hci/address.h"
+#include "hci/address_with_type.h"
#include "l2cap/internal/scheduler_mock.h"
#include "l2cap/le/internal/link.h"
@@ -50,4 +50,4 @@
} // namespace internal
} // namespace le
} // namespace l2cap
-} // namespace bluetooth
\ No newline at end of file
+} // namespace bluetooth
diff --git a/gd/security/internal/security_manager_impl.cc b/gd/security/internal/security_manager_impl.cc
index 26179b5..b245ff9 100644
--- a/gd/security/internal/security_manager_impl.cc
+++ b/gd/security/internal/security_manager_impl.cc
@@ -121,20 +121,20 @@
LOG_ALWAYS_FATAL("Listener has not been registered!");
}
-void SecurityManagerImpl::NotifyDeviceBonded(std::shared_ptr<Device> device) {
+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(std::shared_ptr<Device> device) {
+void SecurityManagerImpl::NotifyDeviceBondFailed(hci::AddressWithType device) {
for (auto& iter : listeners_) {
iter.second->Post(
common::Bind(&ISecurityManagerListener::OnDeviceBondFailed, common::Unretained(iter.first), device));
}
}
-void SecurityManagerImpl::NotifyDeviceUnbonded(std::shared_ptr<Device> device) {
+void SecurityManagerImpl::NotifyDeviceUnbonded(hci::AddressWithType device) {
for (auto& iter : listeners_) {
iter.second->Post(
common::Bind(&ISecurityManagerListener::OnDeviceUnbonded, common::Unretained(iter.first), device));
diff --git a/gd/security/internal/security_manager_impl.h b/gd/security/internal/security_manager_impl.h
index 23b39e1..d6768c9 100644
--- a/gd/security/internal/security_manager_impl.h
+++ b/gd/security/internal/security_manager_impl.h
@@ -93,9 +93,9 @@
protected:
std::vector<std::pair<ISecurityManagerListener*, os::Handler*>> listeners_;
- void NotifyDeviceBonded(std::shared_ptr<bluetooth::hci::Device> device);
- void NotifyDeviceBondFailed(std::shared_ptr<bluetooth::hci::Device> device);
- void NotifyDeviceUnbonded(std::shared_ptr<bluetooth::hci::Device> device);
+ void NotifyDeviceBonded(hci::AddressWithType device);
+ void NotifyDeviceBondFailed(hci::AddressWithType device);
+ void NotifyDeviceUnbonded(hci::AddressWithType device);
// ISecurityManagerChannel
void OnChangeConnectionLinkKeyComplete(std::shared_ptr<hci::Device> device,
diff --git a/gd/security/security_manager.h b/gd/security/security_manager.h
index deb2788..d83c8d3 100644
--- a/gd/security/security_manager.h
+++ b/gd/security/security_manager.h
@@ -21,8 +21,8 @@
#include <memory>
#include <vector>
+#include "hci/address_with_type.h"
#include "hci/device.h"
-#include "hci/device_database.h"
#include "security/internal/security_manager_impl.h"
namespace bluetooth {
@@ -38,23 +38,23 @@
/**
* Called when a device is successfully bonded.
*
- * @param device pointer to the bonded device
+ * @param address of the newly bonded device
*/
- virtual void OnDeviceBonded(std::shared_ptr<bluetooth::hci::Device> device) = 0;
+ virtual void OnDeviceBonded(bluetooth::hci::AddressWithType device) = 0;
/**
* Called when a device is successfully un-bonded.
*
- * @param device pointer to the device that is no longer bonded
+ * @param address of device that is no longer bonded
*/
- virtual void OnDeviceUnbonded(std::shared_ptr<bluetooth::hci::Device> device) = 0;
+ virtual void OnDeviceUnbonded(bluetooth::hci::AddressWithType device) = 0;
/**
* Called as a result of a failure during the bonding process.
*
- * @param device pointer to the device that is no longer bonded
+ * @param address of the device that failed to bond
*/
- virtual void OnDeviceBondFailed(std::shared_ptr<bluetooth::hci::Device> device) = 0;
+ virtual void OnDeviceBondFailed(bluetooth::hci::AddressWithType device) = 0;
};
/**
diff --git a/test/rootcanal/bluetooth_hci.cc b/test/rootcanal/bluetooth_hci.cc
index 3a636f5..2bebd9a 100644
--- a/test/rootcanal/bluetooth_hci.cc
+++ b/test/rootcanal/bluetooth_hci.cc
@@ -104,7 +104,9 @@
controller_ = std::make_shared<DualModeController>();
- controller_->Initialize({"dmc", "3C:5A:B4:01:02:03"});
+ char mac_property[PROPERTY_VALUE_MAX] = "";
+ property_get("bt.rootcanal_mac_address", mac_property, "3C:5A:B4:01:02:03");
+ controller_->Initialize({"dmc", std::string(mac_property)});
controller_->RegisterEventChannel(
[this, cb](std::shared_ptr<std::vector<uint8_t>> packet) {