Snap for 9720638 from 517203d1c9611e78f569a140405607802e107d21 to tm-qpr3-release
Change-Id: Idcfff2440eb79e4fac7495e7d3139925b52854b0
diff --git a/sysprop/hfp.sysprop b/sysprop/hfp.sysprop
index 81b04f5..d2cf1d6 100644
--- a/sysprop/hfp.sysprop
+++ b/sysprop/hfp.sysprop
@@ -9,4 +9,12 @@
prop_name: "bluetooth.hfp.hf_services_mask.config"
}
+prop {
+ api_name: "version"
+ type: Integer
+ scope: Internal
+ access: Readonly
+ prop_name: "bluetooth.hfp.version.config"
+}
+
diff --git a/system/blueberry/tests/sl4a_sl4a/l2cap/le_l2cap_coc_test.py b/system/blueberry/tests/sl4a_sl4a/l2cap/le_l2cap_coc_test.py
new file mode 100644
index 0000000..ee94901
--- /dev/null
+++ b/system/blueberry/tests/sl4a_sl4a/l2cap/le_l2cap_coc_test.py
@@ -0,0 +1,169 @@
+#!/usr/bin/env python3
+#
+# Copyright 2022 - The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import binascii
+import io
+import logging
+import os
+import queue
+import time
+
+from blueberry.tests.gd.cert.context import get_current_context
+from blueberry.tests.gd.cert.truth import assertThat
+from blueberry.tests.gd_sl4a.lib.bt_constants import ble_address_types
+from blueberry.tests.sl4a_sl4a.lib import sl4a_sl4a_base_test
+from blueberry.tests.sl4a_sl4a.lib.security import Security
+
+
+class LeL2capCoCTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass):
+
+ def __get_cert_public_address_and_irk_from_bt_config(self):
+ # Pull IRK from SL4A cert side to pass in from SL4A DUT side when scanning
+ bt_config_file_path = os.path.join(get_current_context().get_full_output_path(),
+ "DUT_%s_bt_config.conf" % self.cert.serial)
+ try:
+ self.cert.adb.pull(["/data/misc/bluedroid/bt_config.conf", bt_config_file_path])
+ except AdbError as error:
+ logging.error("Failed to pull SL4A cert BT config")
+ return False
+ logging.debug("Reading SL4A cert BT config")
+ with io.open(bt_config_file_path) as f:
+ for line in f.readlines():
+ stripped_line = line.strip()
+ if (stripped_line.startswith("Address")):
+ address_fields = stripped_line.split(' ')
+ # API currently requires public address to be capitalized
+ address = address_fields[2].upper()
+ logging.debug("Found cert address: %s" % address)
+ continue
+ if (stripped_line.startswith("LE_LOCAL_KEY_IRK")):
+ irk_fields = stripped_line.split(' ')
+ irk = irk_fields[2]
+ logging.debug("Found cert IRK: %s" % irk)
+ continue
+
+ return address, irk
+
+ def setup_class(self):
+ super().setup_class()
+
+ def setup_test(self):
+ assertThat(super().setup_test()).isTrue()
+
+ def teardown_test(self):
+ self.dut_scanner_.stop_scanning()
+ self.cert_advertiser_.stop_advertising()
+ self.dut_security_.remove_all_bonded_devices()
+ self.cert_security_.remove_all_bonded_devices()
+ super().teardown_test()
+
+ # Scans for the cert device by name. We expect to get back a RPA.
+ def __scan_for_cert_by_name(self):
+ cert_public_address, irk = self.__get_cert_public_address_and_irk_from_bt_config()
+ self.cert_advertiser_.advertise_public_extended_pdu()
+ advertising_name = self.cert_advertiser_.get_local_advertising_name()
+
+ # Scan with name and verify we get back a scan result with the RPA
+ scan_result_addr = self.dut_scanner_.scan_for_name(advertising_name)
+ assertThat(scan_result_addr).isNotNone()
+ assertThat(scan_result_addr).isNotEqualTo(cert_public_address)
+
+ return scan_result_addr
+
+ def __scan_for_irk(self):
+ cert_public_address, irk = self.__get_cert_public_address_and_irk_from_bt_config()
+ rpa_address = self.cert_advertiser_.advertise_public_extended_pdu()
+ id_addr = self.dut_scanner_.scan_for_address_with_irk(cert_public_address, ble_address_types["public"], irk)
+ self.dut_scanner_.stop_scanning()
+ return id_addr
+
+ def __create_le_bond_oob_single_sided(self,
+ wait_for_oob_data=True,
+ wait_for_device_bonded=True,
+ addr=None,
+ addr_type=ble_address_types["random"]):
+ oob_data = self.cert_security_.generate_oob_data(Security.TRANSPORT_LE, wait_for_oob_data)
+ if wait_for_oob_data:
+ assertThat(oob_data[0]).isEqualTo(0)
+ assertThat(oob_data[1]).isNotNone()
+ self.dut_security_.create_bond_out_of_band(oob_data[1], addr, addr_type, wait_for_device_bonded)
+ return oob_data[1].to_sl4a_address()
+
+ def __create_le_bond_oob_double_sided(self,
+ wait_for_oob_data=True,
+ wait_for_device_bonded=True,
+ addr=None,
+ addr_type=ble_address_types["random"]):
+ # Genearte OOB data on DUT, but we don't use it
+ self.dut_security_.generate_oob_data(Security.TRANSPORT_LE, wait_for_oob_data)
+ self.__create_le_bond_oob_single_sided(wait_for_oob_data, wait_for_device_bonded, addr, addr_type)
+
+ def __test_le_l2cap_insecure_coc(self):
+ logging.info("Testing insecure L2CAP CoC")
+ cert_rpa = self.__scan_for_cert_by_name()
+
+ # Listen on an insecure l2cap coc on the cert
+ psm = self.cert_l2cap_.listen_using_l2cap_le_coc(False)
+ self.dut_l2cap_.create_l2cap_le_coc(cert_rpa, psm, False)
+
+ # Cleanup
+ self.dut_scanner_.stop_scanning()
+ self.dut_l2cap_.close_l2cap_le_coc_client()
+ self.cert_advertiser_.stop_advertising()
+ self.cert_l2cap_.close_l2cap_le_coc_server()
+
+ def __test_le_l2cap_secure_coc(self):
+ logging.info("Testing secure L2CAP CoC")
+ cert_rpa = self.__create_le_bond_oob_single_sided()
+
+ # Listen on an secure l2cap coc on the cert
+ psm = self.cert_l2cap_.listen_using_l2cap_le_coc(True)
+ self.dut_l2cap_.create_l2cap_le_coc(cert_rpa, psm, True)
+
+ # Cleanup
+ self.dut_scanner_.stop_scanning()
+ self.dut_l2cap_.close_l2cap_le_coc_client()
+ self.cert_advertiser_.stop_advertising()
+ self.cert_l2cap_.close_l2cap_le_coc_server()
+ self.dut_security_.remove_all_bonded_devices()
+ self.cert_security_.remove_all_bonded_devices()
+
+ def __test_le_l2cap_secure_coc_after_irk_scan(self):
+ logging.info("Testing secure L2CAP CoC after IRK scan")
+ cert_config_addr, irk = self.__get_cert_public_address_and_irk_from_bt_config()
+ cert_id_addr = self.__scan_for_irk()
+
+ assertThat(cert_id_addr).isEqualTo(cert_config_addr)
+ self.__create_le_bond_oob_single_sided(True, True, cert_id_addr, ble_address_types["public"])
+ self.cert_advertiser_.stop_advertising()
+ self.__test_le_l2cap_secure_coc()
+
+ def __test_secure_le_l2cap_coc_stress(self):
+ for i in range(0, 10):
+ self.__test_le_l2cap_secure_coc()
+
+ def __test_insecure_le_l2cap_coc_stress(self):
+ for i in range(0, 10):
+ self.__test_le_l2cap_insecure_coc()
+
+ def __test_le_l2cap_coc_stress(self):
+ #for i in range (0, 10):
+ self.__test_le_l2cap_insecure_coc()
+ self.__test_le_l2cap_secure_coc()
+
+ def __test_secure_le_l2cap_coc_after_irk_scan_stress(self):
+ for i in range(0, 10):
+ self.__test_le_l2cap_secure_coc_after_irk_scan()
diff --git a/system/blueberry/tests/sl4a_sl4a/lib/l2cap.py b/system/blueberry/tests/sl4a_sl4a/lib/l2cap.py
index 3957146..9604ab7 100644
--- a/system/blueberry/tests/sl4a_sl4a/lib/l2cap.py
+++ b/system/blueberry/tests/sl4a_sl4a/lib/l2cap.py
@@ -15,24 +15,56 @@
# limitations under the License.
import logging
+import queue
from blueberry.tests.gd.cert.truth import assertThat
class L2cap:
- __l2cap_connection_timeout = 30 #seconds
+ __l2cap_connection_timeout = 10 #seconds
__device = None
+ __active_client_coc = False
+ __active_server_coc = False
def __init__(self, device):
self.__device = device
+ def __wait_for_event(self, expected_event_name):
+ try:
+ event_info = self.__device.ed.pop_event(expected_event_name, self.__l2cap_connection_timeout)
+ logging.info(event_info)
+ except queue.Empty as error:
+ logging.error("Failed to find event: %s", expected_event_name)
+ return False
+ return True
+
def create_l2cap_le_coc(self, address, psm, secure):
logging.info("creating l2cap channel with secure=%r and psm %s", secure, psm)
self.__device.sl4a.bluetoothSocketConnBeginConnectThreadPsm(address, True, psm, secure)
+ assertThat(self.__wait_for_event("BluetoothSocketConnectSuccess")).isTrue()
+ self.__active_client_coc = True
# Starts listening on the l2cap server socket, returns the psm
- def listen_using_l2cap_coc(self, secure):
- logging.info("Listening for l2cap channel with secure=%r and psm %s", secure, psm)
- self.__device.sl4a.bluetoothSocketConnBeginAcceptThreadPsm(__l2cap_connection_timeout, True, secure)
+ def listen_using_l2cap_le_coc(self, secure):
+ logging.info("Listening for l2cap channel with secure=%r", secure)
+ self.__device.sl4a.bluetoothSocketConnBeginAcceptThreadPsm(self.__l2cap_connection_timeout, True, secure)
+ self.__active_server_coc = True
return self.__device.sl4a.bluetoothSocketConnGetPsm()
+
+ def close_l2cap_le_coc_client(self):
+ if self.__active_client_coc:
+ logging.info("Closing LE L2CAP CoC Client")
+ self.__device.sl4a.bluetoothSocketConnKillConnThread()
+ self.__active_client_coc = False
+
+ def close_l2cap_le_coc_server(self):
+ if self.__active_server_coc:
+ logging.info("Closing LE L2CAP CoC Server")
+ self.__device.sl4a.bluetoothSocketConnEndAcceptThread()
+ self.__active_server_coc = False
+
+ def close(self):
+ self.close_l2cap_le_coc_client()
+ self.close_l2cap_le_coc_server()
+ self.__device == None
diff --git a/system/blueberry/tests/sl4a_sl4a/lib/oob_data.py b/system/blueberry/tests/sl4a_sl4a/lib/oob_data.py
index 69f753a..e54c467 100644
--- a/system/blueberry/tests/sl4a_sl4a/lib/oob_data.py
+++ b/system/blueberry/tests/sl4a_sl4a/lib/oob_data.py
@@ -49,4 +49,4 @@
def to_sl4a_address_type(self):
if len(self.address) != self.ADDRESS_WITH_TYPE_LENGTH:
return -1
- return self.address.upper()[-2]
+ return self.address.upper()[-1]
diff --git a/system/blueberry/tests/sl4a_sl4a/lib/security.py b/system/blueberry/tests/sl4a_sl4a/lib/security.py
index fcfb4ba..78cc758 100644
--- a/system/blueberry/tests/sl4a_sl4a/lib/security.py
+++ b/system/blueberry/tests/sl4a_sl4a/lib/security.py
@@ -37,7 +37,7 @@
TRANSPORT_LE = "2"
__default_timeout = 10 # seconds
- __default_bonding_timeout = 30 # seconds
+ __default_bonding_timeout = 60 # seconds
__device = None
def __init__(self, device):
@@ -70,6 +70,7 @@
logging.info("Generating local oob data failed with error code %d", errorcode)
return errorcode, None
+ logging.info("OOB ADDR with Type: %s", generate_success_event["data"]["address_with_type"])
return 0, OobData(generate_success_event["data"]["address_with_type"],
generate_success_event["data"]["confirmation"], generate_success_event["data"]["randomizer"])
@@ -84,13 +85,27 @@
logging.info("Bonded: %s", bond_state["data"]["bonded_state"])
assertThat(bond_state["data"]["bonded_state"]).isEqualTo(True)
- def create_bond_out_of_band(self, oob_data, wait_for_device_bonded=True):
+ def create_bond_out_of_band(self,
+ oob_data,
+ bt_device_object_address=None,
+ bt_device_object_address_type=-1,
+ wait_for_device_bonded=True):
assertThat(oob_data).isNotNone()
- address = oob_data.to_sl4a_address()
- address_type = oob_data.to_sl4a_address_type()
- logging.info("Bonding OOB with %s and address type=%s", address, address_type)
- self.__device.sl4a.bluetoothCreateLeBondOutOfBand(address, oob_data.confirmation, oob_data.randomizer,
- address_type)
+ oob_data_address = oob_data.to_sl4a_address()
+ oob_data_address_type = oob_data.to_sl4a_address_type()
+
+ # If a BT Device object address isn't specified, default to the oob data
+ # address and type
+ if bt_device_object_address is None:
+ bt_device_object_address = oob_data_address
+ bt_device_object_address_type = oob_data_address_type
+
+ logging.info("Bonding OOB with device addr=%s, device addr type=%s, oob addr=%s, oob addr type=%s",
+ bt_device_object_address, bt_device_object_address_type, oob_data_address, oob_data_address_type)
+ bond_start = self.__device.sl4a.bluetoothCreateLeBondOutOfBand(
+ oob_data_address, oob_data_address_type, oob_data.confirmation, oob_data.randomizer,
+ bt_device_object_address, bt_device_object_address_type)
+ assertThat(bond_start).isTrue()
if wait_for_device_bonded:
self.ensure_device_bonded()
diff --git a/system/blueberry/tests/sl4a_sl4a/lib/sl4a_sl4a_base_test.py b/system/blueberry/tests/sl4a_sl4a/lib/sl4a_sl4a_base_test.py
index fe37b00..0184288 100644
--- a/system/blueberry/tests/sl4a_sl4a/lib/sl4a_sl4a_base_test.py
+++ b/system/blueberry/tests/sl4a_sl4a/lib/sl4a_sl4a_base_test.py
@@ -26,6 +26,7 @@
from blueberry.tests.gd_sl4a.lib.ble_lib import enable_bluetooth
from blueberry.tests.sl4a_sl4a.lib.le_advertiser import LeAdvertiser
from blueberry.tests.sl4a_sl4a.lib.le_scanner import LeScanner
+from blueberry.tests.sl4a_sl4a.lib.l2cap import L2cap
from blueberry.tests.sl4a_sl4a.lib.security import Security
from blueberry.utils.mobly_sl4a_utils import setup_sl4a
from blueberry.utils.mobly_sl4a_utils import teardown_sl4a
@@ -43,11 +44,13 @@
dut_advertiser_ = None
dut_scanner_ = None
dut_security_ = None
+ dut_l2cap_ = None
# CERT
cert_advertiser_ = None
cert_scanner_ = None
cert_security_ = None
+ cert_l2cap_ = None
SUBPROCESS_WAIT_TIMEOUT_SECONDS = 10
@@ -111,9 +114,11 @@
self.dut_advertiser_ = LeAdvertiser(self.dut)
self.dut_scanner_ = LeScanner(self.dut)
self.dut_security_ = Security(self.dut)
+ self.dut_l2cap_ = L2cap(self.dut)
self.cert_advertiser_ = LeAdvertiser(self.cert)
self.cert_scanner_ = LeScanner(self.cert)
self.cert_security_ = Security(self.cert)
+ self.cert_l2cap_ = L2cap(self.cert)
return True
def teardown_test(self):
@@ -121,13 +126,16 @@
safeClose(self.dut_advertiser_)
safeClose(self.dut_scanner_)
safeClose(self.dut_security_)
+ safeClose(self.dut_l2cap_)
safeClose(self.cert_advertiser_)
safeClose(self.cert_scanner_)
safeClose(self.cert_security_)
+ safeClose(self.cert_l2cap_)
self.dut_advertiser_ = None
self.dut_scanner_ = None
self.dut_security_ = None
self.cert_advertiser_ = None
+ self.cert_l2cap_ = None
self.cert_scanner_ = None
self.cert_security_ = None
diff --git a/system/blueberry/tests/sl4a_sl4a/sl4a_sl4a_test_runner.py b/system/blueberry/tests/sl4a_sl4a/sl4a_sl4a_test_runner.py
index 7b2b933..3081aa4 100644
--- a/system/blueberry/tests/sl4a_sl4a/sl4a_sl4a_test_runner.py
+++ b/system/blueberry/tests/sl4a_sl4a/sl4a_sl4a_test_runner.py
@@ -18,6 +18,7 @@
from blueberry.tests.sl4a_sl4a.gatt.gatt_connect_test import GattConnectTest
from blueberry.tests.sl4a_sl4a.gatt.gatt_connect_with_irk_test import GattConnectWithIrkTest
from blueberry.tests.sl4a_sl4a.gatt.gatt_notify_test import GattNotifyTest
+from blueberry.tests.sl4a_sl4a.l2cap.le_l2cap_coc_test import LeL2capCoCTest
from blueberry.tests.sl4a_sl4a.scanning.le_scanning import LeScanningTest
from blueberry.tests.sl4a_sl4a.security.irk_rotation_test import IrkRotationTest
from blueberry.tests.sl4a_sl4a.security.oob_pairing_test import OobPairingTest
@@ -31,6 +32,7 @@
GattNotifyTest,
IrkRotationTest,
LeAdvertisingTest,
+ LeL2capCoCTest,
LeScanningTest,
OobPairingTest,
]
diff --git a/system/bta/Android.bp b/system/bta/Android.bp
index 26ad3f5..07707ab 100644
--- a/system/bta/Android.bp
+++ b/system/bta/Android.bp
@@ -126,6 +126,7 @@
"hh/bta_hh_le.cc",
"hh/bta_hh_main.cc",
"hh/bta_hh_utils.cc",
+ "hfp/bta_hfp_api.cc",
"hd/bta_hd_act.cc",
"hd/bta_hd_api.cc",
"hd/bta_hd_main.cc",
@@ -188,6 +189,7 @@
"libbt-audio-hal-interface",
"libbluetooth-types",
"libbt-protos-lite",
+ "libcom.android.sysprop.bluetooth",
"libosi",
"libbt-common",
],
@@ -337,6 +339,7 @@
],
static_libs: [
"libbluetooth-types",
+ "libcom.android.sysprop.bluetooth",
"libosi",
],
cflags: ["-DBUILDCFG"],
diff --git a/system/bta/BUILD.gn b/system/bta/BUILD.gn
index db8db54..22cf22e 100644
--- a/system/bta/BUILD.gn
+++ b/system/bta/BUILD.gn
@@ -74,6 +74,7 @@
"hh/bta_hh_le.cc",
"hh/bta_hh_main.cc",
"hh/bta_hh_utils.cc",
+ "hfp/bta_hfp_api.cc",
"hd/bta_hd_act.cc",
"hd/bta_hd_api.cc",
"hd/bta_hd_main.cc",
diff --git a/system/bta/ag/bta_ag_sdp.cc b/system/bta/ag/bta_ag_sdp.cc
index 46e5825..27503b1 100644
--- a/system/bta/ag/bta_ag_sdp.cc
+++ b/system/bta/ag/bta_ag_sdp.cc
@@ -161,7 +161,7 @@
/* add profile descriptor list */
if (service_uuid == UUID_SERVCLASS_AG_HANDSFREE) {
profile_uuid = UUID_SERVCLASS_HF_HANDSFREE;
- version = BTA_HFP_VERSION;
+ version = get_default_hfp_version();
} else {
profile_uuid = UUID_SERVCLASS_HEADSET;
version = HSP_VERSION_1_2;
diff --git a/system/bta/hf_client/bta_hf_client_sdp.cc b/system/bta/hf_client/bta_hf_client_sdp.cc
index 4625b6d..cfb88d3 100755
--- a/system/bta/hf_client/bta_hf_client_sdp.cc
+++ b/system/bta/hf_client/bta_hf_client_sdp.cc
@@ -46,6 +46,22 @@
/* Number of elements in service class id list. */
#define BTA_HF_CLIENT_NUM_SVC_ELEMS 2
+#ifdef OS_ANDROID
+#include <hfp.sysprop.h>
+#endif
+
+#define DEFAULT_BTA_HFP_VERSION HFP_VERSION_1_7
+int get_default_hfp_version() {
+#ifdef OS_ANDROID
+ static const int version =
+ android::sysprop::bluetooth::Hfp::version().value_or(
+ DEFAULT_BTA_HFP_VERSION);
+ return version;
+#else
+ return DEFAULT_BTA_HFP_VERSION;
+#endif
+}
+
/*******************************************************************************
*
* Function bta_hf_client_sdp_cback
@@ -124,7 +140,7 @@
/* add profile descriptor list */
profile_uuid = UUID_SERVCLASS_HF_HANDSFREE;
- version = BTA_HFP_VERSION;
+ version = get_default_hfp_version();
result &= SDP_AddProfileDescriptorList(sdp_handle, profile_uuid, version);
diff --git a/system/bta/hfp/bta_hfp_api.cc b/system/bta/hfp/bta_hfp_api.cc
new file mode 100644
index 0000000..63ece44
--- /dev/null
+++ b/system/bta/hfp/bta_hfp_api.cc
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2023 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 "bta_hfp_api.h"
+
+#ifdef OS_ANDROID
+#include <hfp.sysprop.h>
+#endif
+
+#define DEFAULT_BTA_HFP_VERSION HFP_VERSION_1_7
+
+int get_default_hfp_version() {
+#ifdef OS_ANDROID
+ static const int version =
+ android::sysprop::bluetooth::Hfp::version().value_or(
+ DEFAULT_BTA_HFP_VERSION);
+ return version;
+#else
+ return DEFAULT_BTA_HFP_VERSION;
+#endif
+}
diff --git a/system/bta/include/bta_hfp_api.h b/system/bta/include/bta_hfp_api.h
index a3dd3a9..5c3b59b 100644
--- a/system/bta/include/bta_hfp_api.h
+++ b/system/bta/include/bta_hfp_api.h
@@ -24,6 +24,7 @@
#define HFP_VERSION_1_5 0x0105
#define HFP_VERSION_1_6 0x0106
#define HFP_VERSION_1_7 0x0107
+#define HFP_VERSION_1_8 0x0108
#define HSP_VERSION_1_0 0x0100
#define HSP_VERSION_1_2 0x0102
@@ -31,9 +32,6 @@
#define HFP_VERSION_CONFIG_KEY "HfpVersion"
#define HFP_SDP_FEATURES_CONFIG_KEY "HfpSdpFeatures"
-/* Default HFP Version */
-#ifndef BTA_HFP_VERSION
-#define BTA_HFP_VERSION HFP_VERSION_1_7
-#endif
+int get_default_hfp_version();
#endif /* BTA_HFP_API_H */
\ No newline at end of file
diff --git a/system/bta/test/bta_hf_client_add_record_test.cc b/system/bta/test/bta_hf_client_add_record_test.cc
index 5e50cc0..d7a55aa 100644
--- a/system/bta/test/bta_hf_client_add_record_test.cc
+++ b/system/bta/test/bta_hf_client_add_record_test.cc
@@ -68,6 +68,6 @@
uint8_t scn = 0;
bta_hf_client_add_record("Handsfree", scn, features, sdp_handle);
- ASSERT_EQ(gVersion, BTA_HFP_VERSION);
+ ASSERT_EQ(gVersion, get_default_hfp_version());
}
diff --git a/system/btif/Android.bp b/system/btif/Android.bp
index c13945c..ad0de3b 100644
--- a/system/btif/Android.bp
+++ b/system/btif/Android.bp
@@ -385,6 +385,7 @@
],
static_libs: [
"libbluetooth-types",
+ "libcom.android.sysprop.bluetooth",
"libosi",
],
cflags: ["-DBUILDCFG"],
diff --git a/system/btif/src/btif_hf_client.cc b/system/btif/src/btif_hf_client.cc
index 6ea3178..68f40d7 100644
--- a/system/btif/src/btif_hf_client.cc
+++ b/system/btif/src/btif_hf_client.cc
@@ -1086,7 +1086,7 @@
BTIF_TRACE_EVENT("%s: enable: %d", __func__, b_enable);
tBTA_HF_CLIENT_FEAT features = BTIF_HF_CLIENT_FEATURES;
- uint16_t hfp_version = BTA_HFP_VERSION;
+ uint16_t hfp_version = get_default_hfp_version();
if (hfp_version >= HFP_VERSION_1_7) {
features |= BTA_HF_CLIENT_FEAT_ESCO_S4;
}
diff --git a/system/btif/test/btif_hf_client_service_test.cc b/system/btif/test/btif_hf_client_service_test.cc
index db48af1..c776e7f 100644
--- a/system/btif/test/btif_hf_client_service_test.cc
+++ b/system/btif/test/btif_hf_client_service_test.cc
@@ -2,11 +2,26 @@
#include <gtest/gtest.h>
#include "bta_hfp_api.h"
+#ifdef OS_ANDROID
+#include <hfp.sysprop.h>
+#endif
+
#undef LOG_TAG
#include "btif/src/btif_hf_client.cc"
static tBTA_HF_CLIENT_FEAT gFeatures;
+#define DEFAULT_BTA_HFP_VERSION HFP_VERSION_1_7
+int get_default_hfp_version() {
+#ifdef OS_ANDROID
+ static const int version =
+ android::sysprop::bluetooth::Hfp::version().value_or(
+ DEFAULT_BTA_HFP_VERSION);
+ return version;
+#else
+ return DEFAULT_BTA_HFP_VERSION;
+#endif
+}
uint8_t btif_trace_level = BT_TRACE_LEVEL_WARNING;
void LogMsg(uint32_t trace_set_mask, const char* fmt_str, ...) {}
@@ -41,5 +56,5 @@
btif_hf_client_execute_service(enable);
ASSERT_EQ((gFeatures & BTA_HF_CLIENT_FEAT_ESCO_S4) > 0,
- BTA_HFP_VERSION >= HFP_VERSION_1_7);
+ get_default_hfp_version() >= HFP_VERSION_1_7);
}
diff --git a/system/test/mock/mock_bta_hfp_api.cc b/system/test/mock/mock_bta_hfp_api.cc
new file mode 100644
index 0000000..b9dc9dd
--- /dev/null
+++ b/system/test/mock/mock_bta_hfp_api.cc
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2023 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 "bta/include/bta_hfp_api.h"
+
+#define DEFAULT_BTA_HFP_VERSION HFP_VERSION_1_7
+
+int get_default_hfp_version() { return DEFAULT_BTA_HFP_VERSION; }