summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Seymour <rseymour@google.com>2022-04-02 03:52:13 +0000
committerRob Seymour <rseymour@google.com>2022-04-02 04:01:22 +0000
commit4c7dc59bef24cc991251f9a7924ceada90c6bd63 (patch)
treea90550aa3ce1bc5e002ab6444c96954deca81af0
parent6fa2bea006b362a285f744f65f15b5902e55797a (diff)
parentdd4d23c4e1de011f8cd4eb132422172d5e283a73 (diff)
Merge TP1A.220328.001
Change-Id: I5f07094ba2fb3991da03673f97d2957b1f68018b
-rw-r--r--android/app/Android.bp1
-rw-r--r--android/app/AndroidManifest.xml100
-rw-r--r--android/app/jni/com_android_bluetooth_le_audio.cpp70
-rw-r--r--android/app/res/values-fa/strings.xml2
-rw-r--r--android/app/res/values-hy/strings.xml2
-rw-r--r--android/app/res/values/config.xml2
-rw-r--r--android/app/src/com/android/bluetooth/Utils.java20
-rw-r--r--android/app/src/com/android/bluetooth/avrcp/AvrcpVolumeManager.java4
-rw-r--r--android/app/src/com/android/bluetooth/btservice/AdapterProperties.java3
-rw-r--r--android/app/src/com/android/bluetooth/btservice/AdapterService.java48
-rw-r--r--android/app/src/com/android/bluetooth/btservice/BondStateMachine.java2
-rw-r--r--android/app/src/com/android/bluetooth/btservice/Config.java6
-rw-r--r--android/app/src/com/android/bluetooth/btservice/MetricsLogger.java2
-rw-r--r--android/app/src/com/android/bluetooth/btservice/storage/CustomizedMetadataEntity.java8
-rw-r--r--android/app/src/com/android/bluetooth/btservice/storage/Metadata.java12
-rw-r--r--android/app/src/com/android/bluetooth/btservice/storage/MetadataDatabase.java20
-rw-r--r--android/app/src/com/android/bluetooth/gatt/ContextMap.java3
-rw-r--r--android/app/src/com/android/bluetooth/gatt/GattService.java32
-rw-r--r--android/app/src/com/android/bluetooth/le_audio/LeAudioBroadcasterNativeInterface.java81
-rw-r--r--android/app/src/com/android/bluetooth/le_audio/LeAudioService.java213
-rw-r--r--android/app/src/com/android/bluetooth/le_audio/LeAudioStackEvent.java38
-rw-r--r--android/app/src/com/android/bluetooth/mcp/MediaControlProfile.java2
-rw-r--r--android/app/src/com/android/bluetooth/opp/Constants.java2
-rw-r--r--[-rwxr-xr-x]android/app/src/com/android/bluetooth/pbap/BluetoothPbapObexServer.java134
-rw-r--r--android/app/src/com/android/bluetooth/pbap/BluetoothPbapService.java4
-rw-r--r--android/app/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManager.java540
-rw-r--r--[-rwxr-xr-x]android/app/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java6
-rw-r--r--android/app/tests/unit/AndroidManifest.xml6
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/btservice/storage/DatabaseManagerTest.java32
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/btservice/storage/schemas/com.android.bluetooth.btservice.storage.MetadataDatabase/113.json334
-rw-r--r--android/blueberry/server/Android.bp9
-rw-r--r--android/blueberry/server/configs/PtsBotTest.xml19
-rw-r--r--android/blueberry/server/configs/pts_bot_tests_config.json179
-rw-r--r--android/blueberry/server/src/com/android/blueberry/Host.kt2
-rw-r--r--apex/Android.bp9
-rw-r--r--apex/linker.config.json5
-rw-r--r--framework/api/system-current.txt2
-rw-r--r--framework/java/android/bluetooth/BluetoothAdapter.java18
-rw-r--r--framework/java/android/bluetooth/BluetoothCodecConfig.java44
-rw-r--r--framework/java/android/bluetooth/BluetoothDevice.java21
-rw-r--r--framework/java/android/bluetooth/BluetoothHapClient.java12
-rw-r--r--framework/java/android/bluetooth/BluetoothHeadset.java72
-rw-r--r--framework/java/android/bluetooth/BluetoothLeAudio.java3
-rw-r--r--framework/java/android/bluetooth/BluetoothLeBroadcast.java12
-rw-r--r--framework/java/android/bluetooth/BluetoothVolumeControl.java9
-rw-r--r--service/java/com/android/server/bluetooth/BluetoothManagerService.java26
-rw-r--r--system/audio_hal_interface/aidl/le_audio_software_aidl.cc7
-rw-r--r--system/blueberry/tests/gd/cert/gd_device.py7
-rw-r--r--system/bta/dm/bta_dm_act.cc3
-rw-r--r--system/bta/dm/bta_dm_pm.cc8
-rw-r--r--system/bta/has/has_client.cc15
-rw-r--r--system/bta/has/has_client_test.cc94
-rw-r--r--system/bta/has/has_ctp.cc11
-rw-r--r--system/bta/has/has_ctp.h14
-rw-r--r--system/bta/has/has_types.h10
-rw-r--r--system/bta/include/bta_le_audio_broadcaster_api.h15
-rw-r--r--system/bta/le_audio/audio_set_configurations.fbs14
-rw-r--r--system/bta/le_audio/audio_set_configurations.json379
-rw-r--r--system/bta/le_audio/audio_set_scenarios.json102
-rw-r--r--system/bta/le_audio/broadcaster/broadcaster.cc287
-rw-r--r--system/bta/le_audio/broadcaster/broadcaster_test.cc124
-rw-r--r--system/bta/le_audio/broadcaster/broadcaster_types.cc9
-rw-r--r--system/bta/le_audio/broadcaster/broadcaster_types.h5
-rw-r--r--system/bta/le_audio/broadcaster/mock_state_machine.cc20
-rw-r--r--system/bta/le_audio/broadcaster/mock_state_machine.h21
-rw-r--r--system/bta/le_audio/broadcaster/state_machine.cc254
-rw-r--r--system/bta/le_audio/broadcaster/state_machine.h38
-rw-r--r--system/bta/le_audio/broadcaster/state_machine_test.cc356
-rw-r--r--system/bta/le_audio/client.cc56
-rw-r--r--system/bta/le_audio/devices.cc3
-rw-r--r--system/bta/le_audio/le_audio_set_configuration_provider_json.cc75
-rw-r--r--system/bta/le_audio/le_audio_types.h9
-rw-r--r--system/bta/le_audio/state_machine.cc27
-rw-r--r--system/btif/src/btif_dm.cc16
-rw-r--r--system/btif/src/btif_le_audio_broadcaster.cc63
-rw-r--r--system/embdrv/lc3/fuzzer/liblc3_fuzzer.cpp14
-rw-r--r--system/embdrv/lc3/include/lc3.h27
-rw-r--r--system/embdrv/lc3/src/bits.h4
-rw-r--r--system/embdrv/lc3/src/lc3.c81
-rw-r--r--system/embdrv/lc3/src/tns.c2
-rw-r--r--system/gd/common/strings.h7
-rw-r--r--system/gd/common/strings_test.cc11
-rw-r--r--system/gd/hci/acl_manager/le_impl.h123
-rw-r--r--system/gd/hci/le_address_manager.cc15
-rw-r--r--system/gd/hci/le_advertising_manager.cc85
-rw-r--r--system/gd/hci/le_advertising_manager.h12
-rw-r--r--system/gd/hci/le_scanning_callback.h1
-rw-r--r--system/gd/hci/le_scanning_manager.cc40
-rw-r--r--system/gd/os/fuzz/fake_timerfd.cc2
-rw-r--r--system/gd/os/linux_generic/alarm.cc6
-rw-r--r--system/gd/packet/parser/fields/array_field.cc5
-rw-r--r--system/gd/packet/parser/fields/array_field.h2
-rw-r--r--system/gd/packet/parser/fields/body_field.cc3
-rw-r--r--system/gd/packet/parser/fields/body_field.h2
-rw-r--r--system/gd/packet/parser/fields/checksum_field.cc3
-rw-r--r--system/gd/packet/parser/fields/checksum_field.h2
-rw-r--r--system/gd/packet/parser/fields/checksum_start_field.cc3
-rw-r--r--system/gd/packet/parser/fields/checksum_start_field.h2
-rw-r--r--system/gd/packet/parser/fields/custom_field.cc3
-rw-r--r--system/gd/packet/parser/fields/custom_field.h2
-rw-r--r--system/gd/packet/parser/fields/custom_field_fixed_size.cc5
-rw-r--r--system/gd/packet/parser/fields/custom_field_fixed_size.h2
-rw-r--r--system/gd/packet/parser/fields/fixed_scalar_field.cc5
-rw-r--r--system/gd/packet/parser/fields/fixed_scalar_field.h2
-rw-r--r--system/gd/packet/parser/fields/group_field.cc3
-rw-r--r--system/gd/packet/parser/fields/group_field.h2
-rw-r--r--system/gd/packet/parser/fields/packet_field.cc4
-rw-r--r--system/gd/packet/parser/fields/packet_field.h2
-rw-r--r--system/gd/packet/parser/fields/padding_field.cc3
-rw-r--r--system/gd/packet/parser/fields/padding_field.h2
-rw-r--r--system/gd/packet/parser/fields/payload_field.cc24
-rw-r--r--system/gd/packet/parser/fields/payload_field.h4
-rw-r--r--system/gd/packet/parser/fields/reserved_field.cc3
-rw-r--r--system/gd/packet/parser/fields/reserved_field.h2
-rw-r--r--system/gd/packet/parser/fields/scalar_field.cc10
-rw-r--r--system/gd/packet/parser/fields/scalar_field.h2
-rw-r--r--system/gd/packet/parser/fields/struct_field.cc4
-rw-r--r--system/gd/packet/parser/fields/struct_field.h2
-rw-r--r--system/gd/packet/parser/fields/variable_length_struct_field.cc3
-rw-r--r--system/gd/packet/parser/fields/variable_length_struct_field.h2
-rw-r--r--system/gd/packet/parser/fields/vector_field.cc80
-rw-r--r--system/gd/packet/parser/fields/vector_field.h4
-rw-r--r--system/gd/packet/parser/gen_rust.cc7
-rw-r--r--system/gd/packet/parser/packet_def.cc2
-rw-r--r--system/gd/packet/parser/parent_def.cc2
-rw-r--r--system/gd/packet/parser/struct_def.cc2
-rw-r--r--system/gd/packet/parser/test/rust_test_packets.pdl42
-rw-r--r--system/gd/rust/linux/client/src/dbus_iface.rs2
-rw-r--r--system/gd/rust/linux/mgmt/src/bin/btmanagerd/bluetooth_manager.rs8
-rw-r--r--system/gd/rust/linux/mgmt/src/bin/btmanagerd/bluetooth_manager_dbus.rs26
-rw-r--r--system/gd/rust/linux/mgmt/src/bin/btmanagerd/state_machine.rs151
-rw-r--r--system/gd/rust/linux/service/src/iface_bluetooth.rs28
-rw-r--r--system/gd/rust/linux/service/src/iface_bluetooth_gatt.rs4
-rw-r--r--system/gd/rust/linux/stack/src/bluetooth_gatt.rs2
-rw-r--r--system/gd/rust/linux/stack/src/bluetooth_media.rs208
-rw-r--r--system/gd/rust/packets/test_lib.rs94
-rw-r--r--system/gd/rust/topshim/src/profiles/a2dp.rs2
-rw-r--r--system/include/hardware/bt_le_audio.h28
-rw-r--r--system/main/shim/acl.cc2
-rw-r--r--system/main/shim/acl_api.cc4
-rw-r--r--system/main/shim/acl_api.h3
-rw-r--r--system/main/shim/acl_legacy_interface.h2
-rw-r--r--system/main/shim/btm.cc16
-rw-r--r--system/main/shim/btm_api.cc11
-rw-r--r--system/main/shim/btm_api.h15
-rw-r--r--system/main/shim/l2c_api.cc12
-rw-r--r--system/main/shim/l2c_api.h7
-rw-r--r--system/main/shim/le_advertising_manager.cc44
-rw-r--r--system/main/shim/le_scanning_manager.cc10
-rw-r--r--system/main/test/main_shim_test.cc2
-rw-r--r--system/osi/src/config.cc6
-rw-r--r--system/stack/Android.bp1
-rw-r--r--system/stack/a2dp/a2dp_vendor.cc22
-rw-r--r--system/stack/a2dp/a2dp_vendor_aptx_encoder.cc19
-rw-r--r--system/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc18
-rw-r--r--system/stack/a2dp/a2dp_vendor_ldac_abr.cc20
-rw-r--r--system/stack/a2dp/a2dp_vendor_ldac_encoder.cc18
-rw-r--r--system/stack/acl/btm_ble_connection_establishment.cc2
-rw-r--r--system/stack/btm/btm_ble.cc18
-rw-r--r--system/stack/btm/btm_ble_addr.cc8
-rw-r--r--system/stack/btm/btm_ble_bgconn.cc4
-rw-r--r--system/stack/btm/btm_ble_gap.cc18
-rw-r--r--system/stack/btm/btm_ble_int.h5
-rw-r--r--system/stack/btm/btm_ble_privacy.cc4
-rw-r--r--system/stack/btm/btm_dev.cc4
-rw-r--r--system/stack/btm/security_device_record.h9
-rw-r--r--system/stack/gatt/gatt_main.cc2
-rw-r--r--system/stack/include/a2dp_vendor.h10
-rw-r--r--system/stack/include/ble_hci_link_interface.h3
-rw-r--r--system/stack/include/rfcdefs.h11
-rw-r--r--system/stack/include/stack_metrics_logging.h3
-rw-r--r--system/stack/metrics/stack_metrics_logging.cc5
-rw-r--r--system/stack/rfcomm/port_api.cc13
-rw-r--r--system/stack/rfcomm/port_rfc.cc38
-rw-r--r--system/stack/rfcomm/rfc_event.h149
-rw-r--r--system/stack/rfcomm/rfc_int.h45
-rw-r--r--system/stack/rfcomm/rfc_l2cap_if.cc10
-rw-r--r--system/stack/rfcomm/rfc_state.h75
-rw-r--r--system/stack/rfcomm/rfc_utils.cc1
-rw-r--r--system/test/mock/mock_main_shim_acl_api.cc2
-rw-r--r--system/test/mock/mock_main_shim_btm_api.cc4
-rw-r--r--system/test/mock/mock_main_shim_l2cap_api.cc4
-rw-r--r--system/test/mock/mock_main_shim_l2cap_api.h13
-rw-r--r--system/test/mock/mock_osi_mutex.cc65
-rw-r--r--system/test/mock/mock_osi_mutex.h72
-rw-r--r--system/test/mock/mock_stack_acl_ble.cc2
-rw-r--r--system/test/mock/mock_stack_btm_ble_addr.cc6
-rw-r--r--system/test/mock/mock_stack_btm_ble_addr.h8
-rw-r--r--system/test/mock/mock_stack_btm_ble_gap.cc14
-rw-r--r--system/test/mock/mock_stack_btm_inq.cc3
-rw-r--r--system/test/mock/mock_stack_metrics_logging.cc7
-rw-r--r--system/test/mock/mock_stack_metrics_logging.h12
-rw-r--r--system/types/Android.bp6
-rw-r--r--system/types/ble_address_with_type.h30
-rw-r--r--system/types/test/ble_address_with_type_unittest.cc113
-rw-r--r--tools/rootcanal/model/controller/link_layer_controller.cc74
196 files changed, 4821 insertions, 1731 deletions
diff --git a/android/app/Android.bp b/android/app/Android.bp
index 0a765f03a0..21b93717aa 100644
--- a/android/app/Android.bp
+++ b/android/app/Android.bp
@@ -87,6 +87,7 @@ android_app {
],
platform_apis: true,
certificate: "platform",
+ aaptflags: [ "--custom-package", "com.android.bluetooth" ],
jni_libs: ["libbluetooth_jni"],
libs: [
diff --git a/android/app/AndroidManifest.xml b/android/app/AndroidManifest.xml
index 6613470e34..50225ae84d 100644
--- a/android/app/AndroidManifest.xml
+++ b/android/app/AndroidManifest.xml
@@ -1,10 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.bluetooth"
- android:sharedUserId="android.uid.bluetooth">
-
- <original-package android:name="com.android.bluetooth"/>
+ package="com.android.bluetooth.services"
+ android:sharedUserId="android.uid.bluetooth">
<!-- Allows access to the Bluetooth Share Manager -->
<permission android:name="android.permission.ACCESS_BLUETOOTH_SHARE"
@@ -84,7 +82,7 @@
<!-- For PBAP Owner Vcard Info -->
<uses-permission android:name="android.permission.READ_PROFILE"/>
- <application android:name=".btservice.AdapterApp"
+ <application android:name="com.android.bluetooth.btservice.AdapterApp"
android:icon="@mipmap/bt_share"
android:persistent="false"
android:label="@string/app_name"
@@ -93,14 +91,14 @@
android:directBootAware="true"
android:defaultToDeviceProtectedStorage="true"
android:memtagMode="async">
- <provider android:name=".opp.BluetoothOppProvider"
+ <provider android:name="com.android.bluetooth.opp.BluetoothOppProvider"
android:authorities="com.android.bluetooth.opp"
android:exported="true"
android:process="@string/process">
<path-permission android:pathPrefix="/btopp"
android:permission="android.permission.ACCESS_BLUETOOTH_SHARE"/>
</provider>
- <provider android:name=".opp.BluetoothOppFileProvider"
+ <provider android:name="com.android.bluetooth.opp.BluetoothOppFileProvider"
android:authorities="com.android.bluetooth.opp.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
@@ -108,7 +106,7 @@
android:resource="@xml/file_paths"/>
</provider>
<service android:process="@string/process"
- android:name=".btservice.AdapterService"
+ android:name="com.android.bluetooth.btservice.AdapterService"
android:exported="true"
android:permission="android.permission.ACCESS_BLUETOOTH_SHARE">
<intent-filter>
@@ -116,19 +114,19 @@
</intent-filter>
</service>
<service android:process="@string/process"
- android:name=".opp.BluetoothOppService"
+ android:name="com.android.bluetooth.opp.BluetoothOppService"
android:permission="android.permission.ACCESS_BLUETOOTH_SHARE"
android:enabled="@bool/profile_supported_opp"/>
<receiver android:process="@string/process"
android:exported="true"
- android:name=".opp.BluetoothOppReceiver"
+ android:name="com.android.bluetooth.opp.BluetoothOppReceiver"
android:enabled="@bool/profile_supported_opp">
<intent-filter>
<action android:name="android.btopp.intent.action.OPEN_RECEIVED_FILES"/>
</intent-filter>
</receiver>
<receiver android:process="@string/process"
- android:name=".opp.BluetoothOppHandoverReceiver"
+ android:name="com.android.bluetooth.opp.BluetoothOppHandoverReceiver"
android:permission="com.android.permission.ALLOWLIST_BLUETOOTH_DEVICE"
android:exported="true">
<intent-filter>
@@ -146,7 +144,7 @@
<data android:mimeType="*/*"/>
</intent-filter>
</receiver>
- <activity android:name=".opp.BluetoothOppLauncherActivity"
+ <activity android:name="com.android.bluetooth.opp.BluetoothOppLauncherActivity"
android:process="@string/process"
android:theme="@android:style/Theme.Material.Light.Dialog"
android:label="@string/bt_share_picker_label"
@@ -188,36 +186,36 @@
<data android:mimeType="vnd.android.cursor.item/vnd.android.btopp"/>
</intent-filter>
</activity>
- <activity android:name=".opp.BluetoothOppBtEnableActivity"
+ <activity android:name="com.android.bluetooth.opp.BluetoothOppBtEnableActivity"
android:process="@string/process"
android:excludeFromRecents="true"
android:theme="@style/dialog"
android:enabled="@bool/profile_supported_opp">
</activity>
- <activity android:name=".opp.BluetoothOppBtErrorActivity"
+ <activity android:name="com.android.bluetooth.opp.BluetoothOppBtErrorActivity"
android:process="@string/process"
android:excludeFromRecents="true"
android:theme="@style/dialog">
</activity>
- <activity android:name=".opp.BluetoothOppBtEnablingActivity"
+ <activity android:name="com.android.bluetooth.opp.BluetoothOppBtEnablingActivity"
android:process="@string/process"
android:excludeFromRecents="true"
android:theme="@style/dialog"
android:enabled="@bool/profile_supported_opp">
</activity>
- <activity android:name=".opp.BluetoothOppIncomingFileConfirmActivity"
+ <activity android:name="com.android.bluetooth.opp.BluetoothOppIncomingFileConfirmActivity"
android:process="@string/process"
android:excludeFromRecents="true"
android:theme="@style/dialog"
android:enabled="@bool/profile_supported_opp">
</activity>
- <activity android:name=".opp.BluetoothOppTransferActivity"
+ <activity android:name="com.android.bluetooth.opp.BluetoothOppTransferActivity"
android:process="@string/process"
android:excludeFromRecents="true"
android:theme="@style/dialog"
android:enabled="@bool/profile_supported_opp">
</activity>
- <activity android:name=".opp.BluetoothOppTransferHistory"
+ <activity android:name="com.android.bluetooth.opp.BluetoothOppTransferHistory"
android:process="@string/process"
android:label=""
android:excludeFromRecents="true"
@@ -230,7 +228,7 @@
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
- <activity android:name=".pbap.BluetoothPbapActivity"
+ <activity android:name="com.android.bluetooth.pbap.BluetoothPbapActivity"
android:process="@string/process"
android:excludeFromRecents="true"
android:theme="@style/dialog"
@@ -238,7 +236,7 @@
</activity>
<service android:process="@string/process"
android:permission="android.permission.BLUETOOTH_PRIVILEGED"
- android:name=".pbap.BluetoothPbapService"
+ android:name="com.android.bluetooth.pbap.BluetoothPbapService"
android:enabled="@bool/profile_supported_pbap"
android:exported="true">
<intent-filter>
@@ -246,7 +244,7 @@
</intent-filter>
</service>
<service android:process="@string/process"
- android:name=".map.BluetoothMapService"
+ android:name="com.android.bluetooth.map.BluetoothMapService"
android:enabled="@bool/profile_supported_map"
android:exported="true">
<intent-filter>
@@ -255,21 +253,21 @@
<action android:name="com.android.bluetooth.map.USER_CONFIRM_TIMEOUT"/>
</intent-filter>
</service>
- <activity android:name=".map.BluetoothMapSettings"
+ <activity android:name="com.android.bluetooth.map.BluetoothMapSettings"
android:process="@string/process"
android:label="@string/bluetooth_map_settings_title"
android:excludeFromRecents="true"
android:configChanges="orientation|keyboardHidden"
android:enabled="@bool/profile_supported_map">
</activity>
- <provider android:name=".map.MmsFileProvider"
+ <provider android:name="com.android.bluetooth.map.MmsFileProvider"
android:authorities="com.android.bluetooth.map.MmsFileProvider"
android:enabled="true"
android:grantUriPermissions="true"
android:exported="false">
</provider>
<service android:process="@string/process"
- android:name=".mapclient.MapClientService"
+ android:name="com.android.bluetooth.mapclient.MapClientService"
android:enabled="@bool/profile_supported_mapmce"
android:exported="true">
<intent-filter>
@@ -277,7 +275,7 @@
</intent-filter>
</service>
<service android:process="@string/process"
- android:name=".sap.SapService"
+ android:name="com.android.bluetooth.sap.SapService"
android:enabled="@bool/profile_supported_sap"
android:exported="true">
<intent-filter>
@@ -285,7 +283,7 @@
</intent-filter>
</service>
<service android:process="@string/process"
- android:name=".gatt.GattService"
+ android:name="com.android.bluetooth.gatt.GattService"
android:enabled="@bool/profile_supported_gatt"
android:exported="true"
android:permission="android.permission.ACCESS_BLUETOOTH_SHARE">
@@ -294,7 +292,7 @@
</intent-filter>
</service>
<service android:process="@string/process"
- android:name=".hfp.HeadsetService"
+ android:name="com.android.bluetooth.hfp.HeadsetService"
android:enabled="@bool/profile_supported_hs_hfp"
android:exported="true">
<intent-filter>
@@ -302,7 +300,7 @@
</intent-filter>
</service>
<service android:process="@string/process"
- android:name=".a2dp.A2dpService"
+ android:name="com.android.bluetooth.a2dp.A2dpService"
android:enabled="@bool/profile_supported_a2dp"
android:exported="true">
<intent-filter>
@@ -310,7 +308,7 @@
</intent-filter>
</service>
<service android:process="@string/process"
- android:name=".a2dpsink.A2dpSinkService"
+ android:name="com.android.bluetooth.a2dpsink.A2dpSinkService"
android:enabled="@bool/profile_supported_a2dp_sink"
android:exported="true">
<intent-filter>
@@ -318,7 +316,7 @@
</intent-filter>
</service>
<service android:process="@string/process"
- android:name=".avrcpcontroller.BluetoothMediaBrowserService"
+ android:name="com.android.bluetooth.avrcpcontroller.BluetoothMediaBrowserService"
android:exported="true"
android:enabled="@bool/profile_supported_a2dp_sink"
android:label="@string/a2dp_sink_mbs_label">
@@ -327,7 +325,7 @@
</intent-filter>
</service>
- <activity android:name=".BluetoothPrefs"
+ <activity android:name="com.android.bluetooth.BluetoothPrefs"
android:exported="@bool/profile_supported_a2dp_sink"
android:enabled="@bool/profile_supported_a2dp_sink">
<intent-filter>
@@ -336,7 +334,7 @@
</activity>
<service android:process="@string/process"
- android:name=".avrcp.AvrcpTargetService"
+ android:name="com.android.bluetooth.avrcp.AvrcpTargetService"
android:enabled="@bool/profile_supported_avrcp_target"
android:exported="true">
<intent-filter>
@@ -344,7 +342,7 @@
</intent-filter>
</service>
<service android:process="@string/process"
- android:name=".avrcpcontroller.AvrcpControllerService"
+ android:name="com.android.bluetooth.avrcpcontroller.AvrcpControllerService"
android:enabled="@bool/profile_supported_avrcp_controller"
android:exported="true">
<intent-filter>
@@ -352,14 +350,14 @@
</intent-filter>
</service>
<provider android:process="@string/process"
- android:name=".avrcpcontroller.AvrcpCoverArtProvider"
+ android:name="com.android.bluetooth.avrcpcontroller.AvrcpCoverArtProvider"
android:authorities="com.android.bluetooth.avrcpcontroller.AvrcpCoverArtProvider"
android:enabled="@bool/avrcp_controller_enable_cover_art"
android:grantUriPermissions="true"
android:exported="true">
</provider>
<service android:process="@string/process"
- android:name=".hid.HidHostService"
+ android:name="com.android.bluetooth.hid.HidHostService"
android:enabled="@bool/profile_supported_hid_host"
android:exported="true">
<intent-filter>
@@ -367,7 +365,7 @@
</intent-filter>
</service>
<service android:process="@string/process"
- android:name=".hid.HidDeviceService"
+ android:name="com.android.bluetooth.hid.HidDeviceService"
android:enabled="@bool/profile_supported_hid_device"
android:exported="true">
<intent-filter>
@@ -375,7 +373,7 @@
</intent-filter>
</service>
<service android:process="@string/process"
- android:name=".mcp.McpService"
+ android:name="com.android.bluetooth.mcp.McpService"
android:exported="true"
android:enabled="@bool/profile_supported_mcp_server">
<intent-filter>
@@ -384,7 +382,7 @@
</service>
<service
android:process="@string/process"
- android:name=".pan.PanService"
+ android:name="com.android.bluetooth.pan.PanService"
android:enabled="@bool/profile_supported_pan"
android:exported="true">
<intent-filter>
@@ -392,7 +390,7 @@
</intent-filter>
</service>
<service android:process="@string/process"
- android:name=".hfpclient.HeadsetClientService"
+ android:name="com.android.bluetooth.hfpclient.HeadsetClientService"
android:enabled="@bool/profile_supported_hfpclient"
android:exported="true">
<intent-filter>
@@ -400,7 +398,7 @@
</intent-filter>
</service>
<service android:process="@string/process"
- android:name=".hfpclient.HfpClientConnectionService"
+ android:name="com.android.bluetooth.hfpclient.HfpClientConnectionService"
android:permission="android.permission.BIND_CONNECTION_SERVICE"
android:enabled="@bool/hfp_client_connection_service_enabled"
android:exported="true">
@@ -410,7 +408,7 @@
</intent-filter>
</service>
<service android:process="@string/process"
- android:name=".pbapclient.PbapClientService"
+ android:name="com.android.bluetooth.pbapclient.PbapClientService"
android:enabled="@bool/profile_supported_pbapclient"
android:exported="true">
<intent-filter>
@@ -418,14 +416,14 @@
</intent-filter>
</service>
<service android:process="@string/process"
- android:name=".hearingaid.HearingAidService"
+ android:name="com.android.bluetooth.hearingaid.HearingAidService"
android:exported="true">
<intent-filter>
<action android:name="android.bluetooth.IBluetoothHearingAid"/>
</intent-filter>
</service>
<service android:process="@string/process"
- android:name=".hap.HapClientService"
+ android:name="com.android.bluetooth.hap.HapClientService"
android:enabled="@bool/profile_supported_hap_client"
android:exported="true">
<intent-filter>
@@ -434,7 +432,7 @@
</service>
<service
android:process="@string/process"
- android:name=".vc.VolumeControlService"
+ android:name="com.android.bluetooth.vc.VolumeControlService"
android:exported="true"
android:enabled="@bool/profile_supported_vc">
<intent-filter>
@@ -443,7 +441,7 @@
</service>
<service
android:process="@string/process"
- android:name = ".le_audio.LeAudioService"
+ android:name = "com.android.bluetooth.le_audio.LeAudioService"
android:enabled="@bool/profile_supported_le_audio"
android:exported = "true">
<intent-filter>
@@ -452,7 +450,7 @@
</service>
<service
android:process="@string/process"
- android:name = ".csip.CsipSetCoordinatorService"
+ android:name = "com.android.bluetooth.csip.CsipSetCoordinatorService"
android:enabled="@bool/profile_supported_csip_set_coordinator"
android:exported = "true">
<intent-filter>
@@ -461,7 +459,7 @@
</service>
<service
android:process="@string/process"
- android:name = ".tbs.TbsService"
+ android:name = "com.android.bluetooth.tbs.TbsService"
android:enabled="@bool/profile_supported_le_call_control"
android:exported = "true">
<intent-filter>
@@ -470,7 +468,7 @@
</service>
<service
android:process="@string/process"
- android:name = ".bass_client.BassClientService"
+ android:name = "com.android.bluetooth.bass_client.BassClientService"
android:enabled="@bool/profile_supported_bass_client"
android:exported = "true">
<intent-filter>
@@ -479,7 +477,7 @@
</service>
<!-- Authenticator for PBAP account. -->
<service android:process="@string/process"
- android:name=".pbapclient.AuthenticationService"
+ android:name="com.android.bluetooth.pbapclient.AuthenticationService"
android:exported="true"
android:enabled="@bool/profile_supported_pbapclient">
<intent-filter>
@@ -489,7 +487,7 @@
android:resource="@xml/authenticator"/>
</service>
<service
- android:name=".telephony.BluetoothInCallService"
+ android:name="com.android.bluetooth.telephony.BluetoothInCallService"
android:permission="android.permission.BIND_INCALL_SERVICE"
android:process="@string/process"
android:enabled="@bool/profile_supported_hfp_incallservice"
@@ -502,7 +500,7 @@
</service>
<service
android:process="@string/process"
- android:name=".bas.BatteryService"
+ android:name="com.android.bluetooth.bas.BatteryService"
android:enabled="@bool/profile_supported_battery"
android:exported = "true">
<intent-filter>
diff --git a/android/app/jni/com_android_bluetooth_le_audio.cpp b/android/app/jni/com_android_bluetooth_le_audio.cpp
index 61cb49a966..45111b54ba 100644
--- a/android/app/jni/com_android_bluetooth_le_audio.cpp
+++ b/android/app/jni/com_android_bluetooth_le_audio.cpp
@@ -491,7 +491,6 @@ static JNINativeMethod sMethods[] = {
static jmethodID method_onBroadcastCreated;
static jmethodID method_onBroadcastDestroyed;
static jmethodID method_onBroadcastStateChanged;
-static jmethodID method_onBroadcastId;
static LeAudioBroadcasterInterface* sLeAudioBroadcasterInterface = nullptr;
static std::shared_timed_mutex sBroadcasterInterfaceMutex;
@@ -503,7 +502,7 @@ class LeAudioBroadcasterCallbacksImpl : public LeAudioBroadcasterCallbacks {
public:
~LeAudioBroadcasterCallbacksImpl() = default;
- void OnBroadcastCreated(uint8_t instance_id, bool success) override {
+ void OnBroadcastCreated(uint32_t broadcast_id, bool success) override {
LOG(INFO) << __func__;
std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterCallbacksMutex);
@@ -511,11 +510,11 @@ class LeAudioBroadcasterCallbacksImpl : public LeAudioBroadcasterCallbacks {
if (!sCallbackEnv.valid() || sBroadcasterCallbacksObj == nullptr) return;
sCallbackEnv->CallVoidMethod(sBroadcasterCallbacksObj,
- method_onBroadcastCreated, (jint)instance_id,
+ method_onBroadcastCreated, (jint)broadcast_id,
success ? JNI_TRUE : JNI_FALSE);
}
- void OnBroadcastDestroyed(uint8_t instance_id) override {
+ void OnBroadcastDestroyed(uint32_t broadcast_id) override {
LOG(INFO) << __func__;
std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterCallbacksMutex);
@@ -524,10 +523,10 @@ class LeAudioBroadcasterCallbacksImpl : public LeAudioBroadcasterCallbacks {
if (!sCallbackEnv.valid() || sBroadcasterCallbacksObj == nullptr) return;
sCallbackEnv->CallVoidMethod(sBroadcasterCallbacksObj,
method_onBroadcastDestroyed,
- (jint)instance_id);
+ (jint)broadcast_id);
}
- void OnBroadcastStateChanged(uint8_t instance_id,
+ void OnBroadcastStateChanged(uint32_t broadcast_id,
BroadcastState state) override {
LOG(INFO) << __func__;
@@ -537,35 +536,9 @@ class LeAudioBroadcasterCallbacksImpl : public LeAudioBroadcasterCallbacks {
if (!sCallbackEnv.valid() || sBroadcasterCallbacksObj == nullptr) return;
sCallbackEnv->CallVoidMethod(
sBroadcasterCallbacksObj, method_onBroadcastStateChanged,
- (jint)instance_id,
+ (jint)broadcast_id,
(jint) static_cast<std::underlying_type<BroadcastState>::type>(state));
}
-
- void OnBroadcastId(uint8_t instance_id,
- const BroadcastId& broadcast_id) override {
- LOG(INFO) << __func__;
-
- std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterCallbacksMutex);
- CallbackEnv sCallbackEnv(__func__);
-
- // broadcast_id
- int field_size = broadcast_id.size();
- ScopedLocalRef<jbyteArray> serialized_broadcast_id(
- sCallbackEnv.get(), sCallbackEnv->NewByteArray(field_size));
- if (!serialized_broadcast_id.get()) {
- LOG(ERROR) << "Failed to allocate new jbyteArray broadcast_id for the "
- "announcement";
- return;
- }
-
- sCallbackEnv->SetByteArrayRegion(serialized_broadcast_id.get(), 0,
- field_size, (jbyte*)broadcast_id.data());
-
- if (!sCallbackEnv.valid() || sBroadcasterCallbacksObj == nullptr) return;
- sCallbackEnv->CallVoidMethod(sBroadcasterCallbacksObj, method_onBroadcastId,
- (jint)instance_id,
- serialized_broadcast_id.get());
- }
};
static LeAudioBroadcasterCallbacksImpl sLeAudioBroadcasterCallbacks;
@@ -577,7 +550,6 @@ static void BroadcasterClassInitNative(JNIEnv* env, jclass clazz) {
env->GetMethodID(clazz, "onBroadcastDestroyed", "(I)V");
method_onBroadcastStateChanged =
env->GetMethodID(clazz, "onBroadcastStateChanged", "(II)V");
- method_onBroadcastId = env->GetMethodID(clazz, "onBroadcastId", "(I[B)V");
}
static void BroadcasterInitNative(JNIEnv* env, jobject object) {
@@ -672,52 +644,45 @@ static void CreateBroadcastNative(JNIEnv* env, jobject object,
env->ReleaseByteArrayElements(metadata, meta, 0);
}
-static void UpdateMetadataNative(JNIEnv* env, jobject object, jint instance_id,
+static void UpdateMetadataNative(JNIEnv* env, jobject object, jint broadcast_id,
jbyteArray metadata) {
jbyte* meta = env->GetByteArrayElements(metadata, nullptr);
sLeAudioBroadcasterInterface->UpdateMetadata(
- instance_id,
+ broadcast_id,
std::vector<uint8_t>(meta, meta + env->GetArrayLength(metadata)));
env->ReleaseByteArrayElements(metadata, meta, 0);
}
static void StartBroadcastNative(JNIEnv* env, jobject object,
- jint instance_id) {
+ jint broadcast_id) {
LOG(INFO) << __func__;
std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterInterfaceMutex);
if (!sLeAudioBroadcasterInterface) return;
- sLeAudioBroadcasterInterface->StartBroadcast(instance_id);
+ sLeAudioBroadcasterInterface->StartBroadcast(broadcast_id);
}
-static void StopBroadcastNative(JNIEnv* env, jobject object, jint instance_id) {
+static void StopBroadcastNative(JNIEnv* env, jobject object,
+ jint broadcast_id) {
LOG(INFO) << __func__;
std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterInterfaceMutex);
if (!sLeAudioBroadcasterInterface) return;
- sLeAudioBroadcasterInterface->StopBroadcast(instance_id);
+ sLeAudioBroadcasterInterface->StopBroadcast(broadcast_id);
}
static void PauseBroadcastNative(JNIEnv* env, jobject object,
- jint instance_id) {
+ jint broadcast_id) {
LOG(INFO) << __func__;
std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterInterfaceMutex);
if (!sLeAudioBroadcasterInterface) return;
- sLeAudioBroadcasterInterface->PauseBroadcast(instance_id);
+ sLeAudioBroadcasterInterface->PauseBroadcast(broadcast_id);
}
static void DestroyBroadcastNative(JNIEnv* env, jobject object,
- jint instance_id) {
- LOG(INFO) << __func__;
- std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterInterfaceMutex);
- if (!sLeAudioBroadcasterInterface) return;
- sLeAudioBroadcasterInterface->DestroyBroadcast(instance_id);
-}
-
-static void GetBroadcastIdNative(JNIEnv* env, jobject object,
- jint instance_id) {
+ jint broadcast_id) {
LOG(INFO) << __func__;
std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterInterfaceMutex);
if (!sLeAudioBroadcasterInterface) return;
- sLeAudioBroadcasterInterface->GetBroadcastId(instance_id);
+ sLeAudioBroadcasterInterface->DestroyBroadcast(broadcast_id);
}
static void GetAllBroadcastStatesNative(JNIEnv* env, jobject object) {
@@ -738,7 +703,6 @@ static JNINativeMethod sBroadcasterMethods[] = {
{"stopBroadcastNative", "(I)V", (void*)StopBroadcastNative},
{"pauseBroadcastNative", "(I)V", (void*)PauseBroadcastNative},
{"destroyBroadcastNative", "(I)V", (void*)DestroyBroadcastNative},
- {"getBroadcastIdNative", "(I)V", (void*)GetBroadcastIdNative},
{"getAllBroadcastStatesNative", "()V", (void*)GetAllBroadcastStatesNative},
};
diff --git a/android/app/res/values-fa/strings.xml b/android/app/res/values-fa/strings.xml
index e16bda920e..70c818e3c7 100644
--- a/android/app/res/values-fa/strings.xml
+++ b/android/app/res/values-fa/strings.xml
@@ -51,7 +51,7 @@
<string name="download_line3" msgid="6722284930665532816">"اندازه فایل: <xliff:g id="SIZE">%1$s</xliff:g>"</string>
<string name="download_line4" msgid="5234701398884321314"></string>
<string name="download_line5" msgid="4124272066218470715">"درحال دریافت فایل…"</string>
- <string name="download_cancel" msgid="1705762428762702342">"توقف"</string>
+ <string name="download_cancel" msgid="1705762428762702342">"متوقف کردن"</string>
<string name="download_ok" msgid="2404442707314575833">"پنهان کردن"</string>
<string name="incoming_line1" msgid="6342300988329482408">"از"</string>
<string name="incoming_line2" msgid="2199520895444457585">"نام فایل"</string>
diff --git a/android/app/res/values-hy/strings.xml b/android/app/res/values-hy/strings.xml
index 4a259944a2..98b9472381 100644
--- a/android/app/res/values-hy/strings.xml
+++ b/android/app/res/values-hy/strings.xml
@@ -51,7 +51,7 @@
<string name="download_line3" msgid="6722284930665532816">"Ֆայլի չափը՝ <xliff:g id="SIZE">%1$s</xliff:g>"</string>
<string name="download_line4" msgid="5234701398884321314"></string>
<string name="download_line5" msgid="4124272066218470715">"Ֆայլի ստացում..."</string>
- <string name="download_cancel" msgid="1705762428762702342">"Դադարեցնել"</string>
+ <string name="download_cancel" msgid="1705762428762702342">"Կանգնեցնել"</string>
<string name="download_ok" msgid="2404442707314575833">"Թաքցնել"</string>
<string name="incoming_line1" msgid="6342300988329482408">"Ումից"</string>
<string name="incoming_line2" msgid="2199520895444457585">"Ֆայլի անունը"</string>
diff --git a/android/app/res/values/config.xml b/android/app/res/values/config.xml
index 092860759f..bd4c838049 100644
--- a/android/app/res/values/config.xml
+++ b/android/app/res/values/config.xml
@@ -39,7 +39,7 @@
<bool name="profile_supported_csip_set_coordinator">true</bool>
<bool name="profile_supported_le_call_control">true</bool>
<bool name="profile_supported_hap_client">true</bool>
- <bool name="profile_supported_bass_client">false</bool>
+ <bool name="profile_supported_bass_client">true</bool>
<bool name="profile_supported_battery">true</bool>
<!-- If true, we will require location to be enabled on the device to
diff --git a/android/app/src/com/android/bluetooth/Utils.java b/android/app/src/com/android/bluetooth/Utils.java
index fb0be8ea83..b063de0cef 100644
--- a/android/app/src/com/android/bluetooth/Utils.java
+++ b/android/app/src/com/android/bluetooth/Utils.java
@@ -844,12 +844,26 @@ public final class Utils {
android.Manifest.permission.WRITE_SMS) == PackageManager.PERMISSION_GRANTED;
}
- public static boolean isQApp(Context context, String pkgName) {
+ /**
+ * Checks that the target sdk of the app corresponding to the provided package name is greater
+ * than or equal to the passed in target sdk.
+ * <p>
+ * For example, if the calling app has target SDK {@link Build.VERSION_CODES#S} and we pass in
+ * the targetSdk {@link Build.VERSION_CODES#R}, the API will return true because S >= R.
+ *
+ * @param context Bluetooth service context
+ * @param pkgName caller's package name
+ * @param expectedMinimumTargetSdk one of the values from {@link Build.VERSION_CODES}
+ * @return {@code true} if the caller's target sdk is greater than or equal to
+ * expectedMinimumTargetSdk, {@code false} otherwise
+ */
+ public static boolean checkCallerTargetSdk(Context context, String pkgName,
+ int expectedMinimumTargetSdk) {
try {
return context.getPackageManager().getApplicationInfo(pkgName, 0).targetSdkVersion
- >= Build.VERSION_CODES.Q;
+ >= expectedMinimumTargetSdk;
} catch (PackageManager.NameNotFoundException e) {
- // In case of exception, assume Q app
+ // In case of exception, assume true
}
return true;
}
diff --git a/android/app/src/com/android/bluetooth/avrcp/AvrcpVolumeManager.java b/android/app/src/com/android/bluetooth/avrcp/AvrcpVolumeManager.java
index 39f1f14975..d0cfa58fbc 100644
--- a/android/app/src/com/android/bluetooth/avrcp/AvrcpVolumeManager.java
+++ b/android/app/src/com/android/bluetooth/avrcp/AvrcpVolumeManager.java
@@ -176,7 +176,7 @@ class AvrcpVolumeManager extends AudioDeviceCallback {
void setVolume(@NonNull BluetoothDevice device, int avrcpVolume) {
int deviceVolume =
- (int) Math.floor((double) avrcpVolume * sDeviceMaxVolume / AVRCP_MAX_VOL);
+ (int) Math.round((double) avrcpVolume * sDeviceMaxVolume / AVRCP_MAX_VOL);
mVolumeEventLogger.logd(DEBUG, TAG, "setVolume:"
+ " device=" + device
+ " avrcpVolume=" + avrcpVolume
@@ -194,7 +194,7 @@ class AvrcpVolumeManager extends AudioDeviceCallback {
return;
}
int avrcpVolume =
- (int) Math.floor((double) deviceVolume * AVRCP_MAX_VOL / sDeviceMaxVolume);
+ (int) Math.round((double) deviceVolume * AVRCP_MAX_VOL / sDeviceMaxVolume);
if (avrcpVolume > 127) avrcpVolume = 127;
mVolumeEventLogger.logd(DEBUG, TAG, "sendVolumeChanged:"
+ " device=" + device
diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java b/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java
index d58969af49..0c4cc1d86a 100644
--- a/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java
+++ b/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java
@@ -949,8 +949,7 @@ class AdapterProperties {
case AbstractionLayer.BT_PROPERTY_LOCAL_LE_FEATURES:
updateFeatureSupport(val);
- mService.updateLeAudioProfileServiceState(
- mIsLeConnectedIsochronousStreamCentralSupported);
+ mService.updateLeAudioProfileServiceState();
break;
case AbstractionLayer.BT_PROPERTY_DYNAMIC_AUDIO_BUFFER:
diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java
index e6c03e21bf..ff5b89d106 100644
--- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java
+++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java
@@ -76,6 +76,7 @@ import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.BatteryStatsManager;
import android.os.Binder;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -211,7 +212,7 @@ public class AdapterService extends Service {
private static final int CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS = 30;
private static final ComponentName BLUETOOTH_INCALLSERVICE_COMPONENT =
- new ComponentName("com.android.bluetooth",
+ new ComponentName("com.android.bluetooth.services",
BluetoothInCallService.class.getCanonicalName());
public static final String ACTIVITY_ATTRIBUTION_NO_ACTIVE_DEVICE_ADDRESS =
@@ -741,19 +742,27 @@ public class AdapterService extends Service {
BluetoothAdapter.invalidateBluetoothGetStateCache();
}
- void updateLeAudioProfileServiceState(boolean isCisCentralSupported) {
- if (isCisCentralSupported) {
- return;
+ void updateLeAudioProfileServiceState() {
+ HashSet<Class> nonSupportedProfiles = new HashSet<>();
+
+ if (!isLeConnectedIsochronousStreamCentralSupported()) {
+ nonSupportedProfiles.addAll(Config.geLeAudioUnicastProfiles());
+ }
+
+ if (!isLeAudioBroadcastAssistantSupported()) {
+ nonSupportedProfiles.add(BassClientService.class);
}
- // Remove the Le audio unicast profiles from the supported list
- // since the controller doesn't support
- Config.removeLeAudioUnicastProfilesFromSupportedList();
- HashSet<Class> leAudioUnicastProfiles = Config.geLeAudioUnicastProfiles();
+ if (!nonSupportedProfiles.isEmpty()) {
+ // Remove non-supported profiles from the supported list
+ // since the controller doesn't support
+ Config.removeProfileFromSupportedList(nonSupportedProfiles);
- for (Class profileService : leAudioUnicastProfiles) {
- if (isStartedProfile(profileService.getSimpleName())){
- setProfileServiceState(profileService, BluetoothAdapter.STATE_OFF);
+ // Disable the non-supported profiles service
+ for (Class profileService : nonSupportedProfiles) {
+ if (isStartedProfile(profileService.getSimpleName())) {
+ setProfileServiceState(profileService, BluetoothAdapter.STATE_OFF);
+ }
}
}
}
@@ -3421,7 +3430,10 @@ public class AdapterService extends Service {
return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
}
- if (service.isLeAudioBroadcastAssistantSupported()) {
+ HashSet<Class> supportedProfileServices =
+ new HashSet<Class>(Arrays.asList(Config.getSupportedProfiles()));
+
+ if (supportedProfileServices.contains(BassClientService.class)) {
return BluetoothStatusCodes.FEATURE_SUPPORTED;
}
@@ -3830,7 +3842,7 @@ public class AdapterService extends Service {
debugLog("startDiscovery");
String callingPackage = attributionSource.getPackageName();
mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
- boolean isQApp = Utils.isQApp(this, callingPackage);
+ boolean isQApp = Utils.checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.Q);
boolean hasDisavowedLocation =
Utils.hasDisavowedLocationForScan(this, attributionSource, mTestModeEnabled);
String permission = null;
@@ -4643,13 +4655,21 @@ public class AdapterService extends Service {
* @return true, if the LE audio broadcast assistant is supported
*/
public boolean isLeAudioBroadcastAssistantSupported() {
- //TODO: check the profile support status as well after we have the implementation
return mAdapterProperties.isLePeriodicAdvertisingSupported()
&& mAdapterProperties.isLeExtendedAdvertisingSupported()
&& (mAdapterProperties.isLePeriodicAdvertisingSyncTransferSenderSupported()
|| mAdapterProperties.isLePeriodicAdvertisingSyncTransferRecipientSupported());
}
+ /**
+ * Check if the LE audio CIS central feature is supported.
+ *
+ * @return true, if the LE audio CIS central is supported
+ */
+ public boolean isLeConnectedIsochronousStreamCentralSupported() {
+ return mAdapterProperties.isLeConnectedIsochronousStreamCentralSupported();
+ }
+
public int getLeMaximumAdvertisingDataLength() {
return mAdapterProperties.getLeMaximumAdvertisingDataLength();
}
diff --git a/android/app/src/com/android/bluetooth/btservice/BondStateMachine.java b/android/app/src/com/android/bluetooth/btservice/BondStateMachine.java
index be2f5a6c4d..d2a9fd3458 100644
--- a/android/app/src/com/android/bluetooth/btservice/BondStateMachine.java
+++ b/android/app/src/com/android/bluetooth/btservice/BondStateMachine.java
@@ -148,7 +148,7 @@ final class BondStateMachine extends StateMachine {
int newState = msg.arg1;
/* if incoming pairing, transition to pending state */
if (newState == BluetoothDevice.BOND_BONDING) {
- sendIntent(dev, newState, 0);
+ deferMessage(msg);
transitionTo(mPendingCommandState);
} else if (newState == BluetoothDevice.BOND_NONE) {
/* if the link key was deleted by the stack */
diff --git a/android/app/src/com/android/bluetooth/btservice/Config.java b/android/app/src/com/android/bluetooth/btservice/Config.java
index 85884b0fe3..718fabdb20 100644
--- a/android/app/src/com/android/bluetooth/btservice/Config.java
+++ b/android/app/src/com/android/bluetooth/btservice/Config.java
@@ -199,16 +199,16 @@ public class Config {
}
/**
- * Remove LE audio unicast related profiles from the supported list.
+ * Remove the input profiles from the supported list.
*/
- static void removeLeAudioUnicastProfilesFromSupportedList() {
+ static void removeProfileFromSupportedList(HashSet<Class> nonSupportedProfiles) {
ArrayList<Class> profilesList = new ArrayList<Class>(Arrays.asList(sSupportedProfiles));
Iterator<Class> iter = profilesList.iterator();
while (iter.hasNext()) {
Class profileClass = iter.next();
- if (mLeAudioUnicastProfiles.contains(profileClass)) {
+ if (nonSupportedProfiles.contains(profileClass)) {
iter.remove();
Log.v(TAG, "Remove " + profileClass.getSimpleName() + " from supported list.");
}
diff --git a/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java b/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java
index e8857e35ac..39f456cc07 100644
--- a/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java
+++ b/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java
@@ -205,7 +205,7 @@ public class MetricsLogger {
private PendingIntent getDrainIntent() {
Intent counterMetricsIntent = new Intent(BLUETOOTH_COUNTER_METRICS_ACTION);
- counterMetricsIntent.setPackage("com.android.bluetooth");
+ counterMetricsIntent.setPackage("com.android.bluetooth.services");
return PendingIntent.getBroadcast(
mContext, 0, counterMetricsIntent, PendingIntent.FLAG_IMMUTABLE);
}
diff --git a/android/app/src/com/android/bluetooth/btservice/storage/CustomizedMetadataEntity.java b/android/app/src/com/android/bluetooth/btservice/storage/CustomizedMetadataEntity.java
index 2bb71efea8..554e0753fc 100644
--- a/android/app/src/com/android/bluetooth/btservice/storage/CustomizedMetadataEntity.java
+++ b/android/app/src/com/android/bluetooth/btservice/storage/CustomizedMetadataEntity.java
@@ -44,6 +44,8 @@ class CustomizedMetadataEntity {
public byte[] untethered_left_low_battery_threshold;
public byte[] untethered_right_low_battery_threshold;
public byte[] untethered_case_low_battery_threshold;
+ public byte[] spatial_audio;
+ public byte[] fastpair_customized;
public String toString() {
StringBuilder builder = new StringBuilder();
@@ -94,7 +96,11 @@ class CustomizedMetadataEntity {
.append("|untethered_right_low_battery_threshold=")
.append(metadataToString(untethered_right_low_battery_threshold))
.append("|untethered_case_low_battery_threshold=")
- .append(metadataToString(untethered_case_low_battery_threshold));
+ .append(metadataToString(untethered_case_low_battery_threshold))
+ .append("|spatial_audio=")
+ .append(metadataToString(spatial_audio))
+ .append("|fastpair_customized=")
+ .append(metadataToString(fastpair_customized));
return builder.toString();
}
diff --git a/android/app/src/com/android/bluetooth/btservice/storage/Metadata.java b/android/app/src/com/android/bluetooth/btservice/storage/Metadata.java
index 36d6b43cae..2b7f0d5809 100644
--- a/android/app/src/com/android/bluetooth/btservice/storage/Metadata.java
+++ b/android/app/src/com/android/bluetooth/btservice/storage/Metadata.java
@@ -254,6 +254,12 @@ class Metadata {
case BluetoothDevice.METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD:
publicMetadata.untethered_case_low_battery_threshold = value;
break;
+ case BluetoothDevice.METADATA_SPATIAL_AUDIO:
+ publicMetadata.spatial_audio = value;
+ break;
+ case BluetoothDevice.METADATA_FAST_PAIR_CUSTOMIZED_FIELDS:
+ publicMetadata.fastpair_customized = value;
+ break;
}
}
@@ -332,6 +338,12 @@ class Metadata {
case BluetoothDevice.METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD:
value = publicMetadata.untethered_case_low_battery_threshold;
break;
+ case BluetoothDevice.METADATA_SPATIAL_AUDIO:
+ value = publicMetadata.spatial_audio;
+ break;
+ case BluetoothDevice.METADATA_FAST_PAIR_CUSTOMIZED_FIELDS:
+ value = publicMetadata.fastpair_customized;
+ break;
}
return value;
}
diff --git a/android/app/src/com/android/bluetooth/btservice/storage/MetadataDatabase.java b/android/app/src/com/android/bluetooth/btservice/storage/MetadataDatabase.java
index 91338179f2..a2db277c0d 100644
--- a/android/app/src/com/android/bluetooth/btservice/storage/MetadataDatabase.java
+++ b/android/app/src/com/android/bluetooth/btservice/storage/MetadataDatabase.java
@@ -33,7 +33,7 @@ import java.util.List;
/**
* MetadataDatabase is a Room database stores Bluetooth persistence data
*/
-@Database(entities = {Metadata.class}, version = 112)
+@Database(entities = {Metadata.class}, version = 113)
public abstract class MetadataDatabase extends RoomDatabase {
/**
* The metadata database file name
@@ -65,6 +65,7 @@ public abstract class MetadataDatabase extends RoomDatabase {
.addMigrations(MIGRATION_109_110)
.addMigrations(MIGRATION_110_111)
.addMigrations(MIGRATION_111_112)
+ .addMigrations(MIGRATION_112_113)
.allowMainThreadQueries()
.build();
}
@@ -465,4 +466,21 @@ public abstract class MetadataDatabase extends RoomDatabase {
}
}
};
+
+ @VisibleForTesting
+ static final Migration MIGRATION_112_113 = new Migration(112, 113) {
+ @Override
+ public void migrate(SupportSQLiteDatabase database) {
+ try {
+ database.execSQL("ALTER TABLE metadata ADD COLUMN `spatial_audio` BLOB");
+ database.execSQL("ALTER TABLE metadata ADD COLUMN `fastpair_customized` BLOB");
+ } catch (SQLException ex) {
+ // Check if user has new schema, but is just missing the version update
+ Cursor cursor = database.query("SELECT * FROM metadata");
+ if (cursor == null || cursor.getColumnIndex("spatial_audio") == -1) {
+ throw ex;
+ }
+ }
+ }
+ };
}
diff --git a/android/app/src/com/android/bluetooth/gatt/ContextMap.java b/android/app/src/com/android/bluetooth/gatt/ContextMap.java
index d4525327f1..ed95301ad6 100644
--- a/android/app/src/com/android/bluetooth/gatt/ContextMap.java
+++ b/android/app/src/com/android/bluetooth/gatt/ContextMap.java
@@ -95,9 +95,6 @@ import java.util.UUID;
/** The user handle of the app that started the scan */
UserHandle mUserHandle;
- /** Whether the calling app is targeting Q or better */
- boolean mIsQApp;
-
/** Whether the calling app has the network settings permission */
boolean mHasNetworkSettingsPermission;
diff --git a/android/app/src/com/android/bluetooth/gatt/GattService.java b/android/app/src/com/android/bluetooth/gatt/GattService.java
index 2649ebf355..063b752f3f 100644
--- a/android/app/src/com/android/bluetooth/gatt/GattService.java
+++ b/android/app/src/com/android/bluetooth/gatt/GattService.java
@@ -16,6 +16,7 @@
package com.android.bluetooth.gatt;
+import static com.android.bluetooth.Utils.checkCallerTargetSdk;
import static com.android.bluetooth.Utils.enforceBluetoothPrivilegedPermission;
import android.annotation.RequiresPermission;
@@ -2308,8 +2309,8 @@ public class GattService extends ProfileService {
try {
permissionCheck(connId, handle);
} catch (SecurityException ex) {
- // Only throws on T+ as this is an older API and did not throw prior to T
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ // Only throws on apps with target SDK T+ as this old API did not throw prior to T
+ if (checkCallerTargetSdk(this, app.name, Build.VERSION_CODES.TIRAMISU)) {
throw ex;
}
Log.w(TAG, "onNotify() - permission check failed!");
@@ -2976,7 +2977,7 @@ public class GattService extends ProfileService {
scanClient.hasDisavowedLocation =
Utils.hasDisavowedLocationForScan(this, attributionSource, isTestModeEnabled());
- scanClient.isQApp = Utils.isQApp(this, callingPackage);
+ scanClient.isQApp = checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.Q);
if (!scanClient.hasDisavowedLocation) {
if (scanClient.isQApp) {
scanClient.hasLocationPermission = Utils.checkCallerHasFineLocation(
@@ -3052,10 +3053,9 @@ public class GattService extends ProfileService {
app.mHasDisavowedLocation =
Utils.hasDisavowedLocationForScan(this, attributionSource, isTestModeEnabled());
- app.mIsQApp = Utils.isQApp(this, callingPackage);
if (!app.mHasDisavowedLocation) {
try {
- if (app.mIsQApp) {
+ if (checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.Q)) {
app.hasLocationPermission = Utils.checkCallerHasFineLocation(
this, attributionSource, app.mUserHandle);
} else {
@@ -3089,7 +3089,7 @@ public class GattService extends ProfileService {
new ScanClient(scannerId, piInfo.settings, piInfo.filters);
scanClient.hasLocationPermission = app.hasLocationPermission;
scanClient.userHandle = app.mUserHandle;
- scanClient.isQApp = app.mIsQApp;
+ scanClient.isQApp = checkCallerTargetSdk(this, app.name, Build.VERSION_CODES.Q);
scanClient.eligibleForSanitizedExposureNotification =
app.mEligibleForSanitizedExposureNotification;
scanClient.hasNetworkSettingsPermission = app.mHasNetworkSettingsPermission;
@@ -3556,8 +3556,9 @@ public class GattService extends ProfileService {
try {
permissionCheck(connId, handle);
} catch (SecurityException ex) {
- // Only throws on T+ as this is an older API and did not throw prior to T
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ String callingPackage = attributionSource.getPackageName();
+ // Only throws on apps with target SDK T+ as this old API did not throw prior to T
+ if (checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.TIRAMISU)) {
throw ex;
}
Log.w(TAG, "readCharacteristic() - permission check failed!");
@@ -3588,8 +3589,9 @@ public class GattService extends ProfileService {
try {
permissionCheck(uuid);
} catch (SecurityException ex) {
- // Only throws on T+ as this is an older API and did not throw prior to T
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ String callingPackage = attributionSource.getPackageName();
+ // Only throws on apps with target SDK T+ as this old API did not throw prior to T
+ if (checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.TIRAMISU)) {
throw ex;
}
Log.w(TAG, "readUsingCharacteristicUuid() - permission check failed!");
@@ -3665,8 +3667,9 @@ public class GattService extends ProfileService {
try {
permissionCheck(connId, handle);
} catch (SecurityException ex) {
- // Only throws on T+ as this is an older API and did not throw prior to T
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ String callingPackage = attributionSource.getPackageName();
+ // Only throws on apps with target SDK T+ as this old API did not throw prior to T
+ if (checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.TIRAMISU)) {
throw ex;
}
Log.w(TAG, "readDescriptor() - permission check failed!");
@@ -3751,8 +3754,9 @@ public class GattService extends ProfileService {
try {
permissionCheck(connId, handle);
} catch (SecurityException ex) {
- // Only throws on T+ as this is an older API and did not throw prior to T
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ String callingPackage = attributionSource.getPackageName();
+ // Only throws on apps with target SDK T+ as this old API did not throw prior to T
+ if (checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.TIRAMISU)) {
throw ex;
}
Log.w(TAG, "registerForNotification() - permission check failed!");
diff --git a/android/app/src/com/android/bluetooth/le_audio/LeAudioBroadcasterNativeInterface.java b/android/app/src/com/android/bluetooth/le_audio/LeAudioBroadcasterNativeInterface.java
index 7c3e06e992..5c93ff5a46 100644
--- a/android/app/src/com/android/bluetooth/le_audio/LeAudioBroadcasterNativeInterface.java
+++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioBroadcasterNativeInterface.java
@@ -81,34 +81,34 @@ public class LeAudioBroadcasterNativeInterface {
// Callbacks from the native stack back into the Java framework.
@VisibleForTesting
- public void onBroadcastCreated(int instanceId, boolean success) {
+ public void onBroadcastCreated(int broadcastId, boolean success) {
if (DBG) {
- Log.d(TAG, "onBroadcastCreated: instanceId=" + instanceId);
+ Log.d(TAG, "onBroadcastCreated: broadcastId=" + broadcastId);
}
LeAudioStackEvent event =
new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_CREATED);
- event.valueInt1 = instanceId;
+ event.valueInt1 = broadcastId;
event.valueBool1 = success;
sendMessageToService(event);
}
@VisibleForTesting
- public void onBroadcastDestroyed(int instanceId) {
+ public void onBroadcastDestroyed(int broadcastId) {
if (DBG) {
- Log.d(TAG, "onBroadcastDestroyed: instanceId=" + instanceId);
+ Log.d(TAG, "onBroadcastDestroyed: broadcastId=" + broadcastId);
}
LeAudioStackEvent event =
new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_DESTROYED);
- event.valueInt1 = instanceId;
+ event.valueInt1 = broadcastId;
sendMessageToService(event);
}
@VisibleForTesting
- public void onBroadcastStateChanged(int instanceId, int state) {
+ public void onBroadcastStateChanged(int broadcastId, int state) {
if (DBG) {
- Log.d(TAG, "onBroadcastStateChanged: instanceId=" + instanceId + " state=" + state);
+ Log.d(TAG, "onBroadcastStateChanged: broadcastId=" + broadcastId + " state=" + state);
}
LeAudioStackEvent event =
new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_STATE);
@@ -120,23 +120,11 @@ public class LeAudioBroadcasterNativeInterface {
* For now it's only important that this device is a Bluetooth device.
*/
event.device = getDevice(Utils.getBytesFromAddress("FF:FF:FF:FF:FF:FF"));
- event.valueInt1 = instanceId;
+ event.valueInt1 = broadcastId;
event.valueInt2 = state;
sendMessageToService(event);
}
- @VisibleForTesting
- public void onBroadcastId(int instanceId, byte[] broadcastId) {
- LeAudioStackEvent event =
- new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_ID);
- event.valueInt1 = instanceId;
- event.valueByte1 = broadcastId;
- if (DBG) {
- Log.d(TAG, "onBroadcastId: " + event);
- }
- sendMessageToService(event);
- }
-
/**
* Initializes the native interface.
*
@@ -178,62 +166,52 @@ public class LeAudioBroadcasterNativeInterface {
/**
* Update LeAudio Broadcast instance metadata.
*
- * @param instanceId broadcast instance identifier
+ * @param broadcastId broadcast instance identifier
* @param metadata metadata buffer with TLVs
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public void updateMetadata(int instanceId, byte[] metadata) {
- updateMetadataNative(instanceId, metadata);
+ public void updateMetadata(int broadcastId, byte[] metadata) {
+ updateMetadataNative(broadcastId, metadata);
}
/**
* Start LeAudio Broadcast instance.
*
- * @param instanceId broadcast instance identifier
+ * @param broadcastId broadcast instance identifier
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public void startBroadcast(int instanceId) {
- startBroadcastNative(instanceId);
+ public void startBroadcast(int broadcastId) {
+ startBroadcastNative(broadcastId);
}
/**
* Stop LeAudio Broadcast instance.
*
- * @param instanceId broadcast instance identifier
+ * @param broadcastId broadcast instance identifier
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public void stopBroadcast(int instanceId) {
- stopBroadcastNative(instanceId);
+ public void stopBroadcast(int broadcastId) {
+ stopBroadcastNative(broadcastId);
}
/**
* Pause LeAudio Broadcast instance.
*
- * @param instanceId broadcast instance identifier
+ * @param broadcastId broadcast instance identifier
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public void pauseBroadcast(int instanceId) {
- pauseBroadcastNative(instanceId);
+ public void pauseBroadcast(int broadcastId) {
+ pauseBroadcastNative(broadcastId);
}
/**
* Destroy LeAudio Broadcast instance.
*
- * @param instanceId broadcast instance identifier
- */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public void destroyBroadcast(int instanceId) {
- destroyBroadcastNative(instanceId);
- }
-
- /**
- * Get LeAudio Broadcast instance advertising address.
- *
- * @param instanceId broadcast instance identifier
+ * @param broadcastId broadcast instance identifier
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public void getBroadcastId(int instanceId) {
- getBroadcastIdNative(instanceId);
+ public void destroyBroadcast(int broadcastId) {
+ destroyBroadcastNative(broadcastId);
}
/**
@@ -250,11 +228,10 @@ public class LeAudioBroadcasterNativeInterface {
private native void stopNative();
private native void cleanupNative();
private native void createBroadcastNative(byte[] metadata, int profile, byte[] broadcastCode);
- private native void updateMetadataNative(int instanceId, byte[] metadata);
- private native void startBroadcastNative(int instanceId);
- private native void stopBroadcastNative(int instanceId);
- private native void pauseBroadcastNative(int instanceId);
- private native void destroyBroadcastNative(int instanceId);
- private native void getBroadcastIdNative(int instanceId);
+ private native void updateMetadataNative(int broadcastId, byte[] metadata);
+ private native void startBroadcastNative(int broadcastId);
+ private native void stopBroadcastNative(int broadcastId);
+ private native void pauseBroadcastNative(int broadcastId);
+ private native void destroyBroadcastNative(int broadcastId);
private native void getAllBroadcastStatesNative();
}
diff --git a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java
index 2ac32d6dee..0ba5d43ea3 100644
--- a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java
+++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java
@@ -61,7 +61,6 @@ import com.android.bluetooth.vc.VolumeControlService;
import com.android.internal.annotations.VisibleForTesting;
import com.android.modules.utils.SynchronousResultReceiver;
-import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -69,7 +68,6 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
-import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
/**
@@ -171,7 +169,6 @@ public class LeAudioService extends ProfileService {
private Handler mHandler = new Handler(Looper.getMainLooper());
private final Map<Integer, Integer> mBroadcastStateMap = new HashMap<>();
- final Map<Integer, Integer> mBroadcastIdMap = new HashMap<>();
private final Map<Integer, Boolean> mBroadcastsPlaybackMap = new HashMap<>();
private final List<BluetoothLeBroadcastMetadata> mBroadcastMetadataList = new ArrayList<>();
@@ -211,7 +208,6 @@ public class LeAudioService extends ProfileService {
mDeviceGroupIdMap.clear();
mDeviceAudioLocationMap.clear();
mBroadcastStateMap.clear();
- mBroadcastIdMap.clear();
mBroadcastMetadataList.clear();
mBroadcastsPlaybackMap.clear();
@@ -309,7 +305,6 @@ public class LeAudioService extends ProfileService {
}
mBroadcastStateMap.clear();
- mBroadcastIdMap.clear();
mBroadcastsPlaybackMap.clear();
mBroadcastMetadataList.clear();
@@ -591,76 +586,64 @@ public class LeAudioService extends ProfileService {
/**
* Start LeAudio Broadcast instance.
- * @param instanceId broadcast instance identifier
+ * @param broadcastId broadcast instance identifier
*/
- public void startBroadcast(int instanceId) {
+ public void startBroadcast(int broadcastId) {
if (mLeAudioBroadcasterNativeInterface == null) {
Log.w(TAG, "Native interface not available.");
return;
}
if (DBG) Log.d(TAG, "startBroadcast");
- mLeAudioBroadcasterNativeInterface.startBroadcast(instanceId);
+ mLeAudioBroadcasterNativeInterface.startBroadcast(broadcastId);
}
/**
* Updates LeAudio Broadcast instance metadata.
- * @param instanceId broadcast instance identifier
+ * @param broadcastId broadcast instance identifier
* @param metadata metadata for the default Broadcast subgroup
*/
- public void updateBroadcast(int instanceId, BluetoothLeAudioContentMetadata metadata) {
+ public void updateBroadcast(int broadcastId, BluetoothLeAudioContentMetadata metadata) {
if (mLeAudioBroadcasterNativeInterface == null) {
Log.w(TAG, "Native interface not available.");
return;
}
if (DBG) Log.d(TAG, "updateBroadcast");
- mLeAudioBroadcasterNativeInterface.updateMetadata(instanceId, metadata.getRawMetadata());
+ mLeAudioBroadcasterNativeInterface.updateMetadata(broadcastId, metadata.getRawMetadata());
}
/**
* Stop LeAudio Broadcast instance.
- * @param instanceId broadcast instance identifier
+ * @param broadcastId broadcast instance identifier
*/
- public void stopBroadcast(Integer instanceId) {
+ public void stopBroadcast(Integer broadcastId) {
if (mLeAudioBroadcasterNativeInterface == null) {
Log.w(TAG, "Native interface not available.");
return;
}
if (DBG) Log.d(TAG, "stopBroadcast");
- mLeAudioBroadcasterNativeInterface.stopBroadcast(instanceId);
+ mLeAudioBroadcasterNativeInterface.stopBroadcast(broadcastId);
}
/**
* Destroy LeAudio Broadcast instance.
- * @param instanceId broadcast instance identifier
+ * @param broadcastId broadcast instance identifier
*/
- public void destroyBroadcast(int instanceId) {
+ public void destroyBroadcast(int broadcastId) {
if (mLeAudioBroadcasterNativeInterface == null) {
Log.w(TAG, "Native interface not available.");
return;
}
if (DBG) Log.d(TAG, "destroyBroadcast");
- mLeAudioBroadcasterNativeInterface.destroyBroadcast(instanceId);
- }
-
- /**
- * Get LeAudio Broadcast id.
- * @param instanceId broadcast instance identifier
- */
- public void getBroadcastId(int instanceId) {
- if (mLeAudioBroadcasterNativeInterface == null) {
- Log.w(TAG, "Native interface not available.");
- return;
- }
- mLeAudioBroadcasterNativeInterface.getBroadcastId(instanceId);
+ mLeAudioBroadcasterNativeInterface.destroyBroadcast(broadcastId);
}
/**
* Checks if Broadcast instance is playing.
- * @param instanceId broadcast instance identifier
+ * @param broadcastId broadcast instance identifier
* @return true if if broadcast is playing, false otherwise
*/
- public boolean isPlaying(int instanceId) {
- return mBroadcastsPlaybackMap.getOrDefault(instanceId, false);
+ public boolean isPlaying(int broadcastId) {
+ return mBroadcastsPlaybackMap.getOrDefault(broadcastId, false);
}
/**
@@ -1138,55 +1121,37 @@ public class LeAudioService extends ProfileService {
}
} else if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_BROADCAST_CREATED) {
- int instanceId = stackEvent.valueInt1;
+ int broadcastId = stackEvent.valueInt1;
boolean success = stackEvent.valueBool1;
if (success) {
- Log.d(TAG, "Broadcast Instance id: " + instanceId + " created.");
- startBroadcast(instanceId);
- getBroadcastId(instanceId);
+ Log.d(TAG, "Broadcast broadcastId: " + broadcastId + " created.");
+ startBroadcast(broadcastId);
} else {
// TODO: Improve reason reporting or extend the native stack event with reason code
- notifyBroadcastStartFailed(instanceId, BluetoothStatusCodes.ERROR_UNKNOWN);
+ notifyBroadcastStartFailed(broadcastId, BluetoothStatusCodes.ERROR_UNKNOWN);
}
} else if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_BROADCAST_DESTROYED) {
- Integer instanceId = stackEvent.valueInt1;
+ Integer broadcastId = stackEvent.valueInt1;
// TODO: Improve reason reporting or extend the native stack event with reason code
- notifyOnBroadcastStopped(instanceId, BluetoothStatusCodes.REASON_LOCAL_APP_REQUEST);
+ notifyOnBroadcastStopped(broadcastId, BluetoothStatusCodes.REASON_LOCAL_APP_REQUEST);
- mBroadcastStateMap.remove(instanceId);
- mBroadcastsPlaybackMap.remove(instanceId);
- if (mBroadcastIdMap.containsKey(instanceId)) {
- Integer broadcastId = mBroadcastIdMap.get(instanceId);
- mBroadcastMetadataList.removeIf(m -> broadcastId == m.getBroadcastId());
- mBroadcastIdMap.remove(instanceId);
- }
+ mBroadcastsPlaybackMap.remove(broadcastId);
+ mBroadcastStateMap.remove(broadcastId);
+ mBroadcastMetadataList.removeIf(m -> broadcastId == m.getBroadcastId());
} else if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_BROADCAST_STATE) {
- int instanceId = stackEvent.valueInt1;
+ int broadcastId = stackEvent.valueInt1;
int state = stackEvent.valueInt2;
- mBroadcastStateMap.put(instanceId, state);
+ mBroadcastStateMap.put(broadcastId, state);
if (state == LeAudioStackEvent.BROADCAST_STATE_STOPPED) {
- if (DBG) Log.d(TAG, "Broadcast Instance id: " + instanceId + " stopped.");
- destroyBroadcast(instanceId);
+ if (DBG) Log.d(TAG, "Broadcast broadcastId: " + broadcastId + " stopped.");
- } else if (state == LeAudioStackEvent.BROADCAST_STATE_CONFIGURING) {
- if (DBG) Log.d(TAG, "Broadcast Instance id: " + instanceId + " configuring.");
-
- } else if (state == LeAudioStackEvent.BROADCAST_STATE_PAUSED) {
- if (DBG) Log.d(TAG, "Broadcast Instance id: " + instanceId + " paused.");
-
- if (!mBroadcastsPlaybackMap.containsKey(instanceId)) {
- // Initial playback state after the creation
- notifyBroadcastStarted(instanceId,
- BluetoothStatusCodes.REASON_LOCAL_APP_REQUEST);
- }
-
- // Playback paused
- mBroadcastsPlaybackMap.put(instanceId, false);
- notifyPlaybackStopped(instanceId, BluetoothStatusCodes.REASON_LOCAL_STACK_REQUEST);
+ // Playback stopped
+ mBroadcastsPlaybackMap.put(broadcastId, false);
+ notifyPlaybackStopped(broadcastId, BluetoothStatusCodes.REASON_LOCAL_APP_REQUEST);
// Notify audio manager
if (Collections.frequency(mBroadcastsPlaybackMap.values(), true) == 0) {
@@ -1196,24 +1161,36 @@ public class LeAudioService extends ProfileService {
mAudioManager.handleBluetoothActiveDeviceChanged(mActiveAudioOutDevice,
previousDevice,
// TODO: implement createLeAudioBroadcastInfo()
- BluetoothProfileConnectionInfo.createLeAudioInfo(true, true));
+ BluetoothProfileConnectionInfo.createLeAudioInfo(false, true));
}
}
+ destroyBroadcast(broadcastId);
+
+ } else if (state == LeAudioStackEvent.BROADCAST_STATE_CONFIGURING) {
+ if (DBG) Log.d(TAG, "Broadcast broadcastId: " + broadcastId + " configuring.");
+
+ } else if (state == LeAudioStackEvent.BROADCAST_STATE_PAUSED) {
+ if (DBG) Log.d(TAG, "Broadcast broadcastId: " + broadcastId + " paused.");
+
+ // Playback paused
+ mBroadcastsPlaybackMap.put(broadcastId, false);
+ notifyPlaybackStopped(broadcastId, BluetoothStatusCodes.REASON_LOCAL_STACK_REQUEST);
+
} else if (state == LeAudioStackEvent.BROADCAST_STATE_STOPPING) {
- if (DBG) Log.d(TAG, "Broadcast Instance id: " + instanceId + " stopping.");
+ if (DBG) Log.d(TAG, "Broadcast broadcastId: " + broadcastId + " stopping.");
} else if (state == LeAudioStackEvent.BROADCAST_STATE_STREAMING) {
- if (DBG) Log.d(TAG, "Broadcast Instance id: " + instanceId + " streaming.");
+ if (DBG) Log.d(TAG, "Broadcast broadcastId: " + broadcastId + " streaming.");
- if (!mBroadcastsPlaybackMap.containsKey(instanceId)) {
- notifyBroadcastStarted(instanceId,
+ if (!mBroadcastsPlaybackMap.containsKey(broadcastId)) {
+ notifyBroadcastStarted(broadcastId,
BluetoothStatusCodes.REASON_LOCAL_APP_REQUEST);
}
// Stream resumed
- mBroadcastsPlaybackMap.put(instanceId, true);
- notifyPlaybackStarted(instanceId, BluetoothStatusCodes.REASON_LOCAL_STACK_REQUEST);
+ mBroadcastsPlaybackMap.put(broadcastId, true);
+ notifyPlaybackStarted(broadcastId, BluetoothStatusCodes.REASON_LOCAL_STACK_REQUEST);
// Notify audio manager
if (Collections.frequency(mBroadcastsPlaybackMap.values(), true) == 1) {
@@ -1223,15 +1200,10 @@ public class LeAudioService extends ProfileService {
mAudioManager.handleBluetoothActiveDeviceChanged(mActiveAudioOutDevice,
previousDevice,
// TODO: implement createLeAudioBroadcastInfo()
- BluetoothProfileConnectionInfo.createLeAudioInfo(false, true));
+ BluetoothProfileConnectionInfo.createLeAudioInfo(true, true));
}
}
}
-
- } else if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_BROADCAST_ID) {
- int instanceId = stackEvent.valueInt1;
- byte[] broadcastId = stackEvent.valueByte1;
- mBroadcastIdMap.put(instanceId, new BigInteger(broadcastId).intValue());
}
// TODO: Support Broadcast metadata updates
@@ -1624,13 +1596,7 @@ public class LeAudioService extends ProfileService {
}
}
- private void notifyBroadcastStarted(Integer instanceId, int reason) {
- if (!mBroadcastIdMap.containsKey(instanceId)) {
- Log.e(TAG, "Unknown Broadcast ID for broadcast instance: " + instanceId);
- return;
- }
-
- Integer broadcastId = mBroadcastIdMap.get(instanceId);
+ private void notifyBroadcastStarted(Integer broadcastId, int reason) {
if (mBroadcastCallbacks != null) {
int n = mBroadcastCallbacks.beginBroadcast();
for (int i = 0; i < n; i++) {
@@ -1644,7 +1610,7 @@ public class LeAudioService extends ProfileService {
}
}
- private void notifyBroadcastStartFailed(Integer instanceId, int reason) {
+ private void notifyBroadcastStartFailed(Integer broadcastId, int reason) {
if (mBroadcastCallbacks != null) {
int n = mBroadcastCallbacks.beginBroadcast();
for (int i = 0; i < n; i++) {
@@ -1658,13 +1624,7 @@ public class LeAudioService extends ProfileService {
}
}
- private void notifyOnBroadcastStopped(Integer instanceId, int reason) {
- if (!mBroadcastIdMap.containsKey(instanceId)) {
- Log.e(TAG, "Unknown Broadcast ID for broadcast instance: " + instanceId);
- return;
- }
-
- Integer broadcastId = mBroadcastIdMap.get(instanceId);
+ private void notifyOnBroadcastStopped(Integer broadcastId, int reason) {
if (mBroadcastCallbacks != null) {
int n = mBroadcastCallbacks.beginBroadcast();
for (int i = 0; i < n; i++) {
@@ -1692,13 +1652,7 @@ public class LeAudioService extends ProfileService {
}
}
- private void notifyPlaybackStarted(Integer instanceId, int reason) {
- if (!mBroadcastIdMap.containsKey(instanceId)) {
- Log.e(TAG, "Unknown Broadcast ID for broadcast instance: " + instanceId);
- return;
- }
-
- Integer broadcastId = mBroadcastIdMap.get(instanceId);
+ private void notifyPlaybackStarted(Integer broadcastId, int reason) {
if (mBroadcastCallbacks != null) {
int n = mBroadcastCallbacks.beginBroadcast();
for (int i = 0; i < n; i++) {
@@ -1712,13 +1666,7 @@ public class LeAudioService extends ProfileService {
}
}
- private void notifyPlaybackStopped(Integer instanceId, int reason) {
- if (!mBroadcastIdMap.containsKey(instanceId)) {
- Log.e(TAG, "Unknown Broadcast ID for broadcast instance: " + instanceId);
- return;
- }
-
- Integer broadcastId = mBroadcastIdMap.get(instanceId);
+ private void notifyPlaybackStopped(Integer broadcastId, int reason) {
if (mBroadcastCallbacks != null) {
int n = mBroadcastCallbacks.beginBroadcast();
for (int i = 0; i < n; i++) {
@@ -1732,13 +1680,7 @@ public class LeAudioService extends ProfileService {
}
}
- private void notifyBroadcastUpdated(int instanceId, int reason) {
- if (!mBroadcastIdMap.containsKey(instanceId)) {
- Log.e(TAG, "Unknown Broadcast ID for broadcast instance: " + instanceId);
- return;
- }
-
- Integer broadcastId = mBroadcastIdMap.get(instanceId);
+ private void notifyBroadcastUpdated(int broadcastId, int reason) {
if (mBroadcastCallbacks != null) {
int n = mBroadcastCallbacks.beginBroadcast();
for (int i = 0; i < n; i++) {
@@ -1752,13 +1694,7 @@ public class LeAudioService extends ProfileService {
}
}
- private void notifyBroadcastUpdateFailed(int instanceId, int reason) {
- if (!mBroadcastIdMap.containsKey(instanceId)) {
- Log.e(TAG, "Unknown Broadcast ID for broadcast instance: " + instanceId);
- return;
- }
-
- Integer broadcastId = mBroadcastIdMap.get(instanceId);
+ private void notifyBroadcastUpdateFailed(int broadcastId, int reason) {
if (mBroadcastCallbacks != null) {
int n = mBroadcastCallbacks.beginBroadcast();
for (int i = 0; i < n; i++) {
@@ -1773,14 +1709,8 @@ public class LeAudioService extends ProfileService {
}
}
- private void notifyBroadcastMetadataChanged(int instanceId,
+ private void notifyBroadcastMetadataChanged(int broadcastId,
BluetoothLeBroadcastMetadata metadata) {
- if (!mBroadcastIdMap.containsKey(instanceId)) {
- Log.e(TAG, "Unknown Broadcast ID for broadcast instance: " + instanceId);
- return;
- }
-
- Integer broadcastId = mBroadcastIdMap.get(instanceId);
if (mBroadcastCallbacks != null) {
int n = mBroadcastCallbacks.beginBroadcast();
for (int i = 0; i < n; i++) {
@@ -2195,14 +2125,7 @@ public class LeAudioService extends ProfileService {
public void stopBroadcast(int broadcastId, AttributionSource source) {
LeAudioService service = getService(source);
if (service != null) {
- Optional<Integer> instanceId = service.mBroadcastIdMap.entrySet()
- .stream()
- .filter(entry -> Objects.equals(entry.getValue(), broadcastId))
- .map(Map.Entry::getKey)
- .findFirst();
- if (instanceId.isPresent()) {
- service.stopBroadcast(instanceId.get());
- }
+ service.stopBroadcast(broadcastId);
}
}
@@ -2211,14 +2134,7 @@ public class LeAudioService extends ProfileService {
BluetoothLeAudioContentMetadata contentMetadata, AttributionSource source) {
LeAudioService service = getService(source);
if (service != null) {
- Optional<Integer> instanceId = service.mBroadcastIdMap.entrySet()
- .stream()
- .filter(entry -> Objects.equals(entry.getValue(), broadcastId))
- .map(Map.Entry::getKey)
- .findFirst();
- if (instanceId.isPresent()) {
- service.updateBroadcast(instanceId.get(), contentMetadata);
- }
+ service.updateBroadcast(broadcastId, contentMetadata);
}
}
@@ -2229,14 +2145,7 @@ public class LeAudioService extends ProfileService {
boolean defaultValue = false;
LeAudioService service = getService(source);
if (service != null) {
- Optional<Integer> instanceId = service.mBroadcastIdMap.entrySet()
- .stream()
- .filter(entry -> Objects.equals(entry.getValue(), broadcastId))
- .map(Map.Entry::getKey)
- .findFirst();
- if (instanceId.isPresent()) {
- defaultValue = service.isPlaying(instanceId.get());
- }
+ defaultValue = service.isPlaying(broadcastId);
}
receiver.send(defaultValue);
} catch (RuntimeException e) {
diff --git a/android/app/src/com/android/bluetooth/le_audio/LeAudioStackEvent.java b/android/app/src/com/android/bluetooth/le_audio/LeAudioStackEvent.java
index b20b7790f9..1ddbdf10b3 100644
--- a/android/app/src/com/android/bluetooth/le_audio/LeAudioStackEvent.java
+++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioStackEvent.java
@@ -42,7 +42,6 @@ public class LeAudioStackEvent {
public static final int EVENT_TYPE_BROADCAST_CREATED = EVENT_TYPE_UNICAST_MAX + 1;
public static final int EVENT_TYPE_BROADCAST_DESTROYED = EVENT_TYPE_UNICAST_MAX + 2;
public static final int EVENT_TYPE_BROADCAST_STATE = EVENT_TYPE_UNICAST_MAX + 3;
- public static final int EVENT_TYPE_BROADCAST_ID = EVENT_TYPE_UNICAST_MAX + 4;
// Do not modify without updating the HAL bt_le_audio.h files.
// Match up with GroupStatus enum of bt_le_audio.h
@@ -73,7 +72,6 @@ public class LeAudioStackEvent {
public int valueInt4 = 0;
public int valueInt5 = 0;
public boolean valueBool1 = false;
- public byte[] valueByte1;
public BluetoothLeAudioCodecConfig valueCodec1;
public BluetoothLeAudioCodecConfig valueCodec2;
public List<BluetoothLeAudioCodecConfig> valueCodecList1;
@@ -101,7 +99,6 @@ public class LeAudioStackEvent {
+ eventTypeValueCodecList1ToString(type, valueCodecList1));
result.append(", valueCodecList2:"
+ eventTypeValueCodecList2ToString(type, valueCodecList2));
- result.append(", " + eventTypeValueByte1ToString(type, valueByte1));
result.append("}");
return result.toString();
}
@@ -126,8 +123,6 @@ public class LeAudioStackEvent {
return "EVENT_TYPE_BROADCAST_DESTROYED";
case EVENT_TYPE_BROADCAST_STATE:
return "EVENT_TYPE_BROADCAST_STATE";
- case EVENT_TYPE_BROADCAST_ID:
- return "EVENT_TYPE_BROADCAST_ID";
case EVENT_TYPE_AUDIO_LOCAL_CODEC_CONFIG_CAPA_CHANGED:
return "EVENT_TYPE_AUDIO_LOCAL_CODEC_CONFIG_CAPA_CHANGED";
case EVENT_TYPE_AUDIO_GROUP_CODEC_CONFIG_CHANGED:
@@ -164,13 +159,11 @@ public class LeAudioStackEvent {
case EVENT_TYPE_SINK_AUDIO_LOCATION_AVAILABLE:
return "{sink_audio_location:" + value + "}";
case EVENT_TYPE_BROADCAST_CREATED:
- return "{instance_id:" + value + "}";
+ return "{broadcastId:" + value + "}";
case EVENT_TYPE_BROADCAST_DESTROYED:
- return "{instance_id:" + value + "}";
+ return "{broadcastId:" + value + "}";
case EVENT_TYPE_BROADCAST_STATE:
- return "{instance_id:" + value + "}";
- case EVENT_TYPE_BROADCAST_ID:
- return "{instance_id:" + value + "}";
+ return "{broadcastId:" + value + "}";
default:
break;
}
@@ -202,8 +195,6 @@ public class LeAudioStackEvent {
return "{group_id:" + Integer.toString(value) + "}";
case EVENT_TYPE_BROADCAST_STATE:
return "{state:" + broadcastStateToString(value) + "}";
- case EVENT_TYPE_BROADCAST_ID:
- return "{addr_type:" + addrTypeToString(value) + "}";
default:
break;
}
@@ -242,18 +233,6 @@ public class LeAudioStackEvent {
return Integer.toString(value);
}
- private static String eventTypeValueByte1ToString(int type, byte[] value) {
- switch (type) {
- case EVENT_TYPE_BROADCAST_ID:
- if (value == null) {
- return "empty";
- }
- return "broadcast_id: [" + encodeHexString(value) + "]";
- default:
- return "<unused>";
- }
- }
-
private static String eventTypeValueBool1ToString(int type, boolean value) {
switch (type) {
case EVENT_TYPE_BROADCAST_CREATED:
@@ -324,17 +303,6 @@ public class LeAudioStackEvent {
}
}
- private static String addrTypeToString(int value) {
- switch (value) {
- case 0:
- return "Static";
- case 1:
- return "Random";
- default:
- return "Unknown {" + value + "}";
- }
- }
-
protected static String encodeHexString(byte[] pduData) {
StringBuilder out = new StringBuilder(pduData.length * 2);
for (int i = 0; i < pduData.length; i++) {
diff --git a/android/app/src/com/android/bluetooth/mcp/MediaControlProfile.java b/android/app/src/com/android/bluetooth/mcp/MediaControlProfile.java
index fb72a36c6a..9cf2ac75cd 100644
--- a/android/app/src/com/android/bluetooth/mcp/MediaControlProfile.java
+++ b/android/app/src/com/android/bluetooth/mcp/MediaControlProfile.java
@@ -751,7 +751,7 @@ public class MediaControlProfile implements MediaControlServiceCallbacks {
private final Map<String, MediaControlGattServiceInterface> mServiceMap;
- static final String THIS_PACKAGE_NAME = "com.android.bluetooth";
+ static final String THIS_PACKAGE_NAME = "com.android.bluetooth.services";
public void unregisterServiceInstance(String appToken) {
Log.d(TAG, "unregisterServiceInstance");
diff --git a/android/app/src/com/android/bluetooth/opp/Constants.java b/android/app/src/com/android/bluetooth/opp/Constants.java
index bb98752b74..c453a388d4 100644
--- a/android/app/src/com/android/bluetooth/opp/Constants.java
+++ b/android/app/src/com/android/bluetooth/opp/Constants.java
@@ -159,7 +159,7 @@ public class Constants {
/** the intent that gets sent when clicking a incoming file confirm notification */
static final String ACTION_INCOMING_FILE_CONFIRM = "android.btopp.intent.action.CONFIRM";
- static final String THIS_PACKAGE_NAME = "com.android.bluetooth";
+ static final String THIS_PACKAGE_NAME = "com.android.bluetooth.services";
/** The column that is used to remember whether the media scanner was invoked */
static final String MEDIA_SCANNED = "scanned";
diff --git a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapObexServer.java b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapObexServer.java
index 3f9ee0da61..92dce2a1d7 100755..100644
--- a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapObexServer.java
+++ b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapObexServer.java
@@ -93,7 +93,6 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
0x66
};
- // Currently not support SIM card
private static final String[] LEGAL_PATH = {
"/telecom",
"/telecom/pb",
@@ -101,16 +100,6 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
"/telecom/ich",
"/telecom/och",
"/telecom/mch",
- "/telecom/cch"
- };
-
- @SuppressWarnings("unused") private static final String[] LEGAL_PATH_WITH_SIM = {
- "/telecom",
- "/telecom/pb",
- "/telecom/fav",
- "/telecom/ich",
- "/telecom/och",
- "/telecom/mch",
"/telecom/cch",
"/SIM1",
"/SIM1/telecom",
@@ -157,6 +146,19 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
private static final String FAV_PATH = "/telecom/fav";
+ // SIM Support
+ private static final String SIM_PATH = "/SIM1/telecom";
+
+ private static final String SIM_ICH_PATH = "/SIM1/telecom/ich";
+
+ private static final String SIM_OCH_PATH = "/SIM1/telecom/och";
+
+ private static final String SIM_MCH_PATH = "/SIM1/telecom/mch";
+
+ private static final String SIM_CCH_PATH = "/SIM1/telecom/cch";
+
+ private static final String SIM_PB_PATH = "/SIM1/telecom/pb";
+
// type for list vcard objects
private static final String TYPE_LISTING = "x-bt/vcard-listing";
@@ -187,6 +189,8 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
private BluetoothPbapVcardManager mVcardManager;
+ BluetoothPbapSimVcardManager mVcardSimManager;
+
private int mOrderBy = ORDER_BY_INDEXED;
private static final int CALLLOG_NUM_LIMIT = 50;
@@ -209,6 +213,10 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
private PbapStateMachine mStateMachine;
+ private enum ContactsType {
+ TYPE_PHONEBOOK , TYPE_SIM ;
+ }
+
public static class ContentType {
public static final int PHONEBOOK = 1;
@@ -221,6 +229,8 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
public static final int COMBINED_CALL_HISTORY = 5;
public static final int FAVORITES = 6;
+
+ public static final int SIM_PHONEBOOK = 7;
}
public BluetoothPbapObexServer(Handler callback, Context context,
@@ -229,6 +239,7 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
mCallback = callback;
mContext = context;
mVcardManager = new BluetoothPbapVcardManager(mContext);
+ mVcardSimManager = new BluetoothPbapSimVcardManager(mContext);
mStateMachine = stateMachine;
}
@@ -452,21 +463,23 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
appParamValue.needTag = ContentType.PHONEBOOK;
} else if (mCurrentPath.equals(FAV_PATH)) {
appParamValue.needTag = ContentType.FAVORITES;
- } else if (mCurrentPath.equals(ICH_PATH)) {
+ } else if (mCurrentPath.equals(ICH_PATH) || mCurrentPath.equals(SIM_ICH_PATH)) {
appParamValue.needTag = ContentType.INCOMING_CALL_HISTORY;
- } else if (mCurrentPath.equals(OCH_PATH)) {
+ } else if (mCurrentPath.equals(OCH_PATH)|| mCurrentPath.equals(SIM_OCH_PATH)) {
appParamValue.needTag = ContentType.OUTGOING_CALL_HISTORY;
- } else if (mCurrentPath.equals(MCH_PATH)) {
+ } else if (mCurrentPath.equals(MCH_PATH)|| mCurrentPath.equals(SIM_MCH_PATH)) {
appParamValue.needTag = ContentType.MISSED_CALL_HISTORY;
mNeedNewMissedCallsNum = true;
- } else if (mCurrentPath.equals(CCH_PATH)) {
+ } else if (mCurrentPath.equals(CCH_PATH)|| mCurrentPath.equals(SIM_CCH_PATH)) {
appParamValue.needTag = ContentType.COMBINED_CALL_HISTORY;
- } else if (mCurrentPath.equals(TELECOM_PATH)) {
+ } else if (mCurrentPath.equals(TELECOM_PATH)|| mCurrentPath.equals(SIM_PATH)) {
/* PBAP 1.1.1 change */
if (!validName && type.equals(TYPE_LISTING)) {
Log.e(TAG, "invalid vcard listing request in default folder");
return ResponseCodes.OBEX_HTTP_NOT_FOUND;
}
+ } else if (mCurrentPath.equals(SIM_PB_PATH)) {
+ appParamValue.needTag = ContentType.SIM_PHONEBOOK;
} else {
Log.w(TAG, "mCurrentpath is not valid path!!!");
return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
@@ -475,16 +488,14 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
Log.v(TAG, "onGet(): appParamValue.needTag=" + appParamValue.needTag);
}
} else {
- // Not support SIM card currently
- if (name.contains(SIM1.subSequence(0, SIM1.length()))) {
- Log.w(TAG, "Not support access SIM card info!");
- return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
- }
-
// we have weak name checking here to provide better
// compatibility with other devices,although unique name such as
// "pb.vcf" is required by SIG spec.
- if (isNameMatchTarget(name, PB)) {
+ if (mVcardSimManager.isSimPhoneBook(name, type, PB, SIM1,
+ TYPE_PB, TYPE_LISTING, mCurrentPath)) {
+ appParamValue.needTag = ContentType.SIM_PHONEBOOK;
+ if (D) Log.d(TAG, "download SIM phonebook request");
+ } else if (isNameMatchTarget(name, PB)) {
appParamValue.needTag = ContentType.PHONEBOOK;
if (D) {
Log.v(TAG, "download phonebook request");
@@ -765,23 +776,32 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
result.append("<?xml version=\"1.0\"?>");
result.append("<!DOCTYPE vcard-listing SYSTEM \"vcard-listing.dtd\">");
result.append("<vCard-listing version=\"1.0\">");
-
+ String type = "";
// Phonebook listing request
if ((appParamValue.needTag == ContentType.PHONEBOOK)
|| (appParamValue.needTag == ContentType.FAVORITES)) {
- String type = "";
if (appParamValue.searchAttr.equals("0")) {
type = "name";
} else if (appParamValue.searchAttr.equals("1")) {
type = "number";
}
if (type.length() > 0) {
- itemsFound = createList(appParamValue, needSendBody, size, result, type);
+ itemsFound = createList(appParamValue, needSendBody, size, result, type,
+ ContactsType.TYPE_PHONEBOOK);
} else {
return ResponseCodes.OBEX_HTTP_PRECON_FAILED;
}
+ // SIM Phonebook listing Request
+ } else if (appParamValue.needTag == ContentType.SIM_PHONEBOOK) {
+ type = mVcardSimManager.getType(appParamValue.searchAttr);
+ if (type.length() > 0) {
+ itemsFound = createList(appParamValue, needSendBody, size, result, type,
+ ContactsType.TYPE_SIM);
+ } else {
+ return ResponseCodes.OBEX_HTTP_PRECON_FAILED;
+ }
+ // Call history listing request
} else {
- // Call history listing request
ArrayList<String> nameList = mVcardManager.loadCallHistoryList(appParamValue.needTag);
int requestSize =
nameList.size() >= appParamValue.maxListCount ? appParamValue.maxListCount
@@ -810,16 +830,24 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
}
private int createList(AppParamValue appParamValue, int needSendBody, int size,
- StringBuilder result, String type) {
+ StringBuilder result, String type, ContactsType contactType) {
int itemsFound = 0;
ArrayList<String> nameList = null;
if (mVcardSelector) {
- nameList = mVcardManager.getSelectedPhonebookNameList(mOrderBy, appParamValue.vcard21,
- needSendBody, size, appParamValue.vCardSelector,
+ if (contactType == ContactsType.TYPE_PHONEBOOK) {
+ nameList = mVcardManager.getSelectedPhonebookNameList(mOrderBy,
+ appParamValue.vcard21, needSendBody, size, appParamValue.vCardSelector,
appParamValue.vCardSelectorOperator);
+ } else if(contactType == ContactsType.TYPE_SIM) {
+ nameList = mVcardSimManager.getSIMPhonebookNameList(mOrderBy);
+ }
} else {
- nameList = mVcardManager.getPhonebookNameList(mOrderBy);
+ if (contactType == ContactsType.TYPE_PHONEBOOK) {
+ nameList = mVcardManager.getPhonebookNameList(mOrderBy);
+ } else if( contactType == ContactsType.TYPE_SIM) {
+ nameList = mVcardSimManager.getSIMPhonebookNameList(mOrderBy);
+ }
}
final int requestSize =
@@ -837,8 +865,12 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
ArrayList<Integer> savedPosList = new ArrayList<>();
ArrayList<String> selectedNameList = new ArrayList<String>();
// query the number, to get the names
- ArrayList<String> names =
- mVcardManager.getContactNamesByNumber(appParamValue.searchValue);
+ ArrayList<String> names = new ArrayList<>();
+ if (contactType == ContactsType.TYPE_PHONEBOOK) {
+ names = mVcardManager.getContactNamesByNumber(appParamValue.searchValue);
+ } else if(contactType== ContactsType.TYPE_SIM) {
+ names = mVcardSimManager.getSIMContactNamesByNumber(appParamValue.searchValue);
+ }
if (mOrderBy == ORDER_BY_ALPHABETICAL) Collections.sort(names);
for (int i = 0; i < names.size(); i++) {
compareValue = names.get(i).trim();
@@ -1134,7 +1166,7 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
Log.i(TAG, "searchAttr is valid: " + searchAttr);
}
- int size = mVcardManager.getPhonebookSize(appParamValue.needTag);
+ int size = mVcardManager.getPhonebookSize(appParamValue.needTag, mVcardSimManager);
int needSendBody = handleAppParaForResponse(appParamValue, size, reply, op, name);
if (needSendBody != NEED_SEND_BODY) {
op.noBodyHeader();
@@ -1198,7 +1230,7 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
}
}
- int size = mVcardManager.getPhonebookSize(appParamValue.needTag);
+ int size = mVcardManager.getPhonebookSize(appParamValue.needTag, mVcardSimManager);
int needSendBody = handleAppParaForResponse(appParamValue, size, reply, op, name);
if (size == 0) {
if (D) {
@@ -1225,6 +1257,19 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
return mVcardManager.composeAndSendPhonebookOneVcard(op, intIndex, vcard21, null,
mOrderBy, appParamValue.ignorefilter, appParamValue.propertySelector);
}
+ } else if (appParamValue.needTag == ContentType.SIM_PHONEBOOK) {
+ if (intIndex < 0 || intIndex >= size) {
+ Log.w(TAG, "The requested vcard is not acceptable! name= " + name);
+ return ResponseCodes.OBEX_HTTP_NOT_FOUND;
+ } else if (intIndex == 0) {
+ // For PB_PATH, 0.vcf is the phone number of this phone.
+ String ownerVcard = mVcardManager.getOwnerPhoneNumberVcard(vcard21,
+ appParamValue.ignorefilter ? null : appParamValue.propertySelector);
+ return pushBytes(op, ownerVcard);
+ } else {
+ return mVcardSimManager.composeAndSendSIMPhonebookOneVcard(op, intIndex,
+ vcard21, null, mOrderBy);
+ }
} else {
if (intIndex <= 0 || intIndex > size) {
Log.w(TAG, "The requested vcard is not acceptable! name= " + name);
@@ -1256,7 +1301,7 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
}
} // code end for passing PTS3.2 TC_PSE_PBD_BI_01_C
- int pbSize = mVcardManager.getPhonebookSize(appParamValue.needTag);
+ int pbSize = mVcardManager.getPhonebookSize(appParamValue.needTag, mVcardSimManager);
int needSendBody = handleAppParaForResponse(appParamValue, pbSize, reply, op, name);
if (needSendBody != NEED_SEND_BODY) {
op.noBodyHeader();
@@ -1299,7 +1344,8 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
// Limit the number of call log to CALLLOG_NUM_LIMIT
if ((appParamValue.needTag != BluetoothPbapObexServer.ContentType.PHONEBOOK)
- && (appParamValue.needTag != BluetoothPbapObexServer.ContentType.FAVORITES)) {
+ && (appParamValue.needTag != BluetoothPbapObexServer.ContentType.FAVORITES)
+ && (appParamValue.needTag != BluetoothPbapObexServer.ContentType.SIM_PHONEBOOK)) {
if (requestSize > CALLLOG_NUM_LIMIT) {
requestSize = CALLLOG_NUM_LIMIT;
}
@@ -1332,6 +1378,20 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
appParamValue.propertySelector, appParamValue.vCardSelector,
appParamValue.vCardSelectorOperator, mVcardSelector, favorites);
}
+ } else if (appParamValue.needTag == BluetoothPbapObexServer.ContentType.SIM_PHONEBOOK) {
+ if (startPoint == 0) {
+ String ownerVcard = mVcardManager.getOwnerPhoneNumberVcard(vcard21,
+ appParamValue.propertySelector);
+ if (endPoint == 0) {
+ return pushBytes(op, ownerVcard);
+ } else {
+ return mVcardSimManager.composeAndSendSIMPhonebookVcards(op, 1, endPoint,
+ vcard21, ownerVcard);
+ }
+ } else {
+ return mVcardSimManager.composeAndSendSIMPhonebookVcards(op, startPoint,
+ endPoint, vcard21, null);
+ }
} else {
return mVcardManager.composeAndSendSelectedCallLogVcards(appParamValue.needTag, op,
startPoint, endPoint, vcard21, needSendBody, pbSize,
diff --git a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapService.java b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapService.java
index 2fa5da0fc8..da36515e0c 100644
--- a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapService.java
+++ b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapService.java
@@ -86,7 +86,7 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect
public static final boolean DEBUG = true;
- public static final boolean VERBOSE = false;
+ public static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
/**
* Intent indicating incoming obex authentication request which is from
@@ -147,7 +147,7 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect
private static final int SDP_PBAP_SERVER_VERSION = 0x0102;
// PBAP v1.2.3, Sec. 7.1.2: local phonebook and favorites
- private static final int SDP_PBAP_SUPPORTED_REPOSITORIES = 0x0009;
+ private static final int SDP_PBAP_SUPPORTED_REPOSITORIES = 0x000B;
private static final int SDP_PBAP_SUPPORTED_FEATURES = 0x021F;
/* PBAP will use Bluetooth notification ID from 1000000 (included) to 2000000 (excluded).
diff --git a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManager.java b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManager.java
new file mode 100644
index 0000000000..267ce5bf28
--- /dev/null
+++ b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManager.java
@@ -0,0 +1,540 @@
+/*
+* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+* Copyright (C) 2014 Samsung System LSI
+* 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.
+*/
+package com.android.bluetooth.pbap;
+
+import com.android.bluetooth.R;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteException;
+import android.net.Uri;
+import com.android.vcard.VCardBuilder;
+import com.android.vcard.VCardConfig;
+import com.android.vcard.VCardConstants;
+import com.android.vcard.VCardUtils;
+
+import android.content.ContentValues;
+import android.provider.CallLog;
+import android.provider.CallLog.Calls;
+import android.text.TextUtils;
+import android.util.Log;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.CommonDataKinds;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Collections;
+import java.util.Comparator;
+
+import com.android.obex.Operation;
+import com.android.obex.ResponseCodes;
+import com.android.obex.ServerOperation;
+
+/**
+ * VCard composer especially for Call Log used in Bluetooth.
+ */
+public class BluetoothPbapSimVcardManager {
+ private static final String TAG = "PbapSIMvCardComposer";
+
+ private static final boolean V = BluetoothPbapService.VERBOSE;
+
+ private static final String FAILURE_REASON_FAILED_TO_GET_DATABASE_INFO =
+ "Failed to get database information";
+
+ private static final String FAILURE_REASON_NO_ENTRY =
+ "There's no exportable in the database";
+
+ private static final String FAILURE_REASON_NOT_INITIALIZED =
+ "The vCard composer object is not correctly initialized";
+
+ /** Should be visible only from developers... (no need to translate, hopefully) */
+ private static final String FAILURE_REASON_UNSUPPORTED_URI =
+ "The Uri vCard composer received is not supported by the composer.";
+
+ private static final String NO_ERROR = "No error";
+
+ private final String SIM_URI = "content://icc/adn";
+ private final String SIM_PATH = "/SIM1/telecom";
+
+ private static final String[] SIM_PROJECTION = new String[] {
+ Contacts.DISPLAY_NAME,
+ CommonDataKinds.Phone.NUMBER,
+ CommonDataKinds.Phone.TYPE,
+ CommonDataKinds.Phone.LABEL
+ };
+
+ private static final int NAME_COLUMN_INDEX = 0;
+ private static final int NUMBER_COLUMN_INDEX = 1;
+ private static final int NUMBERTYPE_COLUMN_INDEX = 2;
+ private static final int NUMBERLABEL_COLUMN_INDEX = 3;
+
+
+ private final Context mContext;
+ private ContentResolver mContentResolver;
+ private Cursor mCursor;
+ private boolean mTerminateIsCalled;
+ private String mErrorReason = NO_ERROR;
+
+ public BluetoothPbapSimVcardManager(final Context context) {
+ mContext = context;
+ mContentResolver = context.getContentResolver();
+ }
+
+ public boolean init(final Uri contentUri, final String selection,
+ final String[] selectionArgs, final String sortOrder) {
+ final Uri myUri = Uri.parse(SIM_URI);
+ if (!myUri.equals(contentUri)) {
+
+ mErrorReason = FAILURE_REASON_UNSUPPORTED_URI;
+ return false;
+ }
+
+ //checkpoint Figure out if we can apply selection, projection and sort order.
+ mCursor = mContentResolver.query(
+ contentUri, SIM_PROJECTION, null, null,sortOrder);
+
+ if (mCursor == null) {
+ mErrorReason = FAILURE_REASON_FAILED_TO_GET_DATABASE_INFO;
+ return false;
+ }
+ if (mCursor.getCount() == 0 || !mCursor.moveToFirst()) {
+ try {
+ mCursor.close();
+ } catch (SQLiteException e) {
+ Log.e(TAG, "SQLiteException on Cursor#close(): " + e.getMessage());
+ } finally {
+ mErrorReason = FAILURE_REASON_NO_ENTRY;
+ mCursor = null;
+ }
+ return false;
+ }
+ return true;
+ }
+
+ public String createOneEntry(boolean vcardVer21) {
+ if (mCursor == null || mCursor.isAfterLast()) {
+ mErrorReason = FAILURE_REASON_NOT_INITIALIZED;
+ return null;
+ }
+ try {
+ return createOnevCardEntryInternal(vcardVer21);
+ } finally {
+ mCursor.moveToNext();
+ }
+ }
+
+ private String createOnevCardEntryInternal(boolean vcardVer21) {
+ final int vcardType = (vcardVer21 ? VCardConfig.VCARD_TYPE_V21_GENERIC :
+ VCardConfig.VCARD_TYPE_V30_GENERIC) |
+ VCardConfig.FLAG_REFRAIN_PHONE_NUMBER_FORMATTING;
+ final VCardBuilder builder = new VCardBuilder(vcardType);
+ String name = mCursor.getString(NAME_COLUMN_INDEX);
+ if (TextUtils.isEmpty(name)) {
+ name = mCursor.getString(NUMBER_COLUMN_INDEX);
+ }
+ final boolean needCharset = !(VCardUtils.containsOnlyPrintableAscii(name));
+ // Create ContentValues for making name as Structured name
+ List<ContentValues> contentValuesList = new ArrayList<ContentValues>();
+ ContentValues nameContentValues = new ContentValues();
+ nameContentValues.put(StructuredName.DISPLAY_NAME, name);
+ contentValuesList.add(nameContentValues);
+ builder.appendNameProperties(contentValuesList);
+
+ String number = mCursor.getString(NUMBER_COLUMN_INDEX);
+ if (TextUtils.isEmpty(number)) {
+ // To avoid Spec violation and IOT issues, initialize with invalid number
+ number = "000000";
+ }
+ if (number.equals("-1")) {
+ number = mContext.getString(R.string.unknownNumber);
+ }
+
+ // checkpoint Figure out what are the type and label
+ int type = mCursor.getInt(NUMBERTYPE_COLUMN_INDEX);
+ String label = mCursor.getString(NUMBERLABEL_COLUMN_INDEX);
+ if (type == 0) { // value for type is not present in db
+ type = Phone.TYPE_MOBILE;
+ }
+ if (TextUtils.isEmpty(label)) {
+ label = Integer.toString(type);
+ }
+ builder.appendTelLine(type, label, number, false);
+ return builder.toString();
+ }
+
+ public void terminate() {
+ if (mCursor != null) {
+ try {
+ mCursor.close();
+ } catch (SQLiteException e) {
+ Log.e(TAG, "SQLiteException on Cursor#close(): " + e.getMessage());
+ }
+ mCursor = null;
+ }
+
+ mTerminateIsCalled = true;
+ }
+
+ @Override
+ public void finalize() {
+ if (!mTerminateIsCalled) {
+ terminate();
+ }
+ }
+
+ public int getCount() {
+ if (mCursor == null) {
+ return 0;
+ }
+ return mCursor.getCount();
+ }
+
+ public boolean isAfterLast() {
+ if (mCursor == null) {
+ return false;
+ }
+ return mCursor.isAfterLast();
+ }
+
+ public void moveToPosition(final int position, boolean sortalpha) {
+ if(mCursor == null) {
+ return;
+ }
+ if(sortalpha) {
+ setPositionByAlpha(position);
+ return;
+ }
+ mCursor.moveToPosition(position);
+ }
+
+ public String getErrorReason() {
+ return mErrorReason;
+ }
+
+ public void setPositionByAlpha(int position) {
+ if(mCursor == null) {
+ return;
+ }
+ ArrayList<String> nameList = new ArrayList<String>();
+ for (mCursor.moveToFirst(); !mCursor.isAfterLast(); mCursor
+ .moveToNext()) {
+ String name = mCursor.getString(NAME_COLUMN_INDEX);
+ if (TextUtils.isEmpty(name)) {
+ name = mContext.getString(android.R.string.unknownName);
+ }
+ nameList.add(name);
+ }
+
+ Collections.sort(nameList, new Comparator <String> () {
+ @Override
+ public int compare(String str1, String str2){
+ return str1.compareToIgnoreCase(str2);
+ }
+ });
+
+ for (mCursor.moveToFirst(); !mCursor.isAfterLast(); mCursor.moveToNext()) {
+ if(mCursor.getString(NAME_COLUMN_INDEX).equals(nameList.get(position))) {
+ break;
+ }
+
+ }
+ }
+
+ public final int getSIMContactsSize() {
+ final Uri myUri = Uri.parse(SIM_URI);
+ int size = 0;
+ Cursor contactCursor = null;
+ try {
+ contactCursor = mContentResolver.query(myUri, SIM_PROJECTION, null,null, null);
+ if (contactCursor != null) {
+ size = contactCursor.getCount() +1; //always has the 0.vcf
+ }
+ } finally {
+ if (contactCursor != null) {
+ contactCursor.close();
+ }
+ }
+ return size;
+ }
+
+ public final ArrayList<String> getSIMPhonebookNameList(final int orderByWhat) {
+ ArrayList<String> nameList = new ArrayList<String>();
+ nameList.add(BluetoothPbapService.getLocalPhoneName());
+ //Since owner card should always be 0.vcf, maintain a separate list to avoid sorting
+ ArrayList<String> allnames = new ArrayList<String>();
+ final Uri myUri = Uri.parse(SIM_URI);
+ Cursor contactCursor = null;
+ try {
+ contactCursor = mContentResolver.query(myUri, SIM_PROJECTION, null,null,null);
+ if (contactCursor != null) {
+ for (contactCursor.moveToFirst(); !contactCursor.isAfterLast(); contactCursor
+ .moveToNext()) {
+ String name = contactCursor.getString(NAME_COLUMN_INDEX);
+ if (TextUtils.isEmpty(name)) {
+ name = mContext.getString(android.R.string.unknownName);
+ }
+ allnames.add(name);
+ }
+ }
+ } finally {
+ if (contactCursor != null) {
+ contactCursor.close();
+ }
+ }
+ if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_INDEXED) {
+ if (V) Log.v(TAG, "getPhonebookNameList, order by index");
+ } else if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_ALPHABETICAL) {
+ if (V) Log.v(TAG, "getPhonebookNameList, order by alpha");
+ Collections.sort(allnames, new Comparator <String> () {
+ @Override
+ public int compare(String str1, String str2) {
+ return str1.compareToIgnoreCase(str2);
+ }
+ });
+ }
+
+ nameList.addAll(allnames);
+ return nameList;
+
+ }
+
+ public final ArrayList<String> getSIMContactNamesByNumber(
+ final String phoneNumber) {
+ ArrayList<String> nameList = new ArrayList<String>();
+ ArrayList<String> startNameList = new ArrayList<String>();
+ Cursor contactCursor = null;
+ final Uri uri = Uri.parse(SIM_URI);
+
+ try {
+ contactCursor = mContentResolver.query(uri, SIM_PROJECTION,
+ null, null, null);
+
+ if (contactCursor != null) {
+ for (contactCursor.moveToFirst(); !contactCursor.isAfterLast(); contactCursor
+ .moveToNext()) {
+ String number = contactCursor.getString(NUMBER_COLUMN_INDEX);
+ if (number == null) {
+ if (V) Log.v(TAG, "number is null");
+ continue;
+ }
+
+ if (V) Log.v(TAG, "number: " + number + " phoneNumber:" + phoneNumber);
+ if ((number.endsWith(phoneNumber)) || (number.startsWith(phoneNumber))) {
+ String name = contactCursor.getString(NAME_COLUMN_INDEX);
+ if (TextUtils.isEmpty(name)) {
+ name = mContext.getString(android.R.string.unknownName);
+ }
+ if (V) Log.v(TAG, "got name " + name + " by number " + phoneNumber);
+
+ if (number.endsWith(phoneNumber)) {
+ if (V) Log.v(TAG, "Adding to end name list");
+ nameList.add(name);
+ } else {
+ if (V) Log.v(TAG, "Adding to start name list");
+ startNameList.add(name);
+ }
+ }
+ }
+ }
+ } finally {
+ if (contactCursor != null) {
+ contactCursor.close();
+ }
+ }
+ int startListSize = startNameList.size();
+ for (int index = 0; index < startListSize; index++) {
+ String object = startNameList.get(index);
+ if (!nameList.contains(object))
+ nameList.add(object);
+ }
+
+ return nameList;
+ }
+
+ public final int composeAndSendSIMPhonebookVcards(Operation op,
+ final int startPoint, final int endPoint, final boolean vcardType21,
+ String ownerVCard) {
+ if (startPoint < 1 || startPoint > endPoint) {
+ Log.e(TAG, "internal error: startPoint or endPoint is not correct.");
+ return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
+ }
+ final Uri myUri = Uri.parse(SIM_URI);
+ BluetoothPbapSimVcardManager composer = null;
+ HandlerForStringBuffer buffer = null;
+ try {
+ composer = new BluetoothPbapSimVcardManager(mContext);
+ buffer = new HandlerForStringBuffer(op, ownerVCard);
+
+ if (!composer.init(myUri, null, null, null) || !buffer.onInit(mContext)) {
+ return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
+ }
+ composer.moveToPosition(startPoint -1, false);
+ for (int count =startPoint -1; count < endPoint; count++) {
+ if (BluetoothPbapObexServer.sIsAborted) {
+ ((ServerOperation)op).setAborted(true);
+ BluetoothPbapObexServer.sIsAborted = false;
+ break;
+ }
+ String vcard = composer.createOneEntry(vcardType21);
+ if (vcard == null) {
+ Log.e(TAG, "Failed to read a contact. Error reason: "
+ + composer.getErrorReason());
+ return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
+ }
+ buffer.onEntryCreated(vcard);
+ }
+ } finally {
+ if (composer != null) {
+ composer.terminate();
+ }
+ if (buffer != null) {
+ buffer.onTerminate();
+ }
+ }
+ return ResponseCodes.OBEX_HTTP_OK;
+ }
+
+ /**
+ * Handler to emit vCards to PCE.
+ */
+ public class HandlerForStringBuffer {
+ private Operation operation;
+
+ private OutputStream outputStream;
+
+ private String phoneOwnVCard = null;
+
+ public HandlerForStringBuffer(Operation op, String ownerVCard) {
+ operation = op;
+ if (ownerVCard != null) {
+ phoneOwnVCard = ownerVCard;
+ if (V) Log.v(TAG, "phoneOwnVCard \n " + phoneOwnVCard);
+ }
+ }
+
+ private boolean write(String vCard) {
+ try {
+ if (vCard != null) {
+ outputStream.write(vCard.getBytes());
+ return true;
+ }
+ } catch (IOException e) {
+ Log.e(TAG, "write outputstrem failed" + e.toString());
+ }
+ return false;
+ }
+
+ public boolean onInit(Context context) {
+ try {
+ outputStream = operation.openOutputStream();
+ if (phoneOwnVCard != null) {
+ return write(phoneOwnVCard);
+ }
+ return true;
+ } catch (IOException e) {
+ Log.e(TAG, "open outputstrem failed" + e.toString());
+ }
+ return false;
+ }
+
+ public boolean onEntryCreated(String vcard) {
+ return write(vcard);
+ }
+
+ public void onTerminate() {
+ if (!BluetoothPbapObexServer.closeStream(outputStream, operation)) {
+ if (V) Log.v(TAG, "CloseStream failed!");
+ } else {
+ if (V) Log.v(TAG, "CloseStream ok!");
+ }
+ }
+ }
+
+ public final int composeAndSendSIMPhonebookOneVcard(Operation op,
+ final int offset, final boolean vcardType21, String ownerVCard,
+ int orderByWhat) {
+ if (offset < 1) {
+ Log.e(TAG, "Internal error: offset is not correct.");
+ return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
+ }
+ final Uri myUri = Uri.parse(SIM_URI);
+ if (V) Log.v(TAG, "composeAndSendSIMPhonebookOneVcard orderByWhat " + orderByWhat);
+ BluetoothPbapSimVcardManager composer = null;
+ HandlerForStringBuffer buffer = null;
+ try {
+ composer = new BluetoothPbapSimVcardManager(mContext);
+ buffer = new HandlerForStringBuffer(op, ownerVCard);
+ if (!composer.init(myUri, null, null,null)||
+ !buffer.onInit(mContext)) {
+ return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
+ }
+ if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_INDEXED) {
+ composer.moveToPosition(offset -1, false);
+ } else if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_ALPHABETICAL) {
+ composer.moveToPosition(offset -1, true);
+ }
+ if (BluetoothPbapObexServer.sIsAborted) {
+ ((ServerOperation)op).setAborted(true);
+ BluetoothPbapObexServer.sIsAborted = false;
+ }
+ String vcard = composer.createOneEntry(vcardType21);
+ if (vcard == null) {
+ Log.e(TAG, "Failed to read a contact. Error reason: "
+ + composer.getErrorReason());
+ return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
+ }
+ buffer.onEntryCreated(vcard);
+ } finally {
+ if (composer != null) {
+ composer.terminate();
+ }
+ if (buffer != null) {
+ buffer.onTerminate();
+ }
+ }
+
+ return ResponseCodes.OBEX_HTTP_OK;
+ }
+
+ protected boolean isSimPhoneBook(String name, String type, String PB,
+ String SIM1, String TYPE_PB, String TYPE_LISTING, String mCurrentPath) {
+
+ return ((name.contains(PB.subSequence(0, PB.length()))
+ && name.contains(SIM1.subSequence(0,
+ SIM1.length())))
+ && (type.equals(TYPE_PB)))
+ || (((name.contains(
+ PB.subSequence(0, PB.length())))
+ && (mCurrentPath.equals(SIM_PATH)))
+ && (type.equals(TYPE_LISTING)));
+ }
+
+ protected String getType(String searchAttr) {
+ String type = "";
+ if (searchAttr.equals("0")) {
+ type = "name";
+ } else if (searchAttr.equals("1")) {
+ type = "number";
+ }
+ return type;
+ }
+}
diff --git a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java
index e968852771..b22713fc5e 100755..100644
--- a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java
+++ b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java
@@ -148,13 +148,17 @@ public class BluetoothPbapVcardManager {
return vcard;
}
- public final int getPhonebookSize(final int type) {
+ public final int getPhonebookSize(final int type,
+ BluetoothPbapSimVcardManager vCardSimManager) {
int size;
switch (type) {
case BluetoothPbapObexServer.ContentType.PHONEBOOK:
case BluetoothPbapObexServer.ContentType.FAVORITES:
size = getContactsSize(type);
break;
+ case BluetoothPbapObexServer.ContentType.SIM_PHONEBOOK:
+ size = vCardSimManager.getSIMContactsSize();
+ break;
default:
size = getCallHistorySize(type);
break;
diff --git a/android/app/tests/unit/AndroidManifest.xml b/android/app/tests/unit/AndroidManifest.xml
index cf50f48508..e1927e5402 100644
--- a/android/app/tests/unit/AndroidManifest.xml
+++ b/android/app/tests/unit/AndroidManifest.xml
@@ -61,11 +61,11 @@
</application>
<!--
This declares that this application uses the instrumentation test runner targeting
- the package of com.android.bluetooth. To run the tests use the command:
+ the package of com.android.bluetooth.services. To run the tests use the command:
"adb shell am instrument -w com.android.bluetooth.tests/android.test.InstrumentationTestRunner"
-->
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.bluetooth"
- android:label="Tests for com.android.bluetooth"/>
+ android:targetPackage="com.android.bluetooth.services"
+ android:label="Tests for com.android.bluetooth.services"/>
</manifest>
diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/storage/DatabaseManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/storage/DatabaseManagerTest.java
index eb046d832e..42498b47c0 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/btservice/storage/DatabaseManagerTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/storage/DatabaseManagerTest.java
@@ -381,6 +381,10 @@ public final class DatabaseManagerTest {
testSetGetCustomMetaCase(false,
BluetoothDevice.METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD,
value, true);
+ testSetGetCustomMetaCase(false, BluetoothDevice.METADATA_SPATIAL_AUDIO,
+ value, true);
+ testSetGetCustomMetaCase(false, BluetoothDevice.METADATA_FAST_PAIR_CUSTOMIZED_FIELDS,
+ value, true);
testSetGetCustomMetaCase(false, badKey, value, false);
// Device is in database
@@ -435,6 +439,10 @@ public final class DatabaseManagerTest {
testSetGetCustomMetaCase(true,
BluetoothDevice.METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD,
value, true);
+ testSetGetCustomMetaCase(true, BluetoothDevice.METADATA_SPATIAL_AUDIO,
+ value, true);
+ testSetGetCustomMetaCase(true, BluetoothDevice.METADATA_FAST_PAIR_CUSTOMIZED_FIELDS,
+ value, true);
}
@Test
@@ -1151,6 +1159,30 @@ public final class DatabaseManagerTest {
}
}
+ @Test
+ public void testDatabaseMigration_112_113() throws IOException {
+ // Create a database with version 112
+ SupportSQLiteDatabase db = testHelper.createDatabase(DB_NAME, 112);
+ // insert a device to the database
+ ContentValues device = new ContentValues();
+ device.put("address", TEST_BT_ADDR);
+ device.put("migrated", false);
+ assertThat(db.insert("metadata", SQLiteDatabase.CONFLICT_IGNORE, device),
+ CoreMatchers.not(-1));
+ // Migrate database from 112 to 113
+ db.close();
+ db = testHelper.runMigrationsAndValidate(DB_NAME, 113, true,
+ MetadataDatabase.MIGRATION_112_113);
+ Cursor cursor = db.query("SELECT * FROM metadata");
+ assertHasColumn(cursor, "spatial_audio", true);
+ assertHasColumn(cursor, "fastpair_customized", true);
+ while (cursor.moveToNext()) {
+ // Check the new columns was added with default value
+ assertColumnBlobData(cursor, "spatial_audio", null);
+ assertColumnBlobData(cursor, "fastpair_customized", null);
+ }
+ }
+
/**
* Helper function to check whether the database has the expected column
*/
diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/storage/schemas/com.android.bluetooth.btservice.storage.MetadataDatabase/113.json b/android/app/tests/unit/src/com/android/bluetooth/btservice/storage/schemas/com.android.bluetooth.btservice.storage.MetadataDatabase/113.json
new file mode 100644
index 0000000000..08c9ca145c
--- /dev/null
+++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/storage/schemas/com.android.bluetooth.btservice.storage.MetadataDatabase/113.json
@@ -0,0 +1,334 @@
+{
+ "formatVersion": 1,
+ "database": {
+ "version": 113,
+ "identityHash": "1949f73d922d80a81335edc130b9871d",
+ "entities": [
+ {
+ "tableName": "metadata",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`address` TEXT NOT NULL, `migrated` INTEGER NOT NULL, `a2dpSupportsOptionalCodecs` INTEGER NOT NULL, `a2dpOptionalCodecsEnabled` INTEGER NOT NULL, `last_active_time` INTEGER NOT NULL, `is_active_a2dp_device` INTEGER NOT NULL, `a2dp_connection_policy` INTEGER, `a2dp_sink_connection_policy` INTEGER, `hfp_connection_policy` INTEGER, `hfp_client_connection_policy` INTEGER, `hid_host_connection_policy` INTEGER, `pan_connection_policy` INTEGER, `pbap_connection_policy` INTEGER, `pbap_client_connection_policy` INTEGER, `map_connection_policy` INTEGER, `sap_connection_policy` INTEGER, `hearing_aid_connection_policy` INTEGER, `hap_client_connection_policy` INTEGER, `map_client_connection_policy` INTEGER, `le_audio_connection_policy` INTEGER, `volume_control_connection_policy` INTEGER, `csip_set_coordinator_connection_policy` INTEGER, `le_call_control_connection_policy` INTEGER, `bass_client_connection_policy` INTEGER, `battery_connection_policy` INTEGER, `manufacturer_name` BLOB, `model_name` BLOB, `software_version` BLOB, `hardware_version` BLOB, `companion_app` BLOB, `main_icon` BLOB, `is_untethered_headset` BLOB, `untethered_left_icon` BLOB, `untethered_right_icon` BLOB, `untethered_case_icon` BLOB, `untethered_left_battery` BLOB, `untethered_right_battery` BLOB, `untethered_case_battery` BLOB, `untethered_left_charging` BLOB, `untethered_right_charging` BLOB, `untethered_case_charging` BLOB, `enhanced_settings_ui_uri` BLOB, `device_type` BLOB, `main_battery` BLOB, `main_charging` BLOB, `main_low_battery_threshold` BLOB, `untethered_left_low_battery_threshold` BLOB, `untethered_right_low_battery_threshold` BLOB, `untethered_case_low_battery_threshold` BLOB, `spatial_audio` BLOB, `fastpair_customized` BLOB, PRIMARY KEY(`address`))",
+ "fields": [
+ {
+ "fieldPath": "address",
+ "columnName": "address",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "migrated",
+ "columnName": "migrated",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "a2dpSupportsOptionalCodecs",
+ "columnName": "a2dpSupportsOptionalCodecs",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "a2dpOptionalCodecsEnabled",
+ "columnName": "a2dpOptionalCodecsEnabled",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "last_active_time",
+ "columnName": "last_active_time",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "is_active_a2dp_device",
+ "columnName": "is_active_a2dp_device",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "profileConnectionPolicies.a2dp_connection_policy",
+ "columnName": "a2dp_connection_policy",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "profileConnectionPolicies.a2dp_sink_connection_policy",
+ "columnName": "a2dp_sink_connection_policy",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "profileConnectionPolicies.hfp_connection_policy",
+ "columnName": "hfp_connection_policy",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "profileConnectionPolicies.hfp_client_connection_policy",
+ "columnName": "hfp_client_connection_policy",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "profileConnectionPolicies.hid_host_connection_policy",
+ "columnName": "hid_host_connection_policy",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "profileConnectionPolicies.pan_connection_policy",
+ "columnName": "pan_connection_policy",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "profileConnectionPolicies.pbap_connection_policy",
+ "columnName": "pbap_connection_policy",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "profileConnectionPolicies.pbap_client_connection_policy",
+ "columnName": "pbap_client_connection_policy",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "profileConnectionPolicies.map_connection_policy",
+ "columnName": "map_connection_policy",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "profileConnectionPolicies.sap_connection_policy",
+ "columnName": "sap_connection_policy",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "profileConnectionPolicies.hearing_aid_connection_policy",
+ "columnName": "hearing_aid_connection_policy",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "profileConnectionPolicies.hap_client_connection_policy",
+ "columnName": "hap_client_connection_policy",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "profileConnectionPolicies.map_client_connection_policy",
+ "columnName": "map_client_connection_policy",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "profileConnectionPolicies.le_audio_connection_policy",
+ "columnName": "le_audio_connection_policy",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "profileConnectionPolicies.volume_control_connection_policy",
+ "columnName": "volume_control_connection_policy",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "profileConnectionPolicies.csip_set_coordinator_connection_policy",
+ "columnName": "csip_set_coordinator_connection_policy",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "profileConnectionPolicies.le_call_control_connection_policy",
+ "columnName": "le_call_control_connection_policy",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "profileConnectionPolicies.bass_client_connection_policy",
+ "columnName": "bass_client_connection_policy",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "profileConnectionPolicies.battery_connection_policy",
+ "columnName": "battery_connection_policy",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "publicMetadata.manufacturer_name",
+ "columnName": "manufacturer_name",
+ "affinity": "BLOB",
+ "notNull": false
+ },
+ {
+ "fieldPath": "publicMetadata.model_name",
+ "columnName": "model_name",
+ "affinity": "BLOB",
+ "notNull": false
+ },
+ {
+ "fieldPath": "publicMetadata.software_version",
+ "columnName": "software_version",
+ "affinity": "BLOB",
+ "notNull": false
+ },
+ {
+ "fieldPath": "publicMetadata.hardware_version",
+ "columnName": "hardware_version",
+ "affinity": "BLOB",
+ "notNull": false
+ },
+ {
+ "fieldPath": "publicMetadata.companion_app",
+ "columnName": "companion_app",
+ "affinity": "BLOB",
+ "notNull": false
+ },
+ {
+ "fieldPath": "publicMetadata.main_icon",
+ "columnName": "main_icon",
+ "affinity": "BLOB",
+ "notNull": false
+ },
+ {
+ "fieldPath": "publicMetadata.is_untethered_headset",
+ "columnName": "is_untethered_headset",
+ "affinity": "BLOB",
+ "notNull": false
+ },
+ {
+ "fieldPath": "publicMetadata.untethered_left_icon",
+ "columnName": "untethered_left_icon",
+ "affinity": "BLOB",
+ "notNull": false
+ },
+ {
+ "fieldPath": "publicMetadata.untethered_right_icon",
+ "columnName": "untethered_right_icon",
+ "affinity": "BLOB",
+ "notNull": false
+ },
+ {
+ "fieldPath": "publicMetadata.untethered_case_icon",
+ "columnName": "untethered_case_icon",
+ "affinity": "BLOB",
+ "notNull": false
+ },
+ {
+ "fieldPath": "publicMetadata.untethered_left_battery",
+ "columnName": "untethered_left_battery",
+ "affinity": "BLOB",
+ "notNull": false
+ },
+ {
+ "fieldPath": "publicMetadata.untethered_right_battery",
+ "columnName": "untethered_right_battery",
+ "affinity": "BLOB",
+ "notNull": false
+ },
+ {
+ "fieldPath": "publicMetadata.untethered_case_battery",
+ "columnName": "untethered_case_battery",
+ "affinity": "BLOB",
+ "notNull": false
+ },
+ {
+ "fieldPath": "publicMetadata.untethered_left_charging",
+ "columnName": "untethered_left_charging",
+ "affinity": "BLOB",
+ "notNull": false
+ },
+ {
+ "fieldPath": "publicMetadata.untethered_right_charging",
+ "columnName": "untethered_right_charging",
+ "affinity": "BLOB",
+ "notNull": false
+ },
+ {
+ "fieldPath": "publicMetadata.untethered_case_charging",
+ "columnName": "untethered_case_charging",
+ "affinity": "BLOB",
+ "notNull": false
+ },
+ {
+ "fieldPath": "publicMetadata.enhanced_settings_ui_uri",
+ "columnName": "enhanced_settings_ui_uri",
+ "affinity": "BLOB",
+ "notNull": false
+ },
+ {
+ "fieldPath": "publicMetadata.device_type",
+ "columnName": "device_type",
+ "affinity": "BLOB",
+ "notNull": false
+ },
+ {
+ "fieldPath": "publicMetadata.main_battery",
+ "columnName": "main_battery",
+ "affinity": "BLOB",
+ "notNull": false
+ },
+ {
+ "fieldPath": "publicMetadata.main_charging",
+ "columnName": "main_charging",
+ "affinity": "BLOB",
+ "notNull": false
+ },
+ {
+ "fieldPath": "publicMetadata.main_low_battery_threshold",
+ "columnName": "main_low_battery_threshold",
+ "affinity": "BLOB",
+ "notNull": false
+ },
+ {
+ "fieldPath": "publicMetadata.untethered_left_low_battery_threshold",
+ "columnName": "untethered_left_low_battery_threshold",
+ "affinity": "BLOB",
+ "notNull": false
+ },
+ {
+ "fieldPath": "publicMetadata.untethered_right_low_battery_threshold",
+ "columnName": "untethered_right_low_battery_threshold",
+ "affinity": "BLOB",
+ "notNull": false
+ },
+ {
+ "fieldPath": "publicMetadata.untethered_case_low_battery_threshold",
+ "columnName": "untethered_case_low_battery_threshold",
+ "affinity": "BLOB",
+ "notNull": false
+ },
+ {
+ "fieldPath": "publicMetadata.spatial_audio",
+ "columnName": "spatial_audio",
+ "affinity": "BLOB",
+ "notNull": false
+ },
+ {
+ "fieldPath": "publicMetadata.fastpair_customized",
+ "columnName": "fastpair_customized",
+ "affinity": "BLOB",
+ "notNull": false
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "address"
+ ],
+ "autoGenerate": false
+ },
+ "indices": [],
+ "foreignKeys": []
+ }
+ ],
+ "views": [],
+ "setupQueries": [
+ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
+ "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '1949f73d922d80a81335edc130b9871d')"
+ ]
+ }
+} \ No newline at end of file
diff --git a/android/blueberry/server/Android.bp b/android/blueberry/server/Android.bp
index 7d3d0b0658..1831b8f875 100644
--- a/android/blueberry/server/Android.bp
+++ b/android/blueberry/server/Android.bp
@@ -2,7 +2,7 @@ package {
default_applicable_licenses: ["Android-Apache-2.0"],
}
-android_test {
+android_test_helper_app {
name: "BlueberryServer",
srcs: ["src/**/*.kt"],
platform_apis: true,
@@ -29,6 +29,13 @@ android_test {
},
}
+android_test {
+ name: "pts-bot",
+ required: ["BlueberryServer"],
+ test_config: "configs/PtsBotTest.xml",
+ data: ["configs/pts_bot_tests_config.json"],
+}
+
java_library {
name: "blueberry-grpc-java",
visibility: ["//visibility:private"],
diff --git a/android/blueberry/server/configs/PtsBotTest.xml b/android/blueberry/server/configs/PtsBotTest.xml
new file mode 100644
index 0000000000..7ee909a909
--- /dev/null
+++ b/android/blueberry/server/configs/PtsBotTest.xml
@@ -0,0 +1,19 @@
+<configuration description="Runs PTS-bot tests">
+
+ <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="test-file-name" value="BlueberryServer.apk" />
+ <option name="install-arg" value="-r" />
+ <option name="install-arg" value="-g" />
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.InstallApkSetup">
+ <option name="post-install-cmd" value="am instrument -e Debug false com.android.blueberry/.Main" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.blueberry.PtsBotTest" >
+ <option name="mmi2grpc" value="empty" />
+ <option name="tests-config-file" value="pts_bot_tests_config.json" />
+ <option name="physical" value="false" />
+ <option name="profile" value="A2DP/SRC" />
+ </test>
+
+</configuration>
diff --git a/android/blueberry/server/configs/pts_bot_tests_config.json b/android/blueberry/server/configs/pts_bot_tests_config.json
new file mode 100644
index 0000000000..45153dfb5c
--- /dev/null
+++ b/android/blueberry/server/configs/pts_bot_tests_config.json
@@ -0,0 +1,179 @@
+{
+ "ics": {
+ "TSPC_A2DP_9_4": true,
+ "TSPC_A2DP_9_2": true,
+ "TSPC_A2DP_9_1": true,
+ "TSPC_A2DP_8_3": true,
+ "TSPC_A2DP_13_3": true,
+ "TSPC_A2DP_13_2": true,
+ "TSPC_A2DP_9_3": true,
+ "TSPC_A2DP_13_1": true,
+ "TSPC_A2DP_8_2": true,
+ "TSPC_A2DP_12_3": true,
+ "TSPC_A2DP_12_4": true,
+ "TSPC_A2DP_12_2": true,
+ "TSPC_A2DP_8_4": true,
+ "TSPC_A2DP_1_1": true,
+ "TSPC_A2DP_1_2": true,
+ "TSPC_A2DP_2a_3": true,
+ "TSPC_A2DP_2b_2": true,
+ "TSPC_A2DP_2_1": true,
+ "TSPC_A2DP_2_10": true,
+ "TSPC_A2DP_2_10a": true,
+ "TSPC_A2DP_2_13": true,
+ "TSPC_A2DP_2_2": true,
+ "TSPC_A2DP_2_3": true,
+ "TSPC_A2DP_2_4": true,
+ "TSPC_A2DP_2_5": true,
+ "TSPC_A2DP_2_6": true,
+ "TSPC_A2DP_2_7": true,
+ "TSPC_A2DP_2_8": true,
+ "TSPC_A2DP_2_9": true,
+ "TSPC_A2DP_3_1": true,
+ "TSPC_A2DP_3_1a": true,
+ "TSPC_A2DP_3a_1": true,
+ "TSPC_A2DP_3a_10": true,
+ "TSPC_A2DP_3a_11": true,
+ "TSPC_A2DP_3a_12": true,
+ "TSPC_A2DP_3a_2": true,
+ "TSPC_A2DP_3a_3": true,
+ "TSPC_A2DP_3a_4": true,
+ "TSPC_A2DP_3a_5": true,
+ "TSPC_A2DP_3a_6": true,
+ "TSPC_A2DP_3a_7": true,
+ "TSPC_A2DP_3a_8": true,
+ "TSPC_A2DP_3a_9": true,
+ "TSPC_A2DP_4_1": true,
+ "TSPC_A2DP_4_10": true,
+ "TSPC_A2DP_4_10a": true,
+ "TSPC_A2DP_4_13": true,
+ "TSPC_A2DP_4_15": true,
+ "TSPC_A2DP_4_2": true,
+ "TSPC_A2DP_4_3": false,
+ "TSPC_A2DP_4_4": true,
+ "TSPC_A2DP_4_5": true,
+ "TSPC_A2DP_4_6": true,
+ "TSPC_A2DP_4_7": true,
+ "TSPC_A2DP_4_8": false,
+ "TSPC_A2DP_4_9": true,
+ "TSPC_A2DP_7a_3": true,
+ "TSPC_A2DP_7b_2": true,
+ "TSPC_A2DP_5_1": true,
+ "TSPC_A2DP_5_1a": true,
+ "TSPC_A2DP_5a_1": true,
+ "TSPC_A2DP_5a_10": true,
+ "TSPC_A2DP_5a_11": true,
+ "TSPC_A2DP_5a_12": true,
+ "TSPC_A2DP_5a_2": true,
+ "TSPC_A2DP_5a_3": true,
+ "TSPC_A2DP_5a_4": true,
+ "TSPC_A2DP_5a_5": true,
+ "TSPC_A2DP_5a_6": true,
+ "TSPC_A2DP_5a_7": true,
+ "TSPC_A2DP_5a_8": true,
+ "TSPC_A2DP_5a_9": true,
+ "TSPC_AVDTP_1_1": true,
+ "TSPC_AVDTP_1_2": true,
+ "TSPC_AVDTP_1_3": true,
+ "TSPC_AVDTP_1_4": true,
+ "TSPC_AVDTP_16_1": true,
+ "TSPC_AVDTP_16_3": true,
+ "TSPC_AVDTP_2_1": true,
+ "TSPC_AVDTP_2_2": true,
+ "TSPC_AVDTP_2_3": true,
+ "TSPC_AVDTP_2_4": true,
+ "TSPC_AVDTP_2b_1": true,
+ "TSPC_AVDTP_2b_2": true,
+ "TSPC_AVDTP_2b_3": true,
+ "TSPC_AVDTP_2b_4": true,
+ "TSPC_AVDTP_3_1": true,
+ "TSPC_AVDTP_3_2": true,
+ "TSPC_AVDTP_3b_1": true,
+ "TSPC_AVDTP_3b_2": true,
+ "TSPC_AVDTP_4_1": true,
+ "TSPC_AVDTP_4_2": true,
+ "TSPC_AVDTP_4_3": true,
+ "TSPC_AVDTP_4_4": true,
+ "TSPC_AVDTP_4_5": false,
+ "TSPC_AVDTP_4_6": true,
+ "TSPC_AVDTP_4b_1": true,
+ "TSPC_AVDTP_4b_2": true,
+ "TSPC_AVDTP_4b_3": true,
+ "TSPC_AVDTP_4b_4": false,
+ "TSPC_AVDTP_4b_5": false,
+ "TSPC_AVDTP_4b_6": true,
+ "TSPC_AVDTP_5_1": true,
+ "TSPC_AVDTP_5_2": true,
+ "TSPC_AVDTP_5_3": true,
+ "TSPC_AVDTP_5_4": true,
+ "TSPC_AVDTP_5_5": true,
+ "TSPC_AVDTP_5b_1": true,
+ "TSPC_AVDTP_5b_2": false,
+ "TSPC_AVDTP_5b_3": true,
+ "TSPC_AVDTP_5b_4": false,
+ "TSPC_AVDTP_5b_5": true,
+ "TSPC_AVDTP_6b_1": true,
+ "TSPC_AVDTP_7_1": true,
+ "TSPC_AVDTP_7b_1": true,
+ "TSPC_AVDTP_10_1": true,
+ "TSPC_AVDTP_10_2": true,
+ "TSPC_AVDTP_10_3": true,
+ "TSPC_AVDTP_10_4": true,
+ "TSPC_AVDTP_10_5": true,
+ "TSPC_AVDTP_10_6": true,
+ "TSPC_AVDTP_10b_1": true,
+ "TSPC_AVDTP_10b_2": true,
+ "TSPC_AVDTP_10b_3": true,
+ "TSPC_AVDTP_10b_4": true,
+ "TSPC_AVDTP_10b_5": true,
+ "TSPC_AVDTP_10b_6": true,
+ "TSPC_AVDTP_11_1": true,
+ "TSPC_AVDTP_11_2": true,
+ "TSPC_AVDTP_11_3": true,
+ "TSPC_AVDTP_11_4": true,
+ "TSPC_AVDTP_11_5": true,
+ "TSPC_AVDTP_11_6": true,
+ "TSPC_AVDTP_11b_1": true,
+ "TSPC_AVDTP_11b_2": true,
+ "TSPC_AVDTP_11b_3": true,
+ "TSPC_AVDTP_11b_4": true,
+ "TSPC_AVDTP_11b_5": true,
+ "TSPC_AVDTP_11b_6": true,
+ "TSPC_AVDTP_12b_1": true,
+ "TSPC_AVDTP_13_1": true,
+ "TSPC_AVDTP_13b_1": true,
+ "TSPC_AVDTP_8_1": true,
+ "TSPC_AVDTP_8_2": true,
+ "TSPC_AVDTP_8_3": true,
+ "TSPC_AVDTP_8_4": true,
+ "TSPC_AVDTP_8b_1": true,
+ "TSPC_AVDTP_8b_2": true,
+ "TSPC_AVDTP_8b_3": true,
+ "TSPC_AVDTP_8b_4": true,
+ "TSPC_AVDTP_9_1": true,
+ "TSPC_AVDTP_9_2": true,
+ "TSPC_AVDTP_9b_1": true,
+ "TSPC_AVDTP_9b_2": true,
+ "TSPC_AVDTP_14_1": true,
+ "TSPC_AVDTP_14_6": true,
+ "TSPC_AVDTP_14a_3": true,
+ "TSPC_AVDTP_15_1": true,
+ "TSPC_AVDTP_15_6": false,
+ "TSPC_AVDTP_15a_3": true,
+ "TSPC_SUM ICS_31_22": true,
+ "TSPC_PROD_1_2": true,
+ "TSPC_PROD_3_1": true
+ },
+ "ixit": {"default": {}, "A2DP": {}, "AVDTP": {}},
+ "skip": [
+ "A2DP/SRC/SET/BV-05-I",
+ "A2DP/SRC/SET/BV-06-I",
+ "A2DP/SNK/SYN/BV-01-C",
+ "AVDTP/SRC/INT/SIG/SMG/BV-11-C",
+ "AVDTP/SRC/INT/SIG/SMG/BV-23-C",
+ "AVDTP/SNK/INT/SIG/SMG/BV-19-C",
+ "AVDTP/SNK/INT/SIG/SMG/BV-23-C",
+ "A2DP/SRC/CC/BV-09-I"
+ ]
+ }
+
diff --git a/android/blueberry/server/src/com/android/blueberry/Host.kt b/android/blueberry/server/src/com/android/blueberry/Host.kt
index 373cabbd20..433c75287c 100644
--- a/android/blueberry/server/src/com/android/blueberry/Host.kt
+++ b/android/blueberry/server/src/com/android/blueberry/Host.kt
@@ -76,7 +76,7 @@ class Host(private val context: Context, private val server: Server) : HostImplB
grpcUnary<Empty>(scope, responseObserver) {
Log.i(TAG, "reset")
- bluetoothAdapter.factoryReset()
+ bluetoothAdapter.clearBluetooth()
val stateFlow =
flow.filter { it.getAction() == BluetoothAdapter.ACTION_STATE_CHANGED }.map {
diff --git a/apex/Android.bp b/apex/Android.bp
index 46c5db7b4a..f3280eebf5 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -22,10 +22,19 @@ apex {
compile_multilib: "both",
+ prebuilts: [
+ "bluetooth-linker-config",
+ ],
key: "com.android.bluetooth.key",
certificate: ":com.android.bluetooth.certificate",
}
+linker_config {
+ name: "bluetooth-linker-config",
+ src: "linker.config.json",
+ installable: false,
+}
+
apex_key {
name: "com.android.bluetooth.key",
public_key: "com.android.bluetooth.avbpubkey",
diff --git a/apex/linker.config.json b/apex/linker.config.json
new file mode 100644
index 0000000000..7593c0234f
--- /dev/null
+++ b/apex/linker.config.json
@@ -0,0 +1,5 @@
+{
+ "permittedPaths": [
+ "/system_ext/${LIB}"
+ ]
+}
diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt
index aa75707efc..020955f866 100644
--- a/framework/api/system-current.txt
+++ b/framework/api/system-current.txt
@@ -54,11 +54,11 @@ package android.bluetooth {
public final class BluetoothAdapter {
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean addOnMetadataChangedListener(@NonNull android.bluetooth.BluetoothDevice, @NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.OnMetadataChangedListener);
+ method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean clearBluetooth();
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean disable(boolean);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disableBLE();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean enableBLE();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean enableNoAutoConnect();
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean factoryReset();
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void generateLocalOobData(int, @NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.OobDataCallback);
method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getActiveDevices(int);
method public int getConnectionState();
diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java
index 6b4c8062b6..c21ba6596e 100644
--- a/framework/java/android/bluetooth/BluetoothAdapter.java
+++ b/framework/java/android/bluetooth/BluetoothAdapter.java
@@ -1526,7 +1526,7 @@ public final class BluetoothAdapter {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
})
- public boolean factoryReset() {
+ public boolean clearBluetooth() {
try {
mServiceLock.readLock().lock();
if (mService != null) {
@@ -1548,6 +1548,22 @@ public final class BluetoothAdapter {
return false;
}
+ /**
+ * See {@link #clearBluetooth()}
+ *
+ * @return true to indicate that the config file was successfully cleared
+ * @hide
+ */
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
+ public boolean factoryReset() {
+ return clearBluetooth();
+ }
+
/**
* Get the UUIDs supported by the local Bluetooth adapter.
*
diff --git a/framework/java/android/bluetooth/BluetoothCodecConfig.java b/framework/java/android/bluetooth/BluetoothCodecConfig.java
index 4cbf956c24..d1fb561107 100644
--- a/framework/java/android/bluetooth/BluetoothCodecConfig.java
+++ b/framework/java/android/bluetooth/BluetoothCodecConfig.java
@@ -566,6 +566,17 @@ public final class BluetoothCodecConfig implements Parcelable {
* Returns the codec specific value1.
* As the value and usage differ for each codec, please refer to the concerned
* codec specification to obtain the codec specific information.
+ *
+ * <p>See section 4.3.2 of the Bluetooth A2dp specification for SBC codec specific
+ * information elements.
+ * <p>See section 4.4.2 of the Bluetooth A2dp specification for MPEG-1,2 Audio
+ * codec specific information elements.
+ * <p>See section 4.5.2 of the Bluetooth A2dp specification for MPEG-2, 4 AAC
+ * codec specific information elements.
+ * <p>See section 4.6.2 of the Bluetooth A2dp specification for ATRAC family
+ * codec specific information elements.
+ * <p>See section 4.7.2 of the Bluetooth A2dp specification for Vendor Specific A2DP
+ * codec specific information elements.
*/
public long getCodecSpecific1() {
return mCodecSpecific1;
@@ -575,6 +586,17 @@ public final class BluetoothCodecConfig implements Parcelable {
* Returns the codec specific value2.
* As the value and usage differ for each codec, please refer to the concerned
* codec specification to obtain the codec specific information.
+ *
+ * <p>See section 4.3.2 of the Bluetooth A2dp specification for SBC codec specific
+ * information elements.
+ * <p>See section 4.4.2 of the Bluetooth A2dp specification for MPEG-1,2 Audio
+ * codec specific information elements.
+ * <p>See section 4.5.2 of the Bluetooth A2dp specification for MPEG-2, 4 AAC
+ * codec specific information elements.
+ * <p>See section 4.6.2 of the Bluetooth A2dp specification for ATRAC family
+ * codec specific information elements.
+ * <p>See section 4.7.2 of the Bluetooth A2dp specification for Vendor Specific A2DP
+ * codec specific information elements.
*/
public long getCodecSpecific2() {
return mCodecSpecific2;
@@ -584,6 +606,17 @@ public final class BluetoothCodecConfig implements Parcelable {
* Returns the codec specific value3.
* As the value and usage differ for each codec, please refer to the concerned
* codec specification to obtain the codec specific information.
+ *
+ * <p>See section 4.3.2 of the Bluetooth A2dp specification for SBC codec specific
+ * information elements.
+ * <p>See section 4.4.2 of the Bluetooth A2dp specification for MPEG-1,2 Audio
+ * codec specific information elements.
+ * <p>See section 4.5.2 of the Bluetooth A2dp specification for MPEG-2, 4 AAC
+ * codec specific information elements.
+ * <p>See section 4.6.2 of the Bluetooth A2dp specification for ATRAC family
+ * codec specific information elements.
+ * <p>See section 4.7.2 of the Bluetooth A2dp specification for Vendor Specific A2DP
+ * codec specific information elements.
*/
public long getCodecSpecific3() {
return mCodecSpecific3;
@@ -593,6 +626,17 @@ public final class BluetoothCodecConfig implements Parcelable {
* Returns the codec specific value4.
* As the value and usage differ for each codec, please refer to the concerned
* codec specification to obtain the codec specific information.
+ *
+ * <p>See section 4.3.2 of the Bluetooth A2dp specification for SBC codec specific
+ * information elements.
+ * <p>See section 4.4.2 of the Bluetooth A2dp specification for MPEG-1,2 Audio
+ * codec specific information elements.
+ * <p>See section 4.5.2 of the Bluetooth A2dp specification for MPEG-2, 4 AAC
+ * codec specific information elements.
+ * <p>See section 4.6.2 of the Bluetooth A2dp specification for ATRAC family
+ * codec specific information elements.
+ * <p>See section 4.7.2 of the Bluetooth A2dp specification for Vendor Specific A2DP
+ * codec specific information elements.
*/
public long getCodecSpecific4() {
return mCodecSpecific4;
diff --git a/framework/java/android/bluetooth/BluetoothDevice.java b/framework/java/android/bluetooth/BluetoothDevice.java
index 5e674890b6..bf3d9697b0 100644
--- a/framework/java/android/bluetooth/BluetoothDevice.java
+++ b/framework/java/android/bluetooth/BluetoothDevice.java
@@ -652,7 +652,9 @@ public final class BluetoothDevice implements Parcelable, Attributable {
METADATA_MAIN_LOW_BATTERY_THRESHOLD,
METADATA_UNTETHERED_LEFT_LOW_BATTERY_THRESHOLD,
METADATA_UNTETHERED_RIGHT_LOW_BATTERY_THRESHOLD,
- METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD})
+ METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD,
+ METADATA_SPATIAL_AUDIO,
+ METADATA_FAST_PAIR_CUSTOMIZED_FIELDS})
@Retention(RetentionPolicy.SOURCE)
public @interface MetadataKey{}
@@ -862,6 +864,21 @@ public final class BluetoothDevice implements Parcelable, Attributable {
@SystemApi
public static final int METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD = 23;
+
+ /**
+ * The metadata of the audio spatial data.
+ * Data type should be {@link Byte} array.
+ * @hide
+ */
+ public static final int METADATA_SPATIAL_AUDIO = 24;
+
+ /**
+ * The metadata of the Fast Pair for any custmized feature.
+ * Data type should be {@link Byte} array.
+ * @hide
+ */
+ public static final int METADATA_FAST_PAIR_CUSTOMIZED_FIELDS = 25;
+
/**
* Device type which is used in METADATA_DEVICE_TYPE
* Indicates this Bluetooth device is a standard Bluetooth accessory or
@@ -3488,7 +3505,7 @@ public final class BluetoothDevice implements Parcelable, Attributable {
* @hide
*/
public static @MetadataKey int getMaxMetadataKey() {
- return METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD;
+ return METADATA_FAST_PAIR_CUSTOMIZED_FIELDS;
}
/**
diff --git a/framework/java/android/bluetooth/BluetoothHapClient.java b/framework/java/android/bluetooth/BluetoothHapClient.java
index dda803ef38..c05126d9c0 100644
--- a/framework/java/android/bluetooth/BluetoothHapClient.java
+++ b/framework/java/android/bluetooth/BluetoothHapClient.java
@@ -541,15 +541,19 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable
@NonNull Callback callback) {
Objects.requireNonNull(executor, "executor cannot be null");
Objects.requireNonNull(callback, "callback cannot be null");
- if (!isEnabled()) {
- throw new IllegalStateException("service not enabled");
- }
if (DBG) log("registerCallback");
synchronized (mCallbackExecutorMap) {
// If the callback map is empty, we register the service-to-app callback
if (mCallbackExecutorMap.isEmpty()) {
+ if (!isEnabled()) {
+ /* If Bluetooth is off, just store callback and it will be registered
+ * when Bluetooth is on
+ */
+ mCallbackExecutorMap.put(callback, executor);
+ return;
+ }
try {
final IBluetoothHapClient service = getService();
if (service != null) {
@@ -558,7 +562,7 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable
service.registerCallback(mCallback, mAttributionSource, recv);
recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
}
- } catch (IllegalStateException | TimeoutException e) {
+ } catch (TimeoutException e) {
Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
diff --git a/framework/java/android/bluetooth/BluetoothHeadset.java b/framework/java/android/bluetooth/BluetoothHeadset.java
index 9cbfe2971a..693b86608c 100644
--- a/framework/java/android/bluetooth/BluetoothHeadset.java
+++ b/framework/java/android/bluetooth/BluetoothHeadset.java
@@ -1001,7 +1001,6 @@ public final class BluetoothHeadset implements BluetoothProfile {
@Retention(RetentionPolicy.SOURCE)
@IntDef(value = {
BluetoothStatusCodes.SUCCESS,
- BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED,
BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND,
BluetoothStatusCodes.ERROR_TIMEOUT,
BluetoothStatusCodes.ERROR_UNKNOWN,
@@ -1013,7 +1012,6 @@ public final class BluetoothHeadset implements BluetoothProfile {
@IntDef(value = {
BluetoothStatusCodes.ALLOWED,
BluetoothStatusCodes.NOT_ALLOWED,
- BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED,
BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND,
BluetoothStatusCodes.ERROR_TIMEOUT,
BluetoothStatusCodes.ERROR_UNKNOWN,
@@ -1046,21 +1044,22 @@ public final class BluetoothHeadset implements BluetoothProfile {
Log.w(TAG, "Proxy not attached to service");
if (DBG) log(Log.getStackTraceString(new Throwable()));
return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
- } else if (!isEnabled()) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
- }
- try {
- final SynchronousResultReceiver recv = new SynchronousResultReceiver();
- service.setAudioRouteAllowed(allowed, mAttributionSource, recv);
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
- return BluetoothStatusCodes.SUCCESS;
- } catch (TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- return BluetoothStatusCodes.ERROR_TIMEOUT;
- } catch (RemoteException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- e.rethrowFromSystemServer();
+ } else if (isEnabled()) {
+ try {
+ final SynchronousResultReceiver recv = new SynchronousResultReceiver();
+ service.setAudioRouteAllowed(allowed, mAttributionSource, recv);
+ recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
+ return BluetoothStatusCodes.SUCCESS;
+ } catch (TimeoutException e) {
+ Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
+ return BluetoothStatusCodes.ERROR_TIMEOUT;
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
+ e.rethrowFromSystemServer();
+ }
}
+
+ Log.e(TAG, "setAudioRouteAllowed: Bluetooth disabled, but profile service still bound");
return BluetoothStatusCodes.ERROR_UNKNOWN;
}
@@ -1085,21 +1084,22 @@ public final class BluetoothHeadset implements BluetoothProfile {
Log.w(TAG, "Proxy not attached to service");
if (DBG) log(Log.getStackTraceString(new Throwable()));
return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
- } else if (!isEnabled()) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
- }
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.getAudioRouteAllowed(mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(false)
- ? BluetoothStatusCodes.ALLOWED : BluetoothStatusCodes.NOT_ALLOWED;
- } catch (TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- return BluetoothStatusCodes.ERROR_TIMEOUT;
- } catch (RemoteException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- e.rethrowFromSystemServer();
+ } else if (isEnabled()) {
+ try {
+ final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
+ service.getAudioRouteAllowed(mAttributionSource, recv);
+ return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(false)
+ ? BluetoothStatusCodes.ALLOWED : BluetoothStatusCodes.NOT_ALLOWED;
+ } catch (TimeoutException e) {
+ Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
+ return BluetoothStatusCodes.ERROR_TIMEOUT;
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
+ e.rethrowFromSystemServer();
+ }
}
+
+ Log.e(TAG, "getAudioRouteAllowed: Bluetooth disabled, but profile service still bound");
return BluetoothStatusCodes.ERROR_UNKNOWN;
}
@@ -1136,7 +1136,6 @@ public final class BluetoothHeadset implements BluetoothProfile {
BluetoothStatusCodes.ERROR_UNKNOWN,
BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND,
BluetoothStatusCodes.ERROR_TIMEOUT,
- BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED,
BluetoothStatusCodes.ERROR_AUDIO_DEVICE_ALREADY_CONNECTED,
BluetoothStatusCodes.ERROR_NO_ACTIVE_DEVICES,
BluetoothStatusCodes.ERROR_NOT_ACTIVE_DEVICE,
@@ -1186,9 +1185,10 @@ public final class BluetoothHeadset implements BluetoothProfile {
Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
return BluetoothStatusCodes.ERROR_TIMEOUT;
}
- } else {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
}
+
+ Log.e(TAG, "connectAudio: Bluetooth disabled, but profile service still bound");
+ return defaultValue;
}
/** @hide */
@@ -1198,7 +1198,6 @@ public final class BluetoothHeadset implements BluetoothProfile {
BluetoothStatusCodes.ERROR_UNKNOWN,
BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND,
BluetoothStatusCodes.ERROR_TIMEOUT,
- BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED,
BluetoothStatusCodes.ERROR_PROFILE_NOT_CONNECTED,
BluetoothStatusCodes.ERROR_AUDIO_DEVICE_ALREADY_DISCONNECTED
})
@@ -1241,9 +1240,10 @@ public final class BluetoothHeadset implements BluetoothProfile {
Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
return BluetoothStatusCodes.ERROR_TIMEOUT;
}
- } else {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
}
+
+ Log.e(TAG, "disconnectAudio: Bluetooth disabled, but profile service still bound");
+ return defaultValue;
}
/**
diff --git a/framework/java/android/bluetooth/BluetoothLeAudio.java b/framework/java/android/bluetooth/BluetoothLeAudio.java
index 6d416434b2..9d77125271 100644
--- a/framework/java/android/bluetooth/BluetoothLeAudio.java
+++ b/framework/java/android/bluetooth/BluetoothLeAudio.java
@@ -960,9 +960,8 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable {
service.registerCallback(mCallback, mAttributionSource, recv);
recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
}
- } catch (IllegalStateException | TimeoutException e) {
+ } catch (TimeoutException e) {
Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- throw new IllegalStateException("Unexpected error", e);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcast.java b/framework/java/android/bluetooth/BluetoothLeBroadcast.java
index 58f794f2d6..38a8b34a89 100644
--- a/framework/java/android/bluetooth/BluetoothLeBroadcast.java
+++ b/framework/java/android/bluetooth/BluetoothLeBroadcast.java
@@ -425,15 +425,19 @@ public final class BluetoothLeBroadcast implements AutoCloseable, BluetoothProfi
@NonNull Callback callback) {
Objects.requireNonNull(executor, "executor cannot be null");
Objects.requireNonNull(callback, "callback cannot be null");
- if (!isEnabled()) {
- throw new IllegalStateException("service not enabled");
- }
if (DBG) log("registerCallback");
synchronized (mCallbackExecutorMap) {
// If the callback map is empty, we register the service-to-app callback
if (mCallbackExecutorMap.isEmpty()) {
+ if (!mAdapter.isEnabled()) {
+ /* If Bluetooth is off, just store callback and it will be registered
+ * when Bluetooth is on
+ */
+ mCallbackExecutorMap.put(callback, executor);
+ return;
+ }
try {
final IBluetoothLeAudio service = getService();
if (service != null) {
@@ -442,7 +446,7 @@ public final class BluetoothLeBroadcast implements AutoCloseable, BluetoothProfi
service.registerLeBroadcastCallback(mCallback, mAttributionSource, recv);
recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
}
- } catch (TimeoutException | IllegalStateException e) {
+ } catch (TimeoutException e) {
Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
diff --git a/framework/java/android/bluetooth/BluetoothVolumeControl.java b/framework/java/android/bluetooth/BluetoothVolumeControl.java
index a359c91206..080b9a6d64 100644
--- a/framework/java/android/bluetooth/BluetoothVolumeControl.java
+++ b/framework/java/android/bluetooth/BluetoothVolumeControl.java
@@ -344,6 +344,13 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose
synchronized (mCallbackExecutorMap) {
// If the callback map is empty, we register the service-to-app callback
if (mCallbackExecutorMap.isEmpty()) {
+ if (!mAdapter.isEnabled()) {
+ /* If Bluetooth is off, just store callback and it will be registered
+ * when Bluetooth is on
+ */
+ mCallbackExecutorMap.put(callback, executor);
+ return;
+ }
try {
final IBluetoothVolumeControl service = getService();
if (service != null) {
@@ -355,7 +362,7 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose
} catch (RemoteException e) {
Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
throw e.rethrowFromSystemServer();
- } catch (IllegalStateException | TimeoutException e) {
+ } catch (TimeoutException e) {
Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
}
}
diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java
index 6a1c28beb0..f02432679a 100644
--- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java
+++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java
@@ -229,6 +229,7 @@ public class BluetoothManagerService extends IBluetoothManager.Stub {
// used inside handler thread
private boolean mQuietEnable = false;
private boolean mEnable;
+ private boolean mShutdownInProgress = false;
private static CharSequence timeToLog(long timestamp) {
return android.text.format.DateFormat.format("MM-dd HH:mm:ss", timestamp);
@@ -490,6 +491,23 @@ public class BluetoothManagerService extends IBluetoothManager.Stub {
Log.i(TAG, "Device disconnected, reactivating pending flag changes");
onInitFlagsChanged();
}
+ } else if (action.equals(Intent.ACTION_SHUTDOWN)) {
+ Log.i(TAG, "Device is shutting down.");
+ mShutdownInProgress = true;
+ mBluetoothLock.readLock().lock();
+ try {
+ mEnable = false;
+ mEnableExternal = false;
+ if (mBluetooth != null && (mState == BluetoothAdapter.STATE_BLE_ON)) {
+ synchronousOnBrEdrDown(mContext.getAttributionSource());
+ } else if (mBluetooth != null && (mState == BluetoothAdapter.STATE_ON)) {
+ synchronousDisable(mContext.getAttributionSource());
+ }
+ } catch (RemoteException | TimeoutException e) {
+ Log.e(TAG, "Unable to shutdown Bluetooth", e);
+ } finally {
+ mBluetoothLock.readLock().unlock();
+ }
}
}
};
@@ -547,6 +565,7 @@ public class BluetoothManagerService extends IBluetoothManager.Stub {
filter.addAction(Intent.ACTION_SETTING_RESTORED);
filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
filter.addAction(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
+ filter.addAction(Intent.ACTION_SHUTDOWN);
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
mContext.registerReceiver(mReceiver, filter);
@@ -2083,6 +2102,11 @@ public class BluetoothManagerService extends IBluetoothManager.Stub {
case MESSAGE_ENABLE:
int quietEnable = msg.arg1;
int isBle = msg.arg2;
+ if (mShutdownInProgress) {
+ Log.d(TAG, "Skip Bluetooth Enable in device shutdown process");
+ break;
+ }
+
if (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED)
|| mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)) {
if (msg.arg2 == 0) {
@@ -3274,7 +3298,7 @@ public class BluetoothManagerService extends IBluetoothManager.Stub {
*/
private void updateOppLauncherComponentState(UserHandle userHandle,
boolean bluetoothSharingDisallowed) {
- final ComponentName oppLauncherComponent = new ComponentName("com.android.bluetooth",
+ final ComponentName oppLauncherComponent = new ComponentName("com.android.bluetooth.services",
"com.android.bluetooth.opp.BluetoothOppLauncherActivity");
final int newState =
bluetoothSharingDisallowed ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED
diff --git a/system/audio_hal_interface/aidl/le_audio_software_aidl.cc b/system/audio_hal_interface/aidl/le_audio_software_aidl.cc
index 5c946d2bbd..8ba16279d1 100644
--- a/system/audio_hal_interface/aidl/le_audio_software_aidl.cc
+++ b/system/audio_hal_interface/aidl/le_audio_software_aidl.cc
@@ -433,10 +433,9 @@ std::vector<AudioSetConfiguration> get_offload_capabilities() {
if (hal_ucast_capability_to_stack_format(hal_encode_cap, encode_cap)) {
audio_set_config.confs.push_back(SetConfiguration(
- ::le_audio::types::kLeAudioDirectionSink,
- ::le_audio::types::kTargetLatencyBalancedLatencyReliability,
- hal_encode_cap.deviceCount,
+ ::le_audio::types::kLeAudioDirectionSink, hal_encode_cap.deviceCount,
hal_encode_cap.deviceCount * hal_encode_cap.channelCountPerDevice,
+ ::le_audio::types::kTargetLatencyBalancedLatencyReliability,
encode_cap));
str_capability_log = " Encode Capability: " + hal_encode_cap.toString();
}
@@ -444,9 +443,9 @@ std::vector<AudioSetConfiguration> get_offload_capabilities() {
if (hal_ucast_capability_to_stack_format(hal_decode_cap, decode_cap)) {
audio_set_config.confs.push_back(SetConfiguration(
::le_audio::types::kLeAudioDirectionSource,
- ::le_audio::types::kTargetLatencyBalancedLatencyReliability,
hal_decode_cap.deviceCount,
hal_decode_cap.deviceCount * hal_decode_cap.channelCountPerDevice,
+ ::le_audio::types::kTargetLatencyBalancedLatencyReliability,
decode_cap));
str_capability_log += " Decode Capability: " + hal_decode_cap.toString();
}
diff --git a/system/blueberry/tests/gd/cert/gd_device.py b/system/blueberry/tests/gd/cert/gd_device.py
index 4674905842..8074c52433 100644
--- a/system/blueberry/tests/gd/cert/gd_device.py
+++ b/system/blueberry/tests/gd/cert/gd_device.py
@@ -527,7 +527,9 @@ class GdAndroidDevice(GdDeviceBase):
# Ensure Bluetooth is disabled
self.ensure_no_output(self.adb.shell("settings put global ble_scan_always_enabled 0"))
- self.ensure_no_output(self.adb.shell("svc bluetooth disable"))
+ self.adb.shell("cmd bluetooth_manager disable")
+ device_bt_state = int(self.adb.shell("settings get global bluetooth_on"))
+ asserts.assert_equal(device_bt_state, 0, "Failed to disable Bluetooth on device %s %s" % (self.label, self.serial_number))
logging.info("Bluetooth disabled on device %s %s" % (self.label, self.serial_number))
# Start logcat logging
@@ -771,12 +773,15 @@ class GdAndroidDevice(GdDeviceBase):
# sys.boot_completed.
while time.time() < timeout_start + timeout:
try:
+ logging.debug("waiting for device %s to turn off", self.serial_number)
self.adb.get_state()
+ logging.debug("device %s not turned off yet", self.serial_number)
time.sleep(.1)
except AdbError:
# get_state will raise an error if the device is not found. We
# want the device to be missing to prove the device has kicked
# off the reboot.
+ logging.debug("device %s is turned off, waiting for it to boot", self.serial_number)
break
minutes_left = timeout_minutes - (time.time() - timeout_start) / 60.0
self.wait_for_boot_completion(timeout_minutes=minutes_left)
diff --git a/system/bta/dm/bta_dm_act.cc b/system/bta/dm/bta_dm_act.cc
index bf385f8617..ba90f8a720 100644
--- a/system/bta/dm/bta_dm_act.cc
+++ b/system/bta/dm/bta_dm_act.cc
@@ -3200,7 +3200,8 @@ void bta_dm_eir_update_uuid(uint16_t uuid16, bool adding) {
} else {
LOG_INFO("EIR Removing UUID=0x%04X from extended inquiry response", uuid16);
- BTM_RemoveEirService(bta_dm_cb.eir_uuid, uuid16);
+ get_btm_client_interface().eir.BTM_RemoveEirService(bta_dm_cb.eir_uuid,
+ uuid16);
}
bta_dm_set_eir(NULL);
diff --git a/system/bta/dm/bta_dm_pm.cc b/system/bta/dm/bta_dm_pm.cc
index 6a7d6577d6..204017c06d 100644
--- a/system/bta/dm/bta_dm_pm.cc
+++ b/system/bta/dm/bta_dm_pm.cc
@@ -57,7 +57,7 @@ static void bta_dm_pm_stop_timer_by_index(tBTA_PM_TIMER* p_timer,
/* BTA_DM_PM_SSR1 will be dedicated for HH SSR setting entry, no other profile
* can use it */
#define BTA_DM_PM_SSR_HH BTA_DM_PM_SSR1
-static void bta_dm_pm_ssr(const RawAddress& peer_addr, int ssr);
+static void bta_dm_pm_ssr(const RawAddress& peer_addr, const int ssr);
tBTA_DM_CONNECTED_SRVCS bta_dm_conn_srvcs;
static std::recursive_mutex pm_timer_schedule_mutex;
@@ -759,10 +759,9 @@ void bta_dm_pm_sniff(tBTA_DM_PEER_DEVICE* p_peer_dev, uint8_t index) {
* Returns void
*
******************************************************************************/
-static void bta_dm_pm_ssr(const RawAddress& peer_addr, int ssr) {
- int current_ssr_index;
+static void bta_dm_pm_ssr(const RawAddress& peer_addr, const int ssr) {
int ssr_index = ssr;
- tBTA_DM_SSR_SPEC* p_spec = &p_bta_dm_ssr_spec[ssr_index];
+ tBTA_DM_SSR_SPEC* p_spec = &p_bta_dm_ssr_spec[ssr];
LOG_DEBUG("Request to put link to device:%s into power_mode:%s",
PRIVATE_ADDRESS(peer_addr), p_spec->name);
@@ -773,6 +772,7 @@ static void bta_dm_pm_ssr(const RawAddress& peer_addr, int ssr) {
continue;
}
/* p_bta_dm_pm_cfg[0].app_id is the number of entries */
+ int current_ssr_index = BTA_DM_PM_SSR0;
for (int j = 1; j <= p_bta_dm_pm_cfg[0].app_id; j++) {
/* find the associated p_bta_dm_pm_cfg */
const tBTA_DM_PM_CFG& config = p_bta_dm_pm_cfg[j];
diff --git a/system/bta/has/has_client.cc b/system/bta/has/has_client.cc
index 044713437f..875a41c2a1 100644
--- a/system/bta/has/has_client.cc
+++ b/system/bta/has/has_client.cc
@@ -395,7 +395,7 @@ class HasClientImpl : public HasClient {
}
auto op = op_opt.value();
- if (op.opcode == PresetCtpOpcode::READ_PRESET_BY_INDEX) {
+ if (op.opcode == PresetCtpOpcode::READ_PRESETS) {
callbacks_->OnPresetInfoError(device->addr, op.index,
GattStatus2SvcErrorCode(status));
@@ -588,7 +588,7 @@ class HasClientImpl : public HasClient {
if (status != ErrorCode::NO_ERROR) {
switch (operation.opcode) {
- case PresetCtpOpcode::READ_PRESET_BY_INDEX:
+ case PresetCtpOpcode::READ_PRESETS:
LOG_ASSERT(
std::holds_alternative<RawAddress>(operation.addr_or_group))
<< " Unsupported group operation!";
@@ -837,8 +837,8 @@ class HasClientImpl : public HasClient {
.available = preset->IsAvailable(),
.preset_name = preset->GetName()}});
} else {
- CpPresetIndexOperation(HasCtpOp(
- address, PresetCtpOpcode::READ_PRESET_BY_INDEX, preset_index));
+ CpPresetIndexOperation(
+ HasCtpOp(address, PresetCtpOpcode::READ_PRESETS, preset_index));
}
}
@@ -849,7 +849,7 @@ class HasClientImpl : public HasClient {
CpWritePresetNameOperation(HasCtpOp(addr_or_group_id,
PresetCtpOpcode::WRITE_PRESET_NAME,
- preset_index, name));
+ preset_index, 1 /* Don't care */, name));
}
void CleanUp() {
@@ -1662,8 +1662,9 @@ class HasClientImpl : public HasClient {
ccc_val);
/* Get all the presets */
- CpReadAllPresetsOperation(
- HasCtpOp(device->addr, PresetCtpOpcode::READ_ALL_PRESETS));
+ CpReadAllPresetsOperation(HasCtpOp(
+ device->addr, PresetCtpOpcode::READ_PRESETS,
+ le_audio::has::kStartPresetIndex, le_audio::has::kMaxNumOfPresets));
/* Read the current active preset index */
BtaGattQueue::ReadCharacteristic(
diff --git a/system/bta/has/has_client_test.cc b/system/bta/has/has_client_test.cc
index 571686981c..0c28ad7476 100644
--- a/system/bta/has/has_client_test.cc
+++ b/system/bta/has/has_client_test.cc
@@ -319,7 +319,7 @@ class HasClientTestBase : public ::testing::Test {
void* cb_data) {
auto pp = value.data();
auto len = value.size();
- uint8_t op, index;
+ uint8_t op, index, num_of_indices;
const bool indicate = false;
@@ -344,25 +344,21 @@ class HasClientTestBase : public ::testing::Test {
}
switch (static_cast<::le_audio::has::PresetCtpOpcode>(op)) {
- case ::le_audio::has::PresetCtpOpcode::READ_ALL_PRESETS:
- ASSERT_EQ(0u, len);
- InjectNotifyReadPresetsResponse(conn_id, address, handle, value,
- indicate, -1, cb, cb_data);
- break;
-
- case ::le_audio::has::PresetCtpOpcode::READ_PRESET_BY_INDEX:
- if (len < 1) {
+ case ::le_audio::has::PresetCtpOpcode::READ_PRESETS:
+ if (len < 2) {
if (cb)
cb(conn_id, GATT_INVALID_ATTR_LEN, handle, value.size(),
value.data(), cb_data);
} else {
STREAM_TO_UINT8(index, pp);
- --len;
+ STREAM_TO_UINT8(num_of_indices, pp);
+ len -= 2;
ASSERT_EQ(0u, len);
InjectNotifyReadPresetsResponse(conn_id, address, handle, value,
- indicate, index, cb, cb_data);
+ indicate, index, num_of_indices,
+ cb, cb_data);
}
break;
@@ -949,38 +945,43 @@ class HasClientTestBase : public ::testing::Test {
value, indicate);
}
- void InjectNotifyReadPresetsResponse(uint16_t conn_id,
- RawAddress const& address,
- uint16_t handle,
- std::vector<uint8_t> value,
- bool indicate, int index,
- GATT_WRITE_OP_CB cb, void* cb_data) {
+ void InjectNotifyReadPresetsResponse(
+ uint16_t conn_id, RawAddress const& address, uint16_t handle,
+ std::vector<uint8_t> value, bool indicate, int index, int num_of_indices,
+ GATT_WRITE_OP_CB cb, void* cb_data) {
auto presets = current_peer_presets_.at(conn_id);
LOG_ASSERT(!presets.empty()) << __func__ << " Mocking error!";
- if (index == -1) {
+ /* Index is a start index, not necessary is a valid index for the
+ * peer device */
+ auto preset = presets.find(index);
+ while (preset == presets.end() &&
+ index++ <= ::le_audio::has::kMaxNumOfPresets) {
+ preset = presets.find(index);
+ }
+
+ if (preset == presets.end()) {
+ /* operation not possible */
if (cb)
- cb(conn_id, GATT_SUCCESS, handle, value.size(), value.data(), cb_data);
- /* Notify all presets */
- for (auto preset = presets.begin(); preset != presets.end(); preset++) {
- InjectNotifyReadPresetResponse(conn_id, address, handle, *preset,
- indicate,
- (preset == std::prev(presets.end())));
- }
- } else {
- auto preset = presets.find(index);
- if (preset != presets.end()) {
- if (cb)
- cb(conn_id, GATT_SUCCESS, handle, value.size(), value.data(),
- cb_data);
- InjectNotifyReadPresetResponse(conn_id, address, handle, *preset,
- indicate, true);
- } else {
- /* operation not possible */
- if (cb)
- cb(conn_id, (tGATT_STATUS)0x83, handle, value.size(), value.data(),
- cb_data);
- }
+ cb(conn_id, (tGATT_STATUS)0x83, handle, value.size(), value.data(),
+ cb_data);
+
+ return;
+ }
+
+ if (cb)
+ cb(conn_id, GATT_SUCCESS, handle, value.size(), value.data(), cb_data);
+ /* Notify presets */
+ int num_of_notif = 1;
+ while (1) {
+ bool last =
+ preset == std::prev(presets.end()) || num_of_notif == num_of_indices;
+ InjectNotifyReadPresetResponse(conn_id, address, handle, *preset,
+ indicate, (last));
+ if (last) return;
+
+ num_of_notif++;
+ preset++;
}
}
@@ -3023,8 +3024,7 @@ TEST_F(HasTypesTest, test_group_op_coordinator_init) {
EXPECT_CALL(*AlarmMock::Get(), AlarmNew(_)).Times(1);
HasCtpGroupOpCoordinator wrapper(
{address1, address2},
- HasCtpOp(0x01, ::le_audio::has::PresetCtpOpcode::READ_PRESET_BY_INDEX,
- 6));
+ HasCtpOp(0x01, ::le_audio::has::PresetCtpOpcode::READ_PRESETS, 6));
ASSERT_EQ(2u, wrapper.ref_cnt);
EXPECT_CALL(*AlarmMock::Get(), AlarmFree(_)).Times(1);
@@ -3043,12 +3043,10 @@ TEST_F(HasTypesTest, test_group_op_coordinator_copy) {
EXPECT_CALL(*AlarmMock::Get(), AlarmNew(_)).Times(1);
HasCtpGroupOpCoordinator wrapper(
{address1, address2},
- HasCtpOp(0x01, ::le_audio::has::PresetCtpOpcode::READ_PRESET_BY_INDEX,
- 6));
+ HasCtpOp(0x01, ::le_audio::has::PresetCtpOpcode::READ_PRESETS, 6));
HasCtpGroupOpCoordinator wrapper2(
{address1},
- HasCtpOp(0x01, ::le_audio::has::PresetCtpOpcode::READ_PRESET_BY_INDEX,
- 6));
+ HasCtpOp(0x01, ::le_audio::has::PresetCtpOpcode::READ_PRESETS, 6));
ASSERT_EQ(3u, wrapper.ref_cnt);
HasCtpGroupOpCoordinator wrapper3 = wrapper2;
auto* wrapper4 =
@@ -3076,12 +3074,10 @@ TEST_F(HasTypesTest, test_group_op_coordinator_completion) {
EXPECT_CALL(*AlarmMock::Get(), AlarmNew(_)).Times(1);
HasCtpGroupOpCoordinator wrapper(
{address1, address3},
- HasCtpOp(0x01, ::le_audio::has::PresetCtpOpcode::READ_PRESET_BY_INDEX,
- 6));
+ HasCtpOp(0x01, ::le_audio::has::PresetCtpOpcode::READ_PRESETS, 6));
HasCtpGroupOpCoordinator wrapper2(
{address2},
- HasCtpOp(0x01, ::le_audio::has::PresetCtpOpcode::READ_PRESET_BY_INDEX,
- 6));
+ HasCtpOp(0x01, ::le_audio::has::PresetCtpOpcode::READ_PRESETS, 6));
ASSERT_EQ(3u, wrapper.ref_cnt);
EXPECT_CALL(*AlarmMock::Get(), AlarmFree(_)).Times(0);
diff --git a/system/bta/has/has_ctp.cc b/system/bta/has/has_ctp.cc
index 1b88dcadfb..940a494df8 100644
--- a/system/bta/has/has_ctp.cc
+++ b/system/bta/has/has_ctp.cc
@@ -138,14 +138,14 @@ std::vector<uint8_t> HasCtpOp::ToCharacteristicValue() const {
auto* pp = value.data();
switch (opcode) {
- case PresetCtpOpcode::READ_ALL_PRESETS:
- value.resize(1);
+ case PresetCtpOpcode::READ_PRESETS:
+ value.resize(3);
pp = value.data();
UINT8_TO_STREAM(
pp, static_cast<std::underlying_type_t<PresetCtpOpcode>>(opcode));
+ UINT8_TO_STREAM(pp, index);
+ UINT8_TO_STREAM(pp, num_of_indices);
break;
-
- case PresetCtpOpcode::READ_PRESET_BY_INDEX:
case PresetCtpOpcode::SET_ACTIVE_PRESET:
case PresetCtpOpcode::SET_ACTIVE_PRESET_SYNC:
value.resize(2);
@@ -206,8 +206,7 @@ std::ostream& operator<<(std::ostream& out, const PresetCtpChangeId value) {
std::ostream& operator<<(std::ostream& out, const PresetCtpOpcode value) {
const char* ch = 0;
switch (value) {
- CASE_SET_PTR_TO_TOKEN_STR(PresetCtpOpcode::READ_ALL_PRESETS);
- CASE_SET_PTR_TO_TOKEN_STR(PresetCtpOpcode::READ_PRESET_BY_INDEX);
+ CASE_SET_PTR_TO_TOKEN_STR(PresetCtpOpcode::READ_PRESETS);
CASE_SET_PTR_TO_TOKEN_STR(PresetCtpOpcode::READ_PRESET_RESPONSE);
CASE_SET_PTR_TO_TOKEN_STR(PresetCtpOpcode::PRESET_CHANGED);
CASE_SET_PTR_TO_TOKEN_STR(PresetCtpOpcode::WRITE_PRESET_NAME);
diff --git a/system/bta/has/has_ctp.h b/system/bta/has/has_ctp.h
index 38cfe45514..963a23c7b1 100644
--- a/system/bta/has/has_ctp.h
+++ b/system/bta/has/has_ctp.h
@@ -41,8 +41,7 @@ std::ostream& operator<<(std::ostream& out, const PresetCtpChangeId value);
/* HAS control point Opcodes */
enum class PresetCtpOpcode : uint8_t {
- READ_ALL_PRESETS = 0,
- READ_PRESET_BY_INDEX,
+ READ_PRESETS = 1,
READ_PRESET_RESPONSE,
PRESET_CHANGED,
WRITE_PRESET_NAME,
@@ -67,8 +66,7 @@ static constexpr uint16_t PresetCtpOpcode2Bitmask(PresetCtpOpcode op) {
/* Mandatory opcodes if control point characteristic exists */
static constexpr uint16_t kControlPointMandatoryOpcodesBitmask =
- PresetCtpOpcode2Bitmask(PresetCtpOpcode::READ_ALL_PRESETS) |
- PresetCtpOpcode2Bitmask(PresetCtpOpcode::READ_PRESET_BY_INDEX) |
+ PresetCtpOpcode2Bitmask(PresetCtpOpcode::READ_PRESETS) |
PresetCtpOpcode2Bitmask(PresetCtpOpcode::SET_ACTIVE_PRESET) |
PresetCtpOpcode2Bitmask(PresetCtpOpcode::SET_NEXT_PRESET) |
PresetCtpOpcode2Bitmask(PresetCtpOpcode::SET_PREV_PRESET);
@@ -100,13 +98,19 @@ struct HasCtpOp {
std::variant<RawAddress, int> addr_or_group;
PresetCtpOpcode opcode;
uint8_t index;
+ uint8_t num_of_indices;
std::optional<std::string> name;
uint16_t op_id;
HasCtpOp(std::variant<RawAddress, int> addr_or_group_id, PresetCtpOpcode op,
uint8_t index = bluetooth::has::kHasPresetIndexInvalid,
+ uint8_t num_of_indices = 1,
std::optional<std::string> name = std::nullopt)
- : addr_or_group(addr_or_group_id), opcode(op), index(index), name(name) {
+ : addr_or_group(addr_or_group_id),
+ opcode(op),
+ index(index),
+ num_of_indices(num_of_indices),
+ name(name) {
/* Skip 0 on roll-over */
last_op_id_ += 1;
if (last_op_id_ == 0) last_op_id_ = 1;
diff --git a/system/bta/has/has_types.h b/system/bta/has/has_types.h
index d726f07cf7..e7d691deab 100644
--- a/system/bta/has/has_types.h
+++ b/system/bta/has/has_types.h
@@ -70,15 +70,17 @@ union HasGattOpContext {
static_assert(sizeof(HasGattOpContext) <= sizeof(void*));
/* Service UUIDs */
-/* FIXME: actually these were not yet assigned - using placeholders for now. */
static const bluetooth::Uuid kUuidHearingAccessService =
bluetooth::Uuid::From16Bit(0x1854);
static const bluetooth::Uuid kUuidHearingAidFeatures =
- bluetooth::Uuid::From16Bit(0xEEED);
+ bluetooth::Uuid::From16Bit(0x2BDA);
static const bluetooth::Uuid kUuidHearingAidPresetControlPoint =
- bluetooth::Uuid::From16Bit(0xEEEC);
+ bluetooth::Uuid::From16Bit(0x2BDB);
static const bluetooth::Uuid kUuidActivePresetIndex =
- bluetooth::Uuid::From16Bit(0xEEEB);
+ bluetooth::Uuid::From16Bit(0x2BDC);
+
+static const uint8_t kStartPresetIndex = 1;
+static const uint8_t kMaxNumOfPresets = 255;
/* Base device class for the GATT-based service clients */
class GattServiceDevice {
diff --git a/system/bta/include/bta_le_audio_broadcaster_api.h b/system/bta/include/bta_le_audio_broadcaster_api.h
index 33022ef19b..e3ffa28d2d 100644
--- a/system/bta/include/bta_le_audio_broadcaster_api.h
+++ b/system/bta/include/bta_le_audio_broadcaster_api.h
@@ -49,17 +49,16 @@ class LeAudioBroadcaster {
std::vector<uint8_t> metadata, AudioProfile profile,
std::optional<bluetooth::le_audio::BroadcastCode> broadcast_code =
std::nullopt) = 0;
- virtual void SuspendAudioBroadcast(uint8_t instance_id) = 0;
- virtual void StartAudioBroadcast(uint8_t instance_id) = 0;
- virtual void StopAudioBroadcast(uint8_t instance_id) = 0;
- virtual void DestroyAudioBroadcast(uint8_t instance_id) = 0;
- virtual void GetBroadcastId(uint8_t instance_id) = 0;
+ virtual void SuspendAudioBroadcast(uint32_t broadcast_id) = 0;
+ virtual void StartAudioBroadcast(uint32_t broadcast_id) = 0;
+ virtual void StopAudioBroadcast(uint32_t broadcast_id) = 0;
+ virtual void DestroyAudioBroadcast(uint32_t broadcast_id) = 0;
virtual void GetAllBroadcastStates(void) = 0;
- virtual void UpdateMetadata(uint8_t instance_id,
+ virtual void UpdateMetadata(uint32_t broadcast_id,
std::vector<uint8_t> metadata) = 0;
virtual void IsValidBroadcast(
- uint8_t instance_id, uint8_t addr_type, RawAddress addr,
- base::Callback<void(uint8_t /* instance_id */, uint8_t /* addr_type */,
+ uint32_t broadcast_id, uint8_t addr_type, RawAddress addr,
+ base::Callback<void(uint8_t /* broadcast_id */, uint8_t /* addr_type */,
RawAddress /* addr */, bool /* is_valid */)>
cb) = 0;
diff --git a/system/bta/le_audio/audio_set_configurations.fbs b/system/bta/le_audio/audio_set_configurations.fbs
index 8afe72ea99..2aa7bab499 100644
--- a/system/bta/le_audio/audio_set_configurations.fbs
+++ b/system/bta/le_audio/audio_set_configurations.fbs
@@ -64,16 +64,28 @@ table AudioSetSubConfiguration {
codec_id : CodecId (required);
codec_configuration: [CodecSpecificConfiguration] (required);
}
+table CodecConfiguration {
+ name: string (key, required);
+ subconfigurations: [AudioSetSubConfiguration] (required);
+}
+table QosConfiguration {
+ name: string (key, required);
+ retransmission_number: ubyte;
+ max_transport_latency : ushort;
+}
/// Each set configration can contain multiple logical subconfigurations, which
/// all must be configurable with the current set of audio devices. For example,
/// one can define multiple output stream configurations with different
/// qualities, or assign different configurations to each stream direction.
table AudioSetConfiguration {
name: string (key, required);
- subconfigurations: [AudioSetSubConfiguration] (required);
+ codec_config_name: string (required);
+ qos_config_name: string (required);
}
table AudioSetConfigurations {
_comments_: [string];
configurations: [AudioSetConfiguration] (required);
+ codec_configurations: [CodecConfiguration] (required);
+ qos_configurations: [QosConfiguration] (required);
}
root_type AudioSetConfigurations;
diff --git a/system/bta/le_audio/audio_set_configurations.json b/system/bta/le_audio/audio_set_configurations.json
index 08453307a1..81fdaf2661 100644
--- a/system/bta/le_audio/audio_set_configurations.json
+++ b/system/bta/le_audio/audio_set_configurations.json
@@ -1,6 +1,14 @@
{
"_comments_": [
" == Audio Set Configurations == ",
+ " Contains: ",
+ " 1. configurations : ",
+ " Maps configuration name with codec and qos config to be used",
+ " 2. codec_configurations : ",
+ " Array of codec specific configurations",
+ " 3. qos_configurations : ",
+ " Array of QoS specific configurations",
+ " QoS configuration values are as per BAP spec 1.0",
" Example values which can be used as 'codec_configuration.type'",
" Codec Configuration parameter types:",
" SUPPORTED_SAMPLING_FREQUENCY = 1",
@@ -35,6 +43,338 @@
],
"configurations": [
{
+ "name": "DualDev_OneChanStereoSnk_16_1_Server_Preferred",
+ "codec_config_name": "DualDev_OneChanStereoSnk_16_1",
+ "qos_config_name": "QoS_Config_Server_Preferred"
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_16_1_1",
+ "codec_config_name": "DualDev_OneChanStereoSnk_16_1",
+ "qos_config_name": "QoS_Config_16_1_1"
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_16_1_2",
+ "codec_config_name": "DualDev_OneChanStereoSnk_16_1",
+ "qos_config_name": "QoS_Config_16_1_2"
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_16_2_Server_Preferred",
+ "codec_config_name": "DualDev_OneChanStereoSnk_16_2",
+ "qos_config_name": "QoS_Config_Server_Preferred"
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_16_2_1",
+ "codec_config_name": "DualDev_OneChanStereoSnk_16_2",
+ "qos_config_name": "QoS_Config_16_2_1"
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_16_2_2",
+ "codec_config_name": "DualDev_OneChanStereoSnk_16_2",
+ "qos_config_name": "QoS_Config_16_2_2"
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_16_1_Server_Preferred",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_16_1",
+ "qos_config_name": "QoS_Config_Server_Preferred"
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_16_1_1",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_16_1",
+ "qos_config_name": "QoS_Config_16_1_1"
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_16_1_2",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_16_1",
+ "qos_config_name": "QoS_Config_16_1_2"
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_16_2_Server_Preferred",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_16_2",
+ "qos_config_name": "QoS_Config_Server_Preferred"
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_16_2_1",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_16_2",
+ "qos_config_name": "QoS_Config_16_2_1"
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_16_2_2",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_16_2",
+ "qos_config_name": "QoS_Config_16_2_2"
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_16_1_Server_Preferred",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_16_1",
+ "qos_config_name": "QoS_Config_Server_Preferred"
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_16_1_1",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_16_1",
+ "qos_config_name": "QoS_Config_16_1_1"
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_16_1_2",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_16_1",
+ "qos_config_name": "QoS_Config_16_1_2"
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_16_2_Server_Preferred",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_16_2",
+ "qos_config_name": "QoS_Config_Server_Preferred"
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_16_2_1",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_16_2",
+ "qos_config_name": "QoS_Config_16_2_1"
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_16_2_2",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_16_2",
+ "qos_config_name": "QoS_Config_16_2_2"
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_16_1_Server_Preferred",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_16_1",
+ "qos_config_name": "QoS_Config_Server_Preferred"
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_16_1_1",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_16_1",
+ "qos_config_name": "QoS_Config_16_1_1"
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_16_1_2",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_16_1",
+ "qos_config_name": "QoS_Config_16_1_2"
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_16_2_Server_Preferred",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_16_2",
+ "qos_config_name": "QoS_Config_Server_Preferred"
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_16_2_1",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_16_2",
+ "qos_config_name": "QoS_Config_16_2_1"
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_16_2_2",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_16_2",
+ "qos_config_name": "QoS_Config_16_2_2"
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1_Server_Preferred",
+ "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": "QoS_Config_Server_Preferred"
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1_1",
+ "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": "QoS_Config_16_1_1"
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1_2",
+ "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": "QoS_Config_16_1_2"
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2_Server_Preferred",
+ "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": "QoS_Config_Server_Preferred"
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2_1",
+ "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": "QoS_Config_16_2_1"
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2_2",
+ "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": "QoS_Config_16_2_2"
+ },
+ {
+ "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1_Server_Preferred",
+ "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": "QoS_Config_Server_Preferred"
+ },
+ {
+ "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1_1",
+ "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": "QoS_Config_16_1_1"
+ },
+ {
+ "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1_2",
+ "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": "QoS_Config_16_1_2"
+ },
+ {
+ "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2_Server_Preferred",
+ "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": "QoS_Config_Server_Preferred"
+ },
+ {
+ "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2_1",
+ "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": "QoS_Config_16_2_1"
+ },
+ {
+ "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2_2",
+ "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": "QoS_Config_16_2_2"
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_Server_Preferred",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": "QoS_Config_Server_Preferred"
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_1",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": "QoS_Config_16_1_1"
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_2",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": "QoS_Config_16_1_2"
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_Server_Preferred",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": "QoS_Config_Server_Preferred"
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_1",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": "QoS_Config_16_2_1"
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_2",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": "QoS_Config_16_2_2"
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_Server_Preferred",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": "QoS_Config_Server_Preferred"
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_1",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": "QoS_Config_16_1_1"
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_2",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": "QoS_Config_16_1_2"
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_Server_Preferred",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": "QoS_Config_Server_Preferred"
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_1",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": "QoS_Config_16_2_1"
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_2",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": "QoS_Config_16_2_2"
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_Server_Preferred",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": "QoS_Config_Server_Preferred"
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_1",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": "QoS_Config_16_1_1"
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_2",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1",
+ "qos_config_name": "QoS_Config_16_1_2"
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_Server_Preferred",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": "QoS_Config_Server_Preferred"
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_1",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": "QoS_Config_16_2_1"
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_2",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2",
+ "qos_config_name": "QoS_Config_16_2_2"
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_4_Server_Preferred",
+ "codec_config_name": "DualDev_OneChanStereoSnk_48_4",
+ "qos_config_name": "QoS_Config_Server_Preferred"
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_4_1",
+ "codec_config_name": "DualDev_OneChanStereoSnk_48_4",
+ "qos_config_name": "QoS_Config_48_4_1"
+ },
+ {
+ "name": "DualDev_OneChanStereoSnk_48_4_2",
+ "codec_config_name": "DualDev_OneChanStereoSnk_48_4",
+ "qos_config_name": "QoS_Config_48_4_2"
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_48_4_Server_Preferred",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_48_4",
+ "qos_config_name": "QoS_Config_Server_Preferred"
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_48_4_1",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_48_4",
+ "qos_config_name": "QoS_Config_48_4_1"
+ },
+ {
+ "name": "SingleDev_OneChanStereoSnk_48_4_2",
+ "codec_config_name": "SingleDev_OneChanStereoSnk_48_4",
+ "qos_config_name": "QoS_Config_48_4_2"
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_4_Server_Preferred",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4",
+ "qos_config_name": "QoS_Config_Server_Preferred"
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_4_1",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4",
+ "qos_config_name": "QoS_Config_48_4_1"
+ },
+ {
+ "name": "SingleDev_TwoChanStereoSnk_48_4_2",
+ "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4",
+ "qos_config_name": "QoS_Config_48_4_2"
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_48_4_Server_Preferred",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_48_4",
+ "qos_config_name": "QoS_Config_Server_Preferred"
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_48_4_1",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_48_4",
+ "qos_config_name": "QoS_Config_48_4_1"
+ },
+ {
+ "name": "SingleDev_OneChanMonoSnk_48_4_2",
+ "codec_config_name": "SingleDev_OneChanMonoSnk_48_4",
+ "qos_config_name": "QoS_Config_48_4_2"
+ }
+ ],
+ "codec_configurations": [
+ {
"name": "DualDev_OneChanStereoSnk_16_2",
"subconfigurations": [
{
@@ -2114,5 +2454,42 @@
}
]
}
+ ],
+ "qos_configurations": [
+ {
+ "name": "QoS_Config_16_1_1",
+ "retransmission_number": 2,
+ "max_transport_latency": 8
+ },
+ {
+ "name": "QoS_Config_16_1_2",
+ "retransmission_number": 13,
+ "max_transport_latency": 75
+ },
+ {
+ "name": "QoS_Config_16_2_1",
+ "retransmission_number": 2,
+ "max_transport_latency": 10
+ },
+ {
+ "name": "QoS_Config_16_2_2",
+ "retransmission_number": 13,
+ "max_transport_latency": 95
+ },
+ {
+ "name": "QoS_Config_48_4_1",
+ "retransmission_number": 5,
+ "max_transport_latency": 20
+ },
+ {
+ "name": "QoS_Config_48_4_2",
+ "retransmission_number": 13,
+ "max_transport_latency": 100
+ },
+ {
+ "name": "QoS_Config_Server_Preferred",
+ "retransmission_number": 0,
+ "max_transport_latency": 0
+ }
]
-} \ No newline at end of file
+}
diff --git a/system/bta/le_audio/audio_set_scenarios.json b/system/bta/le_audio/audio_set_scenarios.json
index d9f7b8fc7a..d1314a4485 100644
--- a/system/bta/le_audio/audio_set_scenarios.json
+++ b/system/bta/le_audio/audio_set_scenarios.json
@@ -8,55 +8,89 @@
{
"name": "Ringtone",
"configurations": [
- "DualDev_OneChanStereoSnk_16_2",
- "DualDev_OneChanStereoSnk_16_1",
- "SingleDev_OneChanStereoSnk_16_2",
- "SingleDev_OneChanStereoSnk_16_1",
- "SingleDev_TwoChanStereoSnk_16_2",
- "SingleDev_TwoChanStereoSnk_16_1",
- "SingleDev_OneChanMonoSnk_16_2",
- "SingleDev_OneChanMonoSnk_16_1"
+ "DualDev_OneChanStereoSnk_16_2_Server_Preferred",
+ "DualDev_OneChanStereoSnk_16_2_1",
+ "DualDev_OneChanStereoSnk_16_1_Server_Preferred",
+ "DualDev_OneChanStereoSnk_16_1_1",
+ "SingleDev_OneChanStereoSnk_16_2_Server_Preferred",
+ "SingleDev_OneChanStereoSnk_16_2_1",
+ "SingleDev_OneChanStereoSnk_16_1_Server_Preferred",
+ "SingleDev_OneChanStereoSnk_16_1_1",
+ "SingleDev_TwoChanStereoSnk_16_2_Server_Preferred",
+ "SingleDev_TwoChanStereoSnk_16_2_1",
+ "SingleDev_TwoChanStereoSnk_16_1_Server_Preferred",
+ "SingleDev_TwoChanStereoSnk_16_1_1",
+ "SingleDev_OneChanMonoSnk_16_2_Server_Preferred",
+ "SingleDev_OneChanMonoSnk_16_2_1",
+ "SingleDev_OneChanMonoSnk_16_1_Server_Preferred",
+ "SingleDev_OneChanMonoSnk_16_1_1"
]
},
{
"name": "Conversational",
"configurations": [
- "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2",
- "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1",
- "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2",
- "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1",
- "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2",
- "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1",
- "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2",
- "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1",
- "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2",
- "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1"
+ "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2_Server_Preferred",
+ "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2_1",
+ "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1_Server_Preferred",
+ "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1_1",
+ "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2_Server_Preferred",
+ "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2_1",
+ "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1_Server_Preferred",
+ "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1_1",
+ "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_Server_Preferred",
+ "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_1",
+ "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_Server_Preferred",
+ "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_1",
+ "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_Server_Preferred",
+ "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_1",
+ "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_Server_Preferred",
+ "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_1",
+ "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_Server_Preferred",
+ "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_1",
+ "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_Server_Preferred",
+ "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_1"
]
},
{
"name": "Media",
"configurations": [
- "DualDev_OneChanStereoSnk_48_4",
- "DualDev_OneChanStereoSnk_16_2",
- "DualDev_OneChanStereoSnk_16_1",
- "SingleDev_OneChanStereoSnk_48_4",
- "SingleDev_OneChanStereoSnk_16_2",
- "SingleDev_OneChanStereoSnk_16_1",
- "SingleDev_TwoChanStereoSnk_48_4",
- "SingleDev_TwoChanStereoSnk_16_2",
- "SingleDev_TwoChanStereoSnk_16_1",
- "SingleDev_OneChanMonoSnk_48_4",
- "SingleDev_OneChanMonoSnk_16_2",
- "SingleDev_OneChanMonoSnk_16_1"
+ "DualDev_OneChanStereoSnk_48_4_Server_Preferred",
+ "DualDev_OneChanStereoSnk_48_4_2",
+ "DualDev_OneChanStereoSnk_16_2_Server_Preferred",
+ "DualDev_OneChanStereoSnk_16_2_2",
+ "DualDev_OneChanStereoSnk_16_1_Server_Preferred",
+ "DualDev_OneChanStereoSnk_16_1_2",
+ "SingleDev_OneChanStereoSnk_48_4_Server_Preferred",
+ "SingleDev_OneChanStereoSnk_48_4_2",
+ "SingleDev_OneChanStereoSnk_16_2_Server_Preferred",
+ "SingleDev_OneChanStereoSnk_16_2_2",
+ "SingleDev_OneChanStereoSnk_16_1_Server_Preferred",
+ "SingleDev_OneChanStereoSnk_16_1_2",
+ "SingleDev_TwoChanStereoSnk_48_4_Server_Preferred",
+ "SingleDev_TwoChanStereoSnk_48_4_2",
+ "SingleDev_TwoChanStereoSnk_16_2_Server_Preferred",
+ "SingleDev_TwoChanStereoSnk_16_2_2",
+ "SingleDev_TwoChanStereoSnk_16_1_Server_Preferred",
+ "SingleDev_TwoChanStereoSnk_16_1_2",
+ "SingleDev_OneChanMonoSnk_48_4_Server_Preferred",
+ "SingleDev_OneChanMonoSnk_48_4_2",
+ "SingleDev_OneChanMonoSnk_16_2_Server_Preferred",
+ "SingleDev_OneChanMonoSnk_16_2_2",
+ "SingleDev_OneChanMonoSnk_16_1_Server_Preferred",
+ "SingleDev_OneChanMonoSnk_16_1_2"
]
},
{
"name": "Default",
"configurations": [
- "DualDev_OneChanStereoSnk_16_2",
- "SingleDev_OneChanStereoSnk_16_2",
- "SingleDev_TwoChanStereoSnk_16_2",
- "SingleDev_OneChanMonoSnk_16_2"
+ "DualDev_OneChanStereoSnk_16_2_Server_Preferred",
+ "DualDev_OneChanStereoSnk_16_2_1",
+ "SingleDev_OneChanStereoSnk_16_2_Server_Preferred",
+ "SingleDev_OneChanStereoSnk_16_2_1",
+ "SingleDev_TwoChanStereoSnk_16_2_Server_Preferred",
+ "SingleDev_TwoChanStereoSnk_16_2_1",
+ "SingleDev_OneChanMonoSnk_16_2_Server_Preferred",
+ "SingleDev_OneChanMonoSnk_16_2_1"
]
}
]
diff --git a/system/bta/le_audio/broadcaster/broadcaster.cc b/system/bta/le_audio/broadcaster/broadcaster.cc
index 43460e4ecb..a73b886e7d 100644
--- a/system/bta/le_audio/broadcaster/broadcaster.cc
+++ b/system/bta/le_audio/broadcaster/broadcaster.cc
@@ -23,10 +23,13 @@
#include "bta/le_audio/le_audio_types.h"
#include "device/include/controller.h"
#include "embdrv/lc3/include/lc3.h"
+#include "gd/common/strings.h"
+#include "osi/include/log.h"
+#include "osi/include/properties.h"
#include "stack/include/btm_api_types.h"
#include "stack/include/btm_iso_api.h"
-#include "osi/include/properties.h"
+using bluetooth::common::ToString;
using bluetooth::hci::IsoManager;
using bluetooth::hci::iso_manager::big_create_cmpl_evt;
using bluetooth::hci::iso_manager::big_terminate_cmpl_evt;
@@ -67,7 +70,7 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks {
num_retransmit_(3),
audio_data_path_state_(AudioDataPathState::INACTIVE),
audio_instance_(nullptr) {
- LOG(INFO) << __func__;
+ LOG_INFO();
/* Register State machine callbacks */
BroadcastStateMachine::Initialize(&state_machine_callbacks_);
@@ -83,15 +86,22 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks {
/* LE Rand returns 8 octets. Lets' make 2 outstanding Broadcast Ids out
* of it */
- for (int i = 0; i < 4; i += 3) {
- BroadcastId b_id = {rand[i], rand[i + 1], rand[i + 2]};
- instance->available_broadcast_ids_.emplace_back(b_id);
+ for (int i = 0; i < 8; i += 4) {
+ BroadcastId broadcast_id = 0;
+ /* Broadcast ID should be 3 octets long (BAP v1.0 spec.) */
+ STREAM_TO_UINT24(broadcast_id, rand);
+ if (broadcast_id == bluetooth::le_audio::kBroadcastIdInvalid) continue;
+ instance->available_broadcast_ids_.emplace_back(broadcast_id);
+ }
+
+ if (instance->available_broadcast_ids_.empty()) {
+ LOG_ALWAYS_FATAL("Unable to generate proper broadcast identifiers.");
}
}));
}
void CleanUp() {
- DLOG(INFO) << "Broadcaster " << __func__;
+ LOG_INFO("Broadcaster");
broadcasts_.clear();
callbacks_ = nullptr;
@@ -103,7 +113,7 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks {
}
void Stop() {
- DLOG(INFO) << "Broadcaster " << __func__;
+ LOG_INFO("Broadcaster");
for (auto& sm_pair : broadcasts_) {
StopAudioBroadcast(sm_pair.first);
@@ -153,14 +163,14 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks {
return announcement;
}
- void UpdateMetadata(uint8_t instance_id,
+ void UpdateMetadata(uint32_t broadcast_id,
std::vector<uint8_t> metadata) override {
- if (broadcasts_.count(instance_id) == 0) {
- LOG(ERROR) << __func__ << " no such instance_id=" << int{instance_id};
+ if (broadcasts_.count(broadcast_id) == 0) {
+ LOG_ERROR("No such broadcast_id=%d", broadcast_id);
return;
}
- DLOG(INFO) << __func__ << " for instance_id=" << int{instance_id};
+ LOG_INFO("For broadcast_id=%d", broadcast_id);
auto& codec_config = audio_receiver_.getCurrentCodecConfig();
@@ -168,7 +178,7 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks {
BasicAudioAnnouncementData announcement =
prepareAnnouncement(codec_config, std::move(metadata));
- broadcasts_[instance_id]->UpdateBroadcastAnnouncement(
+ broadcasts_[broadcast_id]->UpdateBroadcastAnnouncement(
std::move(announcement));
}
@@ -176,7 +186,10 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks {
LeAudioBroadcaster::AudioProfile profile,
std::optional<bluetooth::le_audio::BroadcastCode>
broadcast_code) override {
- DLOG(INFO) << __func__;
+ LOG_INFO("Audio profile: %s",
+ profile == LeAudioBroadcaster::AudioProfile::MEDIA
+ ? "Media"
+ : "Sonification");
auto& codec_wrapper =
BroadcastCodecWrapper::getCodecConfigForProfile(profile);
@@ -205,21 +218,22 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks {
// Notify the error instead just fail silently
if (!pending_broadcasts_.back()->Initialize()) {
pending_broadcasts_.pop_back();
- callbacks_->OnBroadcastCreated(
- BroadcastStateMachine::kInstanceIdUndefined, false);
+ callbacks_->OnBroadcastCreated(bluetooth::le_audio::kBroadcastIdInvalid,
+ false);
}
}
- void SuspendAudioBroadcast(uint8_t instance_id) override {
- DLOG(INFO) << __func__ << " suspending instance_id=" << int{instance_id};
- if (broadcasts_.count(instance_id) != 0) {
- DLOG(INFO) << __func__ << " Stopping LeAudioClientAudioSource";
+ void SuspendAudioBroadcast(uint32_t broadcast_id) override {
+ LOG_INFO("broadcast_id=%d", broadcast_id);
+
+ if (broadcasts_.count(broadcast_id) != 0) {
+ LOG_INFO("Stopping LeAudioClientAudioSource");
LeAudioClientAudioSource::Stop();
- broadcasts_[instance_id]->SetMuted(true);
- broadcasts_[instance_id]->ProcessMessage(
+ broadcasts_[broadcast_id]->SetMuted(true);
+ broadcasts_[broadcast_id]->ProcessMessage(
BroadcastStateMachine::Message::SUSPEND, nullptr);
} else {
- LOG(ERROR) << __func__ << " no such instance_id=" << int{instance_id};
+ LOG_ERROR("No such broadcast_id=%d", broadcast_id);
}
}
@@ -235,94 +249,83 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks {
return (iter != instance->broadcasts_.cend());
}
- void StartAudioBroadcast(uint8_t instance_id) override {
- DLOG(INFO) << __func__ << " starting instance_id=" << int{instance_id};
+ void StartAudioBroadcast(uint32_t broadcast_id) override {
+ LOG_INFO("Starting broadcast_id=%d", broadcast_id);
if (IsAnyoneStreaming()) {
- LOG(ERROR) << __func__ << ": Stop the other broadcast first!";
+ LOG_ERROR("Stop the other broadcast first!");
return;
}
- if (broadcasts_.count(instance_id) != 0) {
+ if (broadcasts_.count(broadcast_id) != 0) {
if (!audio_instance_) {
audio_instance_ = LeAudioClientAudioSource::Acquire();
if (!audio_instance_) {
- LOG(ERROR) << __func__ << " could not acquire le audio";
+ LOG_ERROR("Could not acquire le audio");
return;
}
}
- broadcasts_[instance_id]->ProcessMessage(
+ broadcasts_[broadcast_id]->ProcessMessage(
BroadcastStateMachine::Message::START, nullptr);
} else {
- LOG(ERROR) << __func__ << " no such instance_id=" << int{instance_id};
+ LOG_ERROR("No such broadcast_id=%d", broadcast_id);
}
}
- void StopAudioBroadcast(uint8_t instance_id) override {
- if (broadcasts_.count(instance_id) == 0) {
- LOG(ERROR) << __func__ << " no such instance_id=" << int{instance_id};
+ void StopAudioBroadcast(uint32_t broadcast_id) override {
+ if (broadcasts_.count(broadcast_id) == 0) {
+ LOG_ERROR("no such broadcast_id=%d", broadcast_id);
return;
}
- DLOG(INFO) << __func__ << " stopping instance_id=" << int{instance_id};
-
- DLOG(INFO) << __func__ << " Stopping LeAudioClientAudioSource";
+ LOG_INFO("Stopping LeAudioClientAudioSource, broadcast_id=%d",
+ broadcast_id);
LeAudioClientAudioSource::Stop();
- broadcasts_[instance_id]->SetMuted(true);
- broadcasts_[instance_id]->ProcessMessage(
+ broadcasts_[broadcast_id]->SetMuted(true);
+ broadcasts_[broadcast_id]->ProcessMessage(
BroadcastStateMachine::Message::STOP, nullptr);
}
- void DestroyAudioBroadcast(uint8_t instance_id) override {
- DLOG(INFO) << __func__ << " destroying instance_id=" << int{instance_id};
- broadcasts_.erase(instance_id);
- }
-
- void GetBroadcastId(uint8_t instance_id) override {
- if (broadcasts_.count(instance_id) == 0) {
- LOG(ERROR) << __func__ << " no such instance_id=" << int{instance_id};
- return;
- }
-
- auto broadcast_id = broadcasts_[instance_id]->GetBroadcastId();
- callbacks_->OnBroadcastId(instance_id, broadcast_id);
+ void DestroyAudioBroadcast(uint32_t broadcast_id) override {
+ LOG_INFO("Destroying broadcast_id=%d", broadcast_id);
+ broadcasts_.erase(broadcast_id);
}
void GetAllBroadcastStates(void) override {
for (auto const& kv_it : broadcasts_) {
callbacks_->OnBroadcastStateChanged(
- kv_it.second->GetInstanceId(),
+ kv_it.second->GetBroadcastId(),
static_cast<bluetooth::le_audio::BroadcastState>(
kv_it.second->GetState()));
}
}
void IsValidBroadcast(
- uint8_t instance_id, uint8_t addr_type, RawAddress addr,
- base::Callback<void(uint8_t /* instance_id */, uint8_t /* addr_type */,
+ uint32_t broadcast_id, uint8_t addr_type, RawAddress addr,
+ base::Callback<void(uint8_t /* broadcast_id */, uint8_t /* addr_type */,
RawAddress /* addr */, bool /* is_local */)>
cb) override {
- if (broadcasts_.count(instance_id) == 0) {
- LOG(ERROR) << __func__ << " no such instance_id=" << int{instance_id};
- std::move(cb).Run(instance_id, addr_type, addr, false);
+ if (broadcasts_.count(broadcast_id) == 0) {
+ LOG_ERROR("No such broadcast_id=%d", broadcast_id);
+ std::move(cb).Run(broadcast_id, addr_type, addr, false);
return;
}
- broadcasts_[instance_id]->RequestOwnAddress(base::Bind(
- [](uint8_t instance_id, uint8_t req_address_type,
+ broadcasts_[broadcast_id]->RequestOwnAddress(base::Bind(
+ [](uint32_t broadcast_id, uint8_t req_address_type,
RawAddress req_address,
- base::Callback<void(uint8_t /* instance_id */,
+ base::Callback<void(uint8_t /* broadcast_id */,
uint8_t /* addr_type */, RawAddress /* addr */,
bool /* is_local */)>
cb,
uint8_t rcv_address_type, RawAddress rcv_address) {
bool is_local = (req_address_type == rcv_address_type) &&
(req_address == rcv_address);
- std::move(cb).Run(instance_id, req_address_type, req_address,
+ std::move(cb).Run(broadcast_id, req_address_type, req_address,
is_local);
},
- instance_id, addr_type, addr, std::move(cb)));
+ broadcast_id, addr_type, addr, std::move(cb)));
}
void SetNumRetransmit(uint8_t count) override { num_retransmit_ = count; }
@@ -333,36 +336,53 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks {
uint8_t GetStreamingPhy(void) const override { return current_phy_; }
+ BroadcastId BroadcastIdFromBigHandle(uint8_t big_handle) const {
+ auto pair_it =
+ std::find_if(broadcasts_.begin(), broadcasts_.end(),
+ [big_handle](auto const& entry) {
+ return entry.second->GetAdvertisingSid() == big_handle;
+ });
+ if (pair_it != broadcasts_.end()) {
+ return pair_it->second->GetBroadcastId();
+ }
+ return bluetooth::le_audio::kBroadcastIdInvalid;
+ }
+
void OnSetupIsoDataPath(uint8_t status, uint16_t conn_handle,
- uint8_t big_id) override {
- CHECK(broadcasts_.count(big_id) != 0);
- broadcasts_[big_id]->OnSetupIsoDataPath(status, conn_handle);
+ uint8_t big_handle) override {
+ auto broadcast_id = BroadcastIdFromBigHandle(big_handle);
+ CHECK(broadcasts_.count(broadcast_id) != 0);
+ broadcasts_[broadcast_id]->OnSetupIsoDataPath(status, conn_handle);
}
void OnRemoveIsoDataPath(uint8_t status, uint16_t conn_handle,
- uint8_t big_id) override {
- CHECK(broadcasts_.count(big_id) != 0);
- broadcasts_[big_id]->OnRemoveIsoDataPath(status, conn_handle);
+ uint8_t big_handle) override {
+ auto broadcast_id = BroadcastIdFromBigHandle(big_handle);
+ CHECK(broadcasts_.count(broadcast_id) != 0);
+ broadcasts_[broadcast_id]->OnRemoveIsoDataPath(status, conn_handle);
}
void OnBigEvent(uint8_t event, void* data) override {
switch (event) {
case bluetooth::hci::iso_manager::kIsoEventBigOnCreateCmpl: {
auto* evt = static_cast<big_create_cmpl_evt*>(data);
- CHECK(broadcasts_.count(evt->big_id) != 0);
- broadcasts_[evt->big_id]->HandleHciEvent(HCI_BLE_CREATE_BIG_CPL_EVT,
- evt);
+ auto broadcast_id = BroadcastIdFromBigHandle(evt->big_id);
+ CHECK(broadcasts_.count(broadcast_id) != 0);
+ broadcasts_[broadcast_id]->HandleHciEvent(HCI_BLE_CREATE_BIG_CPL_EVT,
+ evt);
} break;
case bluetooth::hci::iso_manager::kIsoEventBigOnTerminateCmpl: {
auto* evt = static_cast<big_terminate_cmpl_evt*>(data);
- CHECK(broadcasts_.count(evt->big_id) != 0);
- broadcasts_[evt->big_id]->HandleHciEvent(HCI_BLE_TERM_BIG_CPL_EVT, evt);
+ auto broadcast_id = BroadcastIdFromBigHandle(evt->big_id);
+ CHECK(broadcasts_.count(broadcast_id) != 0);
+ broadcasts_[broadcast_id]->HandleHciEvent(HCI_BLE_TERM_BIG_CPL_EVT,
+ evt);
LeAudioClientAudioSource::Release(audio_instance_);
audio_instance_ = nullptr;
} break;
default:
- LOG(ERROR) << __func__ << " Invalid event: " << int{event};
+ LOG_ERROR("Invalid event=%d", event);
}
}
@@ -379,19 +399,19 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks {
}
private:
- uint8_t GetNumRetransmit(uint8_t broadcaster_id) {
+ uint8_t GetNumRetransmit(uint32_t broadcast_id) {
/* TODO: Should be based on QOS settings */
return GetNumRetransmit();
}
- uint32_t GetSduItv(uint8_t broadcaster_id) {
+ uint32_t GetSduItv(uint32_t broadcast_id) {
/* TODO: Should be based on QOS settings
* currently tuned for media profile (music band)
*/
return 0x002710;
}
- uint16_t GetMaxTransportLatency(uint8_t broadcaster_id) {
+ uint16_t GetMaxTransportLatency(uint32_t broadcast_id) {
/* TODO: Should be based on QOS settings
* currently tuned for media profile (music band)
*/
@@ -400,53 +420,55 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks {
static class BroadcastStateMachineCallbacks
: public IBroadcastStateMachineCallbacks {
- void OnStateMachineCreateStatus(uint8_t instance_id,
+ void OnStateMachineCreateStatus(uint32_t broadcast_id,
bool initialized) override {
auto pending_broadcast = std::find_if(
instance->pending_broadcasts_.begin(),
- instance->pending_broadcasts_.end(), [instance_id](auto& sm) {
- return (sm->GetInstanceId() == instance_id);
+ instance->pending_broadcasts_.end(), [broadcast_id](auto& sm) {
+ return (sm->GetBroadcastId() == broadcast_id);
});
LOG_ASSERT(pending_broadcast != instance->pending_broadcasts_.end());
- LOG_ASSERT(instance->broadcasts_.count(instance_id) == 0);
+ LOG_ASSERT(instance->broadcasts_.count(broadcast_id) == 0);
if (initialized) {
- const uint8_t instance_id = (*pending_broadcast)->GetInstanceId();
- DLOG(INFO) << __func__ << " instance_id=" << int{instance_id}
- << " state=" << (*pending_broadcast)->GetState();
+ const uint32_t broadcast_id = (*pending_broadcast)->GetBroadcastId();
+ LOG_INFO("broadcast_id=%d state=%s", broadcast_id,
+ ToString((*pending_broadcast)->GetState()).c_str());
- instance->broadcasts_[instance_id] = std::move(*pending_broadcast);
+ instance->broadcasts_[broadcast_id] = std::move(*pending_broadcast);
} else {
- LOG(ERROR) << "Failed creating broadcast!";
+ LOG_ERROR("Failed creating broadcast!");
}
instance->pending_broadcasts_.erase(pending_broadcast);
- instance->callbacks_->OnBroadcastCreated(instance_id, initialized);
+ instance->callbacks_->OnBroadcastCreated(broadcast_id, initialized);
}
- void OnStateMachineDestroyed(uint8_t instance_id) override {
+ void OnStateMachineDestroyed(uint32_t broadcast_id) override {
/* This is a special case when state machine destructor calls this
* callback. It may happen during the Cleanup() call when all state
* machines are erased and instance can already be set to null to avoid
* unnecessary calls.
*/
- if (instance) instance->callbacks_->OnBroadcastDestroyed(instance_id);
+ if (instance) instance->callbacks_->OnBroadcastDestroyed(broadcast_id);
}
static int getStreamerCount() {
return std::count_if(instance->broadcasts_.begin(),
instance->broadcasts_.end(), [](auto const& sm) {
- LOG(INFO)
- << "\t<< state :" << sm.second->GetState();
+ LOG_VERBOSE(
+ "broadcast_id=%d, state=%s",
+ sm.second->GetBroadcastId(),
+ ToString(sm.second->GetState()).c_str());
return sm.second->GetState() ==
BroadcastStateMachine::State::STREAMING;
});
}
- void OnStateMachineEvent(uint8_t instance_id,
+ void OnStateMachineEvent(uint32_t broadcast_id,
BroadcastStateMachine::State state,
const void* data) override {
- DLOG(INFO) << __func__ << " instance_id=" << int{instance_id}
- << " state=" << state;
+ LOG_INFO("broadcast_id=%d state=%s", broadcast_id,
+ ToString(state).c_str());
switch (state) {
case BroadcastStateMachine::State::STOPPED:
@@ -460,10 +482,10 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks {
break;
case BroadcastStateMachine::State::STREAMING:
if (getStreamerCount() == 1) {
- DLOG(INFO) << __func__ << " Starting LeAudioClientAudioSource";
+ LOG_INFO("Starting LeAudioClientAudioSource");
- if (instance->broadcasts_.count(instance_id) != 0) {
- const auto& broadcast = instance->broadcasts_.at(instance_id);
+ if (instance->broadcasts_.count(broadcast_id) != 0) {
+ const auto& broadcast = instance->broadcasts_.at(broadcast_id);
// Reconfigure encoder instance for the new stream requirements
audio_receiver_.setCurrentCodecConfig(
@@ -476,7 +498,7 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks {
LeAudioClientAudioSource::Start(*cfg, &audio_receiver_);
if (!is_started) {
/* Audio Source setup failed - stop the broadcast */
- instance->StopAudioBroadcast(instance_id);
+ instance->StopAudioBroadcast(broadcast_id);
return;
}
@@ -487,24 +509,25 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks {
};
instance->callbacks_->OnBroadcastStateChanged(
- instance_id, static_cast<bluetooth::le_audio::BroadcastState>(state));
+ broadcast_id,
+ static_cast<bluetooth::le_audio::BroadcastState>(state));
}
- void OnOwnAddressResponse(uint8_t instance_id, uint8_t addr_type,
+ void OnOwnAddressResponse(uint32_t broadcast_id, uint8_t addr_type,
RawAddress addr) override {
/* Not used currently */
}
- uint8_t GetNumRetransmit(uint8_t instance_id) override {
- return instance->GetNumRetransmit(instance_id);
+ uint8_t GetNumRetransmit(uint32_t broadcast_id) override {
+ return instance->GetNumRetransmit(broadcast_id);
}
- uint32_t GetSduItv(uint8_t instance_id) override {
- return instance->GetSduItv(instance_id);
+ uint32_t GetSduItv(uint32_t broadcast_id) override {
+ return instance->GetSduItv(broadcast_id);
}
- uint16_t GetMaxTransportLatency(uint8_t instance_id) override {
- return instance->GetMaxTransportLatency(instance_id);
+ uint16_t GetMaxTransportLatency(uint32_t broadcast_id) override {
+ return instance->GetMaxTransportLatency(broadcast_id);
}
} state_machine_callbacks_;
@@ -518,10 +541,8 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks {
void CheckAndReconfigureEncoders() {
auto const& codec_id = codec_wrapper_.GetLeAudioCodecId();
if (codec_id.coding_format != kLeAudioCodingFormatLC3) {
- LOG(ERROR) << "Invalid codec ID: "
- << "[" << +codec_id.coding_format << ":"
- << +codec_id.vendor_company_id << ":"
- << +codec_id.vendor_codec_id << "]";
+ LOG_ERROR("Invalid codec ID: [%d:%d:%d]", codec_id.coding_format,
+ codec_id.vendor_company_id, codec_id.vendor_codec_id);
return;
}
@@ -561,11 +582,11 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks {
int initial_channel_offset, int pitch_samples,
int num_channels) {
auto encoder_status =
- lc3_encode(encoder, (int16_t*)(data.data() + initial_channel_offset),
+ lc3_encode(encoder, LC3_PCM_FORMAT_S16,
+ (int16_t*)(data.data() + initial_channel_offset),
pitch_samples, out_buffer.size(), out_buffer.data());
if (encoder_status != 0) {
- LOG(ERROR) << "Error while encoding"
- << "\terror: " << encoder_status;
+ LOG_ERROR("Encoding error=%d", encoder_status);
}
}
@@ -574,15 +595,16 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks {
std::vector<std::vector<uint8_t>>& encoded_channels) {
auto const& config = broadcast->GetBigConfig();
if (config == std::nullopt) {
- LOG(ERROR) << "Broadcast instance_id= "
- << int{broadcast->GetInstanceId()}
- << " has no valid BIS configurations in state= "
- << broadcast->GetState();
+ LOG_ERROR(
+ "Broadcast broadcast_id=%d has no valid BIS configurations in "
+ "state=%s",
+ broadcast->GetBroadcastId(),
+ ToString(broadcast->GetState()).c_str());
return;
}
if (config->connection_handles.size() < encoded_channels.size()) {
- LOG(ERROR) << "Not enough BIS'es to broadcast all channels!";
+ LOG_ERROR("Not enough BIS'es to broadcast all channels!");
return;
}
@@ -596,7 +618,7 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks {
virtual void OnAudioDataReady(const std::vector<uint8_t>& data) override {
if (!instance) return;
- DVLOG(INFO) << __func__ << ": " << data.size() << " bytes received.";
+ LOG_VERBOSE("Received %zu bytes.", data.size());
/* Constants for the channel data configuration */
const auto num_channels = codec_wrapper_.GetNumChannels();
@@ -620,12 +642,12 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks {
!broadcast->IsMuted())
sendBroadcastData(broadcast, enc_audio_buffers_);
}
- DVLOG(INFO) << __func__ << ": END";
+ LOG_VERBOSE("All data sent.");
}
virtual void OnAudioSuspend(
std::promise<void> do_suspend_promise) override {
- LOG(INFO) << __func__;
+ LOG_INFO();
/* TODO: Should we suspend all broadcasts - remove BIGs? */
do_suspend_promise.set_value();
if (instance)
@@ -633,7 +655,7 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks {
}
virtual void OnAudioResume(void) override {
- LOG(INFO) << __func__;
+ LOG_INFO();
/* TODO: Should we resume all broadcasts - recreate BIGs? */
if (instance)
instance->audio_data_path_state_ = AudioDataPathState::ACTIVE;
@@ -649,7 +671,7 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks {
virtual void OnAudioMetadataUpdate(
std::promise<void> do_update_metadata_promise,
const source_metadata_t& source_metadata) override {
- LOG(INFO) << __func__;
+ LOG_INFO();
if (!instance) return;
do_update_metadata_promise.set_value();
/* TODO: We probably don't want to change stream type or update the
@@ -666,7 +688,7 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks {
} audio_receiver_;
bluetooth::le_audio::LeAudioBroadcasterCallbacks* callbacks_;
- std::map<uint8_t, std::unique_ptr<BroadcastStateMachine>> broadcasts_;
+ std::map<uint32_t, std::unique_ptr<BroadcastStateMachine>> broadcasts_;
std::vector<std::unique_ptr<BroadcastStateMachine>> pending_broadcasts_;
/* Some BIG params are set globally */
@@ -688,25 +710,24 @@ LeAudioBroadcasterImpl::LeAudioClientAudioSinkReceiverImpl
void LeAudioBroadcaster::Initialize(
bluetooth::le_audio::LeAudioBroadcasterCallbacks* callbacks,
base::Callback<bool()> audio_hal_verifier) {
- LOG(INFO) << "Broadcaster " << __func__;
+ LOG_INFO();
if (instance) {
- LOG(ERROR) << "Already initialized";
+ LOG_ERROR("Already initialized");
return;
}
if (!controller_get_interface()->supports_ble_isochronous_broadcaster() &&
!osi_property_get_bool("persist.bluetooth.fake_iso_support", false)) {
- LOG(WARNING) << "Isochronous Broadcast not supported by the controller!";
+ LOG_WARN("Isochronous Broadcast not supported by the controller!");
return;
}
- IsoManager::GetInstance()->Start();
-
if (!std::move(audio_hal_verifier).Run()) {
- LOG_ASSERT(false) << __func__ << ", HAL 2.1 not supported, Init aborted.";
- return;
+ LOG_ALWAYS_FATAL("HAL requirements not met. Init aborted.");
}
+ IsoManager::GetInstance()->Start();
+
instance = new LeAudioBroadcasterImpl(callbacks);
/* Register HCI event handlers */
IsoManager::GetInstance()->RegisterBigCallbacks(instance);
@@ -715,13 +736,13 @@ void LeAudioBroadcaster::Initialize(
bool LeAudioBroadcaster::IsLeAudioBroadcasterRunning() { return instance; }
LeAudioBroadcaster* LeAudioBroadcaster::Get(void) {
- LOG(INFO) << "Broadcaster " << __func__;
+ LOG_INFO();
CHECK(instance);
return instance;
}
void LeAudioBroadcaster::Stop(void) {
- LOG(INFO) << "Broadcaster " << __func__;
+ LOG_INFO();
if (instance) {
instance->Stop();
@@ -729,7 +750,7 @@ void LeAudioBroadcaster::Stop(void) {
}
void LeAudioBroadcaster::Cleanup(void) {
- LOG(INFO) << "Broadcaster " << __func__;
+ LOG_INFO();
if (instance == nullptr) return;
diff --git a/system/bta/le_audio/broadcaster/broadcaster_test.cc b/system/bta/le_audio/broadcaster/broadcaster_test.cc
index d028451105..69867245d0 100644
--- a/system/bta/le_audio/broadcaster/broadcaster_test.cc
+++ b/system/bta/le_audio/broadcaster/broadcaster_test.cc
@@ -20,13 +20,13 @@
#include <chrono>
-#include "device/include/controller.h"
#include "bta/include/bta_le_audio_api.h"
#include "bta/include/bta_le_audio_broadcaster_api.h"
-#include "bta/test/common/mock_controller.h"
+#include "bta/le_audio/broadcaster/mock_state_machine.h"
#include "bta/le_audio/mock_iso_manager.h"
#include "bta/le_audio/mock_le_audio_client_audio.h"
-#include "bta/le_audio/broadcaster/mock_state_machine.h"
+#include "bta/test/common/mock_controller.h"
+#include "device/include/controller.h"
#include "stack/include/btm_iso_api.h"
using testing::_;
@@ -53,12 +53,6 @@ void btsnd_hcic_ble_rand(base::Callback<void(BT_OCTET8)> cb) {
generator_cb = cb;
}
-std::ostream& operator<<(
- std::ostream& os,
- const le_audio::broadcaster::BroadcastStateMachine& machine) {
- return os;
-}
-
namespace le_audio {
namespace broadcaster {
namespace {
@@ -72,15 +66,13 @@ static const std::vector<uint8_t> default_metadata = {0x03, 0x02, 0x01, 0x00};
class MockLeAudioBroadcasterCallbacks
: public bluetooth::le_audio::LeAudioBroadcasterCallbacks {
public:
- MOCK_METHOD((void), OnBroadcastCreated, (uint8_t instance_id, bool success),
+ MOCK_METHOD((void), OnBroadcastCreated, (uint32_t broadcast_id, bool success),
(override));
- MOCK_METHOD((void), OnBroadcastDestroyed, (uint8_t instance_id), (override));
- MOCK_METHOD((void), OnBroadcastStateChanged,
- (uint8_t instance_id, bluetooth::le_audio::BroadcastState state),
+ MOCK_METHOD((void), OnBroadcastDestroyed, (uint32_t broadcast_id),
(override));
- MOCK_METHOD((void), OnBroadcastId,
- (uint8_t instance_id,
- const bluetooth::le_audio::BroadcastId& broadcast_id),
+ MOCK_METHOD((void), OnBroadcastStateChanged,
+ (uint32_t broadcast_id,
+ bluetooth::le_audio::BroadcastState state),
(override));
};
@@ -140,16 +132,16 @@ class BroadcasterTest : public Test {
MockLeAudioClientAudioSource::SetMockInstanceForTesting(nullptr);
}
- uint8_t InstantiateBroadcast(
+ uint32_t InstantiateBroadcast(
LeAudioBroadcaster::AudioProfile profile = default_profile,
std::vector<uint8_t> metadata = default_metadata,
BroadcastCode code = default_code) {
- uint8_t instance_id = LeAudioBroadcaster::kInstanceIdUndefined;
+ uint32_t broadcast_id = LeAudioBroadcaster::kInstanceIdUndefined;
EXPECT_CALL(mock_broadcaster_callbacks_, OnBroadcastCreated(_, true))
- .WillOnce(SaveArg<0>(&instance_id));
+ .WillOnce(SaveArg<0>(&broadcast_id));
LeAudioBroadcaster::Get()->CreateAudioBroadcast(metadata, profile, code);
- return instance_id;
+ return broadcast_id;
}
protected:
@@ -180,10 +172,10 @@ TEST_F(BroadcasterTest, GetStreamingPhy) {
}
TEST_F(BroadcasterTest, CreateAudioBroadcast) {
- uint8_t instance_id = InstantiateBroadcast();
- ASSERT_NE(instance_id, LeAudioBroadcaster::kInstanceIdUndefined);
- ASSERT_EQ(instance_id,
- MockBroadcastStateMachine::GetLastInstance()->GetInstanceId());
+ auto broadcast_id = InstantiateBroadcast();
+ ASSERT_NE(broadcast_id, LeAudioBroadcaster::kInstanceIdUndefined);
+ ASSERT_EQ(broadcast_id,
+ MockBroadcastStateMachine::GetLastInstance()->GetBroadcastId());
auto& instance_config = MockBroadcastStateMachine::GetLastInstance()->cfg;
ASSERT_EQ(instance_config.broadcast_code, default_code);
@@ -194,30 +186,30 @@ TEST_F(BroadcasterTest, CreateAudioBroadcast) {
}
TEST_F(BroadcasterTest, SuspendAudioBroadcast) {
- uint8_t instance_id = InstantiateBroadcast();
- LeAudioBroadcaster::Get()->StartAudioBroadcast(instance_id);
+ auto broadcast_id = InstantiateBroadcast();
+ LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id);
EXPECT_CALL(mock_broadcaster_callbacks_,
- OnBroadcastStateChanged(instance_id, BroadcastState::CONFIGURED))
+ OnBroadcastStateChanged(broadcast_id, BroadcastState::CONFIGURED))
.Times(1);
EXPECT_CALL(mock_audio_source_, Stop).Times(AtLeast(1));
- LeAudioBroadcaster::Get()->SuspendAudioBroadcast(instance_id);
+ LeAudioBroadcaster::Get()->SuspendAudioBroadcast(broadcast_id);
}
TEST_F(BroadcasterTest, StartAudioBroadcast) {
- uint8_t instance_id = InstantiateBroadcast();
- LeAudioBroadcaster::Get()->StopAudioBroadcast(instance_id);
+ auto broadcast_id = InstantiateBroadcast();
+ LeAudioBroadcaster::Get()->StopAudioBroadcast(broadcast_id);
EXPECT_CALL(mock_broadcaster_callbacks_,
- OnBroadcastStateChanged(instance_id, BroadcastState::STREAMING))
+ OnBroadcastStateChanged(broadcast_id, BroadcastState::STREAMING))
.Times(1);
LeAudioClientAudioSinkReceiver* audio_receiver;
EXPECT_CALL(mock_audio_source_, Start)
.WillOnce(DoAll(SaveArg<1>(&audio_receiver), Return(true)));
- LeAudioBroadcaster::Get()->StartAudioBroadcast(instance_id);
+ LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id);
ASSERT_NE(audio_receiver, nullptr);
// NOTICE: This is really an implementation specific part, we fake the BIG
@@ -226,7 +218,7 @@ TEST_F(BroadcasterTest, StartAudioBroadcast) {
// a mocked one).
BigConfig big_cfg;
big_cfg.big_id =
- MockBroadcastStateMachine::GetLastInstance()->GetInstanceId();
+ MockBroadcastStateMachine::GetLastInstance()->GetAdvertisingSid();
big_cfg.connection_handles = {0x10, 0x12};
big_cfg.max_pdu = 128;
MockBroadcastStateMachine::GetLastInstance()->SetExpectedBigConfig(big_cfg);
@@ -238,19 +230,19 @@ TEST_F(BroadcasterTest, StartAudioBroadcast) {
}
TEST_F(BroadcasterTest, StartAudioBroadcastMedia) {
- uint8_t instance_id =
+ auto broadcast_id =
InstantiateBroadcast(LeAudioBroadcaster::AudioProfile::MEDIA);
- LeAudioBroadcaster::Get()->StopAudioBroadcast(instance_id);
+ LeAudioBroadcaster::Get()->StopAudioBroadcast(broadcast_id);
EXPECT_CALL(mock_broadcaster_callbacks_,
- OnBroadcastStateChanged(instance_id, BroadcastState::STREAMING))
+ OnBroadcastStateChanged(broadcast_id, BroadcastState::STREAMING))
.Times(1);
LeAudioClientAudioSinkReceiver* audio_receiver;
EXPECT_CALL(mock_audio_source_, Start)
.WillOnce(DoAll(SaveArg<1>(&audio_receiver), Return(true)));
- LeAudioBroadcaster::Get()->StartAudioBroadcast(instance_id);
+ LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id);
ASSERT_NE(audio_receiver, nullptr);
// NOTICE: This is really an implementation specific part, we fake the BIG
@@ -259,7 +251,7 @@ TEST_F(BroadcasterTest, StartAudioBroadcastMedia) {
// a mocked one).
BigConfig big_cfg;
big_cfg.big_id =
- MockBroadcastStateMachine::GetLastInstance()->GetInstanceId();
+ MockBroadcastStateMachine::GetLastInstance()->GetAdvertisingSid();
big_cfg.connection_handles = {0x10, 0x12};
big_cfg.max_pdu = 128;
MockBroadcastStateMachine::GetLastInstance()->SetExpectedBigConfig(big_cfg);
@@ -271,83 +263,75 @@ TEST_F(BroadcasterTest, StartAudioBroadcastMedia) {
}
TEST_F(BroadcasterTest, StopAudioBroadcast) {
- uint8_t instance_id = InstantiateBroadcast();
- LeAudioBroadcaster::Get()->StartAudioBroadcast(instance_id);
+ auto broadcast_id = InstantiateBroadcast();
+ LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id);
EXPECT_CALL(mock_broadcaster_callbacks_,
- OnBroadcastStateChanged(instance_id, BroadcastState::STOPPED))
+ OnBroadcastStateChanged(broadcast_id, BroadcastState::STOPPED))
.Times(1);
EXPECT_CALL(mock_audio_source_, Stop).Times(AtLeast(1));
- LeAudioBroadcaster::Get()->StopAudioBroadcast(instance_id);
+ LeAudioBroadcaster::Get()->StopAudioBroadcast(broadcast_id);
}
TEST_F(BroadcasterTest, DestroyAudioBroadcast) {
- uint8_t instance_id = InstantiateBroadcast();
+ auto broadcast_id = InstantiateBroadcast();
- EXPECT_CALL(mock_broadcaster_callbacks_, OnBroadcastDestroyed(instance_id))
+ EXPECT_CALL(mock_broadcaster_callbacks_, OnBroadcastDestroyed(broadcast_id))
.Times(1);
- LeAudioBroadcaster::Get()->DestroyAudioBroadcast(instance_id);
+ LeAudioBroadcaster::Get()->DestroyAudioBroadcast(broadcast_id);
// Expect not being able to interact with this Broadcast
EXPECT_CALL(mock_broadcaster_callbacks_,
- OnBroadcastStateChanged(instance_id, _))
+ OnBroadcastStateChanged(broadcast_id, _))
.Times(0);
EXPECT_CALL(mock_audio_source_, Stop).Times(0);
- LeAudioBroadcaster::Get()->StopAudioBroadcast(instance_id);
+ LeAudioBroadcaster::Get()->StopAudioBroadcast(broadcast_id);
EXPECT_CALL(mock_audio_source_, Start).Times(0);
- LeAudioBroadcaster::Get()->StartAudioBroadcast(instance_id);
+ LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id);
EXPECT_CALL(mock_audio_source_, Stop).Times(0);
- LeAudioBroadcaster::Get()->SuspendAudioBroadcast(instance_id);
-}
-
-TEST_F(BroadcasterTest, GetBroadcastId) {
- uint8_t instance_id = InstantiateBroadcast();
-
- EXPECT_CALL(mock_broadcaster_callbacks_, OnBroadcastId(instance_id, _))
- .Times(1);
- LeAudioBroadcaster::Get()->GetBroadcastId(instance_id);
+ LeAudioBroadcaster::Get()->SuspendAudioBroadcast(broadcast_id);
}
TEST_F(BroadcasterTest, GetBroadcastAllStates) {
- uint8_t instance_id = InstantiateBroadcast();
- uint8_t instance_id2 = InstantiateBroadcast();
- ASSERT_NE(instance_id, LeAudioBroadcaster::kInstanceIdUndefined);
- ASSERT_NE(instance_id2, LeAudioBroadcaster::kInstanceIdUndefined);
- ASSERT_NE(instance_id, instance_id2);
+ auto broadcast_id = InstantiateBroadcast();
+ auto broadcast_id2 = InstantiateBroadcast();
+ ASSERT_NE(broadcast_id, LeAudioBroadcaster::kInstanceIdUndefined);
+ ASSERT_NE(broadcast_id2, LeAudioBroadcaster::kInstanceIdUndefined);
+ ASSERT_NE(broadcast_id, broadcast_id2);
/* In the current implementation state machine switches to the correct state
* on itself, therefore here when we use mocked state machine this is not
* being verified.
*/
EXPECT_CALL(mock_broadcaster_callbacks_,
- OnBroadcastStateChanged(instance_id, _))
+ OnBroadcastStateChanged(broadcast_id, _))
.Times(1);
EXPECT_CALL(mock_broadcaster_callbacks_,
- OnBroadcastStateChanged(instance_id2, _))
+ OnBroadcastStateChanged(broadcast_id2, _))
.Times(1);
LeAudioBroadcaster::Get()->GetAllBroadcastStates();
}
TEST_F(BroadcasterTest, UpdateMetadata) {
- uint8_t instance_id = InstantiateBroadcast();
+ auto broadcast_id = InstantiateBroadcast();
EXPECT_CALL(*MockBroadcastStateMachine::GetLastInstance(),
UpdateBroadcastAnnouncement)
.Times(1);
- LeAudioBroadcaster::Get()->UpdateMetadata(instance_id,
+ LeAudioBroadcaster::Get()->UpdateMetadata(broadcast_id,
std::vector<uint8_t>({0x02, 0x01}));
}
TEST_F(BroadcasterTest, SetNumRetransmit) {
- uint8_t instance_id = InstantiateBroadcast();
+ auto broadcast_id = InstantiateBroadcast();
LeAudioBroadcaster::Get()->SetNumRetransmit(9);
ASSERT_EQ(MockBroadcastStateMachine::GetLastInstance()->cb->GetNumRetransmit(
- instance_id),
+ broadcast_id),
9);
ASSERT_EQ(LeAudioBroadcaster::Get()->GetNumRetransmit(), 9);
}
@@ -355,12 +339,12 @@ TEST_F(BroadcasterTest, SetNumRetransmit) {
TEST_F(BroadcasterTest, SetStreamingPhy) {
LeAudioBroadcaster::Get()->SetStreamingPhy(2);
// From now on new streams should be using Phy = 2.
- uint8_t instance_id = InstantiateBroadcast();
+ InstantiateBroadcast();
ASSERT_EQ(MockBroadcastStateMachine::GetLastInstance()->cfg.streaming_phy, 2);
// From now on new streams should be using Phy = 1.
LeAudioBroadcaster::Get()->SetStreamingPhy(1);
- instance_id = InstantiateBroadcast();
+ InstantiateBroadcast();
ASSERT_EQ(MockBroadcastStateMachine::GetLastInstance()->cfg.streaming_phy, 1);
ASSERT_EQ(LeAudioBroadcaster::Get()->GetStreamingPhy(), 1);
}
diff --git a/system/bta/le_audio/broadcaster/broadcaster_types.cc b/system/bta/le_audio/broadcaster/broadcaster_types.cc
index 3cfbc6c122..fc3ee47faf 100644
--- a/system/bta/le_audio/broadcaster/broadcaster_types.cc
+++ b/system/bta/le_audio/broadcaster/broadcaster_types.cc
@@ -147,8 +147,7 @@ void PrepareAdvertisingData(bluetooth::le_audio::BroadcastId& broadcast_id,
UINT8_TO_STREAM(data_ptr, 6);
UINT8_TO_STREAM(data_ptr, BTM_BLE_AD_TYPE_SERVICE_DATA_TYPE);
UINT16_TO_STREAM(data_ptr, kBroadcastAudioAnnouncementServiceUuid);
- ARRAY_TO_STREAM(data_ptr, broadcast_id.data(),
- bluetooth::le_audio::kBroadcastAnnouncementBroadcastIdSize);
+ UINT24_TO_STREAM(data_ptr, broadcast_id)
};
void PreparePeriodicData(const BasicAudioAnnouncementData& announcement,
@@ -272,9 +271,6 @@ std::vector<uint8_t> BroadcastCodecWrapper::GetCodecSpecData() const {
return data;
}
-} /* namespace broadcaster */
-} /* namespace le_audio */
-
std::ostream& operator<<(
std::ostream& os,
const le_audio::broadcaster::BroadcastCodecWrapper& config) {
@@ -292,3 +288,6 @@ std::ostream& operator<<(
os << "]";
return os;
}
+
+} /* namespace broadcaster */
+} /* namespace le_audio */
diff --git a/system/bta/le_audio/broadcaster/broadcaster_types.h b/system/bta/le_audio/broadcaster/broadcaster_types.h
index 8103fab979..7070424661 100644
--- a/system/bta/le_audio/broadcaster/broadcaster_types.h
+++ b/system/bta/le_audio/broadcaster/broadcaster_types.h
@@ -148,9 +148,10 @@ struct BroadcastCodecWrapper {
uint32_t codec_frame_len;
uint8_t blocks_per_sdu;
};
-} // namespace broadcaster
-} // namespace le_audio
std::ostream& operator<<(
std::ostream& os,
const le_audio::broadcaster::BroadcastCodecWrapper& config);
+
+} // namespace broadcaster
+} // namespace le_audio
diff --git a/system/bta/le_audio/broadcaster/mock_state_machine.cc b/system/bta/le_audio/broadcaster/mock_state_machine.cc
index 6af8c5ca9f..239ca0bb8e 100644
--- a/system/bta/le_audio/broadcaster/mock_state_machine.cc
+++ b/system/bta/le_audio/broadcaster/mock_state_machine.cc
@@ -32,6 +32,9 @@ std::unique_ptr<BroadcastStateMachine> BroadcastStateMachine::CreateInstance(
return std::move(instance);
}
+namespace le_audio {
+namespace broadcaster {
+
std::ostream& operator<<(std::ostream& os,
const BroadcastStateMachine::Message& state) {
static const char* char_value_[BroadcastStateMachine::MESSAGE_COUNT] = {
@@ -48,5 +51,22 @@ std::ostream& operator<<(std::ostream& os,
return os;
}
+std::ostream& operator<<(std::ostream& os, const BigConfig& config) {
+ return os;
+}
+
+std::ostream& operator<<(std::ostream& os,
+ const BroadcastStateMachineConfig& config) {
+ return os;
+}
+
+std::ostream& operator<<(std::ostream& os,
+ const BroadcastStateMachine& machine) {
+ return os;
+}
+
+} // namespace broadcaster
+} // namespace le_audio
+
uint8_t MockBroadcastStateMachine::instance_counter_ = 0;
MockBroadcastStateMachine* MockBroadcastStateMachine::last_instance_ = nullptr;
diff --git a/system/bta/le_audio/broadcaster/mock_state_machine.h b/system/bta/le_audio/broadcaster/mock_state_machine.h
index 69480ab2d7..427f0128ee 100644
--- a/system/bta/le_audio/broadcaster/mock_state_machine.h
+++ b/system/bta/le_audio/broadcaster/mock_state_machine.h
@@ -28,10 +28,10 @@ class MockBroadcastStateMachine
le_audio::broadcaster::BroadcastStateMachineConfig cfg,
le_audio::broadcaster::IBroadcastStateMachineCallbacks* cb)
: cfg(cfg), cb(cb) {
- instance_id_ = ++instance_counter_;
+ advertising_sid_ = ++instance_counter_;
ON_CALL(*this, Initialize).WillByDefault([this]() {
- this->cb->OnStateMachineCreateStatus(GetInstanceId(), result_);
+ this->cb->OnStateMachineCreateStatus(this->cfg.broadcast_id, result_);
return result_;
});
@@ -53,14 +53,14 @@ class MockBroadcastStateMachine
if (result_) SetState(State::CONFIGURED);
break;
};
- this->cb->OnStateMachineEvent(GetInstanceId(), GetState(),
+ this->cb->OnStateMachineEvent(this->cfg.broadcast_id, GetState(),
sent_data);
});
ON_CALL(*this, GetBigConfig).WillByDefault(testing::ReturnRef(big_config_));
ON_CALL(*this, RequestOwnAddress()).WillByDefault([this]() {
- this->cb->OnOwnAddressResponse(GetInstanceId(), 0, RawAddress());
+ this->cb->OnOwnAddressResponse(this->cfg.broadcast_id, 0, RawAddress());
});
ON_CALL(*this, GetCodecConfig())
@@ -70,9 +70,10 @@ class MockBroadcastStateMachine
});
ON_CALL(*this, GetBroadcastId())
- .WillByDefault([this]() -> const bluetooth::le_audio::BroadcastId {
+ .WillByDefault([this]() -> bluetooth::le_audio::BroadcastId {
return this->cfg.broadcast_id;
});
+
ON_CALL(*this, GetOwnAddress()).WillByDefault([this]() -> RawAddress {
return this->addr_;
});
@@ -82,13 +83,17 @@ class MockBroadcastStateMachine
});
};
- ~MockBroadcastStateMachine() { cb->OnStateMachineDestroyed(instance_id_); }
+ ~MockBroadcastStateMachine() {
+ cb->OnStateMachineDestroyed(this->cfg.broadcast_id);
+ }
MOCK_METHOD((bool), Initialize, (), (override));
MOCK_METHOD((const le_audio::broadcaster::BroadcastCodecWrapper&),
GetCodecConfig, (), (const override));
MOCK_METHOD((std::optional<le_audio::broadcaster::BigConfig> const&),
- GetBigConfig, (), (override));
+ GetBigConfig, (), (const override));
+ MOCK_METHOD((le_audio::broadcaster::BroadcastStateMachineConfig const&),
+ GetStateMachineConfig, (), (const override));
MOCK_METHOD(
(void), RequestOwnAddress,
(base::Callback<void(uint8_t /* address_type*/, RawAddress /*address*/)>
@@ -99,7 +104,7 @@ class MockBroadcastStateMachine
MOCK_METHOD((uint8_t), GetOwnAddressType, (), (override));
MOCK_METHOD((std::optional<bluetooth::le_audio::BroadcastCode>),
GetBroadcastCode, (), (const override));
- MOCK_METHOD((bluetooth::le_audio::BroadcastId const&), GetBroadcastId, (),
+ MOCK_METHOD((bluetooth::le_audio::BroadcastId), GetBroadcastId, (),
(const override));
MOCK_METHOD((void), UpdateBroadcastAnnouncement,
(le_audio::broadcaster::BasicAudioAnnouncementData announcement),
diff --git a/system/bta/le_audio/broadcaster/state_machine.cc b/system/bta/le_audio/broadcaster/state_machine.cc
index 8b7b035626..bbf7a6c390 100644
--- a/system/bta/le_audio/broadcaster/state_machine.cc
+++ b/system/bta/le_audio/broadcaster/state_machine.cc
@@ -27,11 +27,14 @@
#include "base/logging.h"
#include "bta/le_audio/broadcaster/broadcaster_types.h"
#include "bta/le_audio/le_audio_types.h"
+#include "gd/common/strings.h"
+#include "osi/include/log.h"
#include "service/common/bluetooth/low_energy_constants.h"
#include "stack/include/ble_advertiser.h"
#include "stack/include/btm_iso_api.h"
#include "stack/include/btu.h"
+using bluetooth::common::ToString;
using bluetooth::hci::IsoManager;
using bluetooth::hci::iso_manager::big_create_cmpl_evt;
using bluetooth::hci::iso_manager::big_terminate_cmpl_evt;
@@ -50,16 +53,17 @@ class BroadcastStateMachineImpl : public BroadcastStateMachine {
~BroadcastStateMachineImpl() {
if (GetState() == State::STREAMING) TerminateBig();
DestroyBroadcastAnnouncement();
- if (callbacks_) callbacks_->OnStateMachineDestroyed(GetInstanceId());
+ if (callbacks_) callbacks_->OnStateMachineDestroyed(GetBroadcastId());
}
bool Initialize() override {
static constexpr uint8_t sNumBisMax = 31;
if (sm_config_.codec_wrapper.GetNumChannels() > sNumBisMax) {
- DLOG(ERROR) << int{sm_config_.codec_wrapper.GetNumChannels()}
- << " channel count exceeds " << int{sNumBisMax}
- << " - the maximum number of possible BISes!";
+ LOG_ERROR(
+ "Channel count of %d exceeds the maximum number of possible BISes, "
+ "which is %d",
+ sm_config_.codec_wrapper.GetNumChannels(), sNumBisMax);
return false;
}
@@ -73,35 +77,39 @@ class BroadcastStateMachineImpl : public BroadcastStateMachine {
return sm_config_.codec_wrapper;
}
- std::optional<BigConfig> const& GetBigConfig() override {
+ std::optional<BigConfig> const& GetBigConfig() const override {
return active_config_;
}
+ BroadcastStateMachineConfig const& GetStateMachineConfig() const override {
+ return sm_config_;
+ }
+
void RequestOwnAddress(
base::Callback<void(uint8_t /* address_type*/, RawAddress /*address*/)>
cb) override {
- uint8_t instance_id = GetInstanceId();
- advertiser_if_->GetOwnAddress(instance_id, cb);
+ uint8_t advertising_sid = GetAdvertisingSid();
+ advertiser_if_->GetOwnAddress(advertising_sid, cb);
}
void RequestOwnAddress(void) override {
- uint8_t instance_id = GetInstanceId();
+ auto broadcast_id = GetBroadcastId();
RequestOwnAddress(
base::Bind(&IBroadcastStateMachineCallbacks::OnOwnAddressResponse,
- base::Unretained(this->callbacks_), instance_id));
+ base::Unretained(this->callbacks_), broadcast_id));
}
RawAddress GetOwnAddress() override {
- LOG(INFO) << __func__;
+ LOG_INFO();
return addr_;
}
uint8_t GetOwnAddressType() override {
- LOG(INFO) << __func__;
+ LOG_INFO();
return addr_type_;
}
- bluetooth::le_audio::BroadcastId const& GetBroadcastId() const override {
+ bluetooth::le_audio::BroadcastId GetBroadcastId() const override {
return sm_config_.broadcast_id;
}
@@ -116,13 +124,13 @@ class BroadcastStateMachineImpl : public BroadcastStateMachine {
PreparePeriodicData(announcement, periodic_data);
sm_config_.announcement = std::move(announcement);
- advertiser_if_->SetPeriodicAdvertisingData(instance_id_, periodic_data,
+ advertiser_if_->SetPeriodicAdvertisingData(advertising_sid_, periodic_data,
base::DoNothing());
}
void ProcessMessage(Message msg, const void* data = nullptr) override {
- DLOG(INFO) << __func__ << " instance_id=" << int{GetInstanceId()}
- << " state=" << GetState() << " message=" << msg;
+ LOG_INFO("broadcast_id=%d, state=%s, message=%s", GetBroadcastId(),
+ ToString(GetState()).c_str(), ToString(msg).c_str());
switch (msg) {
case Message::START:
start_msg_handlers[StateMachine::GetState()](data);
@@ -151,7 +159,7 @@ class BroadcastStateMachineImpl : public BroadcastStateMachine {
/* in STOPPED state */
[this](const void*) {
SetState(State::CONFIGURING);
- callbacks_->OnStateMachineEvent(GetInstanceId(), GetState());
+ callbacks_->OnStateMachineEvent(GetBroadcastId(), GetState());
EnableAnnouncement();
},
/* in CONFIGURING state */
@@ -172,7 +180,7 @@ class BroadcastStateMachineImpl : public BroadcastStateMachine {
/* in CONFIGURED state */
[this](const void*) {
SetState(State::STOPPING);
- callbacks_->OnStateMachineEvent(GetInstanceId(), GetState());
+ callbacks_->OnStateMachineEvent(GetBroadcastId(), GetState());
DisableAnnouncement();
},
/* in STOPPING state */
@@ -182,7 +190,7 @@ class BroadcastStateMachineImpl : public BroadcastStateMachine {
if ((active_config_ != std::nullopt) && !suspending_) {
suspending_ = false;
SetState(State::STOPPING);
- callbacks_->OnStateMachineEvent(GetInstanceId(), GetState());
+ callbacks_->OnStateMachineEvent(GetBroadcastId(), GetState());
TriggerIsoDatapathTeardown(active_config_->connection_handles[0]);
}
}};
@@ -218,50 +226,49 @@ class BroadcastStateMachineImpl : public BroadcastStateMachine {
[](const void*) { /* Already streaming */ }};
void OnAddressResponse(uint8_t addr_type, RawAddress addr) {
- DLOG(INFO) << __func__ << " own address: " << addr
- << " own address type: " << +addr_type;
+ LOG_INFO("own address=%s, type=%d", ToString(addr).c_str(), addr_type);
addr_ = addr;
addr_type_ = addr_type;
}
- void CreateAnnouncementCb(uint8_t instance_id, int8_t tx_power,
+ void CreateAnnouncementCb(uint8_t advertising_sid, int8_t tx_power,
uint8_t status) {
- DLOG(INFO) << __func__ << " instance_id=" << int{instance_id}
- << " tx_power=" << int{tx_power} << " status=" << int{status};
+ LOG_INFO("advertising_sid=%d tx_power=%d status=%d", advertising_sid,
+ tx_power, status);
- /* If this callback gets called the instance_id is valid even though the
- * status can be other than BTM_BLE_MULTI_ADV_SUCCESS. We must set it here
- * to properly identify the instance when callback gets called.
+ /* If this callback gets called the advertising_sid is valid even though the
+ * status can be other than BTM_BLE_MULTI_ADV_SUCCESS.
*/
- instance_id_ = instance_id;
+ advertising_sid_ = advertising_sid;
if (status != BTM_BLE_MULTI_ADV_SUCCESS) {
- callbacks_->OnStateMachineCreateStatus(instance_id, false);
+ LOG_ERROR("Creating Announcement failed");
+ callbacks_->OnStateMachineCreateStatus(GetBroadcastId(), false);
return;
}
/* Ext. advertisings are already on */
SetState(State::CONFIGURED);
- callbacks_->OnStateMachineCreateStatus(instance_id, true);
- callbacks_->OnStateMachineEvent(instance_id, State::CONFIGURED);
+ callbacks_->OnStateMachineCreateStatus(GetBroadcastId(), true);
+ callbacks_->OnStateMachineEvent(GetBroadcastId(), State::CONFIGURED);
advertiser_if_->GetOwnAddress(
- instance_id, base::Bind(&BroadcastStateMachineImpl::OnAddressResponse,
- base::Unretained(this)));
+ advertising_sid,
+ base::Bind(&BroadcastStateMachineImpl::OnAddressResponse,
+ base::Unretained(this)));
}
- void CreateAnnouncementTimeoutCb(uint8_t instance_id, uint8_t status) {
- DLOG(INFO) << __func__ << " instance_id=" << int{instance_id}
- << " status=" << int{status};
- instance_id_ = instance_id;
- callbacks_->OnStateMachineCreateStatus(instance_id, false);
+ void CreateAnnouncementTimeoutCb(uint8_t advertising_sid, uint8_t status) {
+ LOG_INFO("advertising_sid=%d status=%d", advertising_sid, status);
+ advertising_sid_ = advertising_sid;
+ callbacks_->OnStateMachineCreateStatus(GetBroadcastId(), false);
}
void CreateBroadcastAnnouncement(
bluetooth::le_audio::BroadcastId& broadcast_id,
const BasicAudioAnnouncementData& announcement, uint8_t streaming_phy) {
- DLOG(INFO) << __func__;
+ LOG_INFO();
if (advertiser_if_ != nullptr) {
tBTM_BLE_ADV_PARAMS adv_params;
tBLE_PERIODIC_ADV_PARAMS periodic_params;
@@ -301,13 +308,12 @@ class BroadcastStateMachineImpl : public BroadcastStateMachine {
void DestroyBroadcastAnnouncement() {
if (BleAdvertisingManager::IsInitialized())
- advertiser_if_->Unregister(GetInstanceId());
+ advertiser_if_->Unregister(GetAdvertisingSid());
}
void EnableAnnouncementCb(bool enable, uint8_t status) {
- DLOG(INFO) << __func__ << " operation=" << (enable ? "enable" : "disable")
- << " instance_id=" << int{GetInstanceId()}
- << " status=" << int{status};
+ LOG_INFO("operation=%s, broadcast_id=%d, status=%d",
+ (enable ? "enable" : "disable"), GetBroadcastId(), status);
if (status == BTM_BLE_MULTI_ADV_SUCCESS) {
/* Periodic is enabled but without BIGInfo. Stream is suspended. */
@@ -318,14 +324,14 @@ class BroadcastStateMachineImpl : public BroadcastStateMachine {
} else {
/* User wanted to stop the announcement - report target state reached */
SetState(State::STOPPED);
- callbacks_->OnStateMachineEvent(GetInstanceId(), GetState());
+ callbacks_->OnStateMachineEvent(GetBroadcastId(), GetState());
}
}
}
void EnableAnnouncementTimeoutCb(bool enable, uint8_t status) {
- DLOG(INFO) << __func__ << " operation=" << (enable ? "enable" : "disable")
- << " status=" << int{status};
+ LOG_INFO("operation=%s, broadcast_id=%d, status=%d",
+ (enable ? "enable" : "disable"), GetBroadcastId(), status);
if (enable) {
/* Timeout on enabling */
SetState(State::STOPPED);
@@ -333,13 +339,13 @@ class BroadcastStateMachineImpl : public BroadcastStateMachine {
/* Timeout on disabling */
SetState(State::CONFIGURED);
}
- callbacks_->OnStateMachineEvent(GetInstanceId(), GetState());
+ callbacks_->OnStateMachineEvent(GetBroadcastId(), GetState());
}
void EnableAnnouncement() {
- DLOG(INFO) << __func__ << "instance_id: " << int{GetInstanceId()};
+ LOG_INFO("broadcast_id=%d", GetBroadcastId());
advertiser_if_->Enable(
- GetInstanceId(), true,
+ GetAdvertisingSid(), true,
base::Bind(&BroadcastStateMachineImpl::EnableAnnouncementCb,
base::Unretained(this), true),
0, 0, /* Enable until stopped */
@@ -348,16 +354,16 @@ class BroadcastStateMachineImpl : public BroadcastStateMachine {
}
void CreateBig(void) {
- DLOG(INFO) << __func__ << " instance_id=" << int{GetInstanceId()};
+ LOG_INFO("broadcast_id=%d", GetBroadcastId());
/* TODO: Figure out how to decide on the currently hard-codded params. */
struct bluetooth::hci::iso_manager::big_create_params big_params = {
- .adv_handle = GetInstanceId(),
+ .adv_handle = GetAdvertisingSid(),
.num_bis = sm_config_.codec_wrapper.GetNumChannels(),
- .sdu_itv = callbacks_->GetSduItv(GetInstanceId()),
+ .sdu_itv = callbacks_->GetSduItv(GetBroadcastId()),
.max_sdu_size = sm_config_.codec_wrapper.GetMaxSduSize(),
.max_transport_latency =
- callbacks_->GetMaxTransportLatency(GetInstanceId()),
- .rtn = callbacks_->GetNumRetransmit(GetInstanceId()),
+ callbacks_->GetMaxTransportLatency(GetBroadcastId()),
+ .rtn = callbacks_->GetNumRetransmit(GetBroadcastId()),
.phy = sm_config_.streaming_phy,
.packing = 0x00, /* Sequencial */
.framing = 0x00, /* Unframed */
@@ -366,14 +372,14 @@ class BroadcastStateMachineImpl : public BroadcastStateMachine {
: std::array<uint8_t, 16>({0}),
};
- IsoManager::GetInstance()->CreateBig(GetInstanceId(),
+ IsoManager::GetInstance()->CreateBig(GetAdvertisingSid(),
std::move(big_params));
}
void DisableAnnouncement(void) {
- DLOG(INFO) << __func__ << "instance_id: " << int{instance_id_};
+ LOG_INFO("broadcast_id=%d", GetBroadcastId());
advertiser_if_->Enable(
- GetInstanceId(), false,
+ GetAdvertisingSid(), false,
base::Bind(&BroadcastStateMachineImpl::EnableAnnouncementCb,
base::Unretained(this), false),
0, 0,
@@ -382,16 +388,16 @@ class BroadcastStateMachineImpl : public BroadcastStateMachine {
}
void TerminateBig() {
- DLOG(INFO) << __func__ << "suspending: " << suspending_;
+ LOG_INFO("suspending=%d", suspending_);
/* Terminate with reason: Connection Terminated By Local Host */
- IsoManager::GetInstance()->TerminateBig(GetInstanceId(), 0x16);
+ IsoManager::GetInstance()->TerminateBig(GetAdvertisingSid(), 0x16);
}
void OnSetupIsoDataPath(uint8_t status, uint16_t conn_hdl) override {
LOG_ASSERT(active_config_ != std::nullopt);
if (status != 0) {
- DLOG(ERROR) << "Failure creating data path. Tearing down the BIG now.";
+ LOG_ERROR("Failure creating data path. Tearing down the BIG now.");
suspending_ = true;
TerminateBig();
return;
@@ -409,11 +415,12 @@ class BroadcastStateMachineImpl : public BroadcastStateMachine {
/* It was the last BIS to set up - change state to streaming */
SetState(State::STREAMING);
callbacks_->OnStateMachineEvent(
- GetInstanceId(), GetState(),
+ GetBroadcastId(), GetState(),
&sm_config_.codec_wrapper.GetLeAudioCodecConfiguration());
} else {
/* Note: We would feed a watchdog here if we had one */
/* There are more BISes to set up data path for */
+ LOG_INFO("There is more data paths to set up.");
TriggerIsoDatapathSetup(*handle_it);
}
}
@@ -422,7 +429,7 @@ class BroadcastStateMachineImpl : public BroadcastStateMachine {
LOG_ASSERT(active_config_ != std::nullopt);
if (status != 0) {
- DLOG(ERROR) << "Failure removing data path. Tearing down the BIG now.";
+ LOG_ERROR("Failure removing data path. Tearing down the BIG now.");
TerminateBig();
return;
}
@@ -441,11 +448,13 @@ class BroadcastStateMachineImpl : public BroadcastStateMachine {
} else {
/* Note: We would feed a watchdog here if we had one */
/* There are more BISes to tear down data path for */
+ LOG_INFO("There is more data paths to tear down.");
TriggerIsoDatapathTeardown(*handle_it);
}
}
void TriggerIsoDatapathSetup(uint16_t conn_handle) {
+ LOG_INFO("conn_hdl=%d", conn_handle);
LOG_ASSERT(active_config_ != std::nullopt);
/* Note: For the LC3 software encoding on the Host side, the coding format
@@ -474,7 +483,7 @@ class BroadcastStateMachineImpl : public BroadcastStateMachine {
}
void TriggerIsoDatapathTeardown(uint16_t conn_handle) {
- LOG(INFO) << __func__;
+ LOG_INFO("conn_hdl=%d", conn_handle);
LOG_ASSERT(active_config_ != std::nullopt);
SetMuted(true);
@@ -487,16 +496,14 @@ class BroadcastStateMachineImpl : public BroadcastStateMachine {
case HCI_BLE_CREATE_BIG_CPL_EVT: {
auto* evt = static_cast<big_create_cmpl_evt*>(data);
- if (evt->big_id != GetInstanceId()) {
- LOG(ERROR) << __func__ << " State=" << GetState()
- << " Event=" << +event
- << " Unknown big, big_id= " << +evt->big_id;
+ if (evt->big_id != GetAdvertisingSid()) {
+ LOG_ERROR("State=%s, Event=%d, Unknown big, big_id=%d",
+ ToString(GetState()).c_str(), event, evt->big_id);
break;
}
if (evt->status == 0x00) {
- DLOG(INFO) << __func__
- << " BIG create BIG cmpl, big_id=" << +evt->big_id;
+ LOG_INFO("BIG create BIG complete, big_id=%d", evt->big_id);
active_config_ = {
.status = evt->status,
.big_id = evt->big_id,
@@ -513,23 +520,20 @@ class BroadcastStateMachineImpl : public BroadcastStateMachine {
};
TriggerIsoDatapathSetup(evt->conn_handles[0]);
} else {
- LOG(ERROR) << __func__ << " State=" << GetState()
- << " Event=" << +event
- << ". Unable to create big, big_id= " << +evt->big_id
- << ", status=" << +evt->status;
+ LOG_ERROR(
+ "State=%s Event=%d. Unable to create big, big_id=%d, status=%d",
+ ToString(GetState()).c_str(), event, evt->big_id, evt->status);
}
} break;
case HCI_BLE_TERM_BIG_CPL_EVT: {
auto* evt = static_cast<big_terminate_cmpl_evt*>(data);
- DLOG(INFO) << __func__
- << " BIG terminate BIG cmpl, reason=" << int{evt->reason}
- << " big_id=" << int{evt->big_id};
+ LOG_INFO("BIG terminate BIG cmpl, reason=%d big_id=%d", evt->reason,
+ evt->big_id);
- if (evt->big_id != GetInstanceId()) {
- LOG(ERROR) << __func__ << " State=" << GetState()
- << " Event=" << +event
- << " Unknown instance= " << +evt->big_id;
+ if (evt->big_id != GetAdvertisingSid()) {
+ LOG_ERROR("State=%s Event=%d, unknown adv.sid=%d",
+ ToString(GetState()).c_str(), event, evt->big_id);
break;
}
@@ -540,15 +544,15 @@ class BroadcastStateMachineImpl : public BroadcastStateMachine {
/* Check if we got this HCI event due to STOP or SUSPEND message. */
if (suspending_) {
- callbacks_->OnStateMachineEvent(GetInstanceId(), GetState(), evt);
+ callbacks_->OnStateMachineEvent(GetBroadcastId(), GetState(), evt);
suspending_ = false;
} else {
DisableAnnouncement();
}
} break;
default:
- LOG(ERROR) << __func__ << " State=" << GetState()
- << " Unknown event= " << int{event};
+ LOG_ERROR("State=%s Unknown event=%d", ToString(GetState()).c_str(),
+ event);
break;
}
}
@@ -569,19 +573,22 @@ void BroadcastStateMachine::Initialize(
BroadcastStateMachineImpl::callbacks_ = callbacks;
/* Get BLE advertiser interface */
if (BleAdvertisingManager::IsInitialized()) {
- DLOG(INFO) << __func__ << " BleAdvertisingManager acquired";
+ LOG_INFO("BleAdvertisingManager acquired");
BroadcastStateMachineImpl::advertiser_if_ = BleAdvertisingManager::Get();
} else {
- LOG(ERROR) << __func__ << " Could not acquire BleAdvertisingManager!";
+ LOG_INFO("Could not acquire BleAdvertisingManager!");
BroadcastStateMachineImpl::advertiser_if_ = nullptr;
}
}
+namespace le_audio {
+namespace broadcaster {
+
std::ostream& operator<<(std::ostream& os,
- const BroadcastStateMachine::Message& state) {
+ const BroadcastStateMachine::Message& msg) {
static const char* char_value_[BroadcastStateMachine::MESSAGE_COUNT] = {
"START", "SUSPEND", "STOP"};
- os << char_value_[static_cast<uint8_t>(state)];
+ os << char_value_[static_cast<uint8_t>(msg)];
return os;
}
@@ -593,17 +600,78 @@ std::ostream& operator<<(std::ostream& os,
return os;
}
+std::ostream& operator<<(std::ostream& os,
+ const le_audio::broadcaster::BigConfig& config) {
+ os << "\n";
+ os << " Status: 0x" << std::hex << +config.status << std::dec << "\n";
+ os << " BIG ID: " << +config.big_id << "\n";
+ os << " Sync delay: " << config.big_sync_delay << "\n";
+ os << " Transport Latency: " << config.transport_latency_big << "\n";
+ os << " Phy: " << +config.phy << "\n";
+ os << " Nse: " << +config.nse << "\n";
+ os << " Bn: " << +config.bn << "\n";
+ os << " Pto: " << +config.pto << "\n";
+ os << " Irc: " << +config.irc << "\n";
+ os << " Max pdu: " << config.max_pdu << "\n";
+ os << " Iso interval: " << config.iso_interval << "\n";
+ os << " Connection handles (BISes): [";
+ for (auto& el : config.connection_handles) {
+ os << std::hex << +el << std::dec << ":";
+ }
+ os << "]";
+ return os;
+}
+
+std::ostream& operator<<(
+ std::ostream& os,
+ const le_audio::broadcaster::BroadcastStateMachineConfig& config) {
+ const char* const PHYS[] = {"NONE", "1M", "2M", "CODED"};
+
+ os << "\n";
+ os << " Broadcast ID: " << config.broadcast_id << "\n";
+ os << " Streaming PHY: "
+ << ((config.streaming_phy > 3) ? std::to_string(config.streaming_phy)
+ : PHYS[config.streaming_phy])
+ << "\n";
+ os << " Codec Wrapper: " << config.codec_wrapper << "\n";
+ if (config.broadcast_code) {
+ os << " Broadcast Code: [";
+ for (auto& el : *config.broadcast_code) {
+ os << std::hex << +el << ":";
+ }
+ os << "]\n";
+ } else {
+ os << " Broadcast Code: NONE\n";
+ }
+
+ std::vector<uint8_t> an_raw;
+ config.announcement.ToRawPacket(an_raw);
+ os << " Announcement RAW: [";
+ for (auto& el : an_raw) {
+ os << std::hex << +el << ":";
+ }
+ os << "]";
+
+ return os;
+}
+
std::ostream& operator<<(
std::ostream& os,
const le_audio::broadcaster::BroadcastStateMachine& machine) {
os << " Broadcast state machine: {"
- << " State: " << machine.GetState()
- << " Instance ID: " << +machine.GetInstanceId() << "\n"
- << " Codec Config: " << machine.GetCodecConfig() << "\n";
- os << " Broadcast ID: [";
- for (auto& el : machine.GetBroadcastId()) {
- os << std::hex << +el << ":";
+ << " Advertising SID: " << +machine.GetAdvertisingSid() << "\n"
+ << " State: " << machine.GetState() << "\n";
+ os << " State Machine Config: " << machine.GetStateMachineConfig()
+ << "\n";
+
+ if (machine.GetBigConfig()) {
+ os << " BigConfig: " << *machine.GetBigConfig() << "\n";
+ } else {
+ os << " BigConfig: NONE\n";
}
- os << "]}\n";
+ os << " }\n";
return os;
}
+
+} // namespace broadcaster
+} // namespace le_audio
diff --git a/system/bta/le_audio/broadcaster/state_machine.h b/system/bta/le_audio/broadcaster/state_machine.h
index 5877a8c445..260f846305 100644
--- a/system/bta/le_audio/broadcaster/state_machine.h
+++ b/system/bta/le_audio/broadcaster/state_machine.h
@@ -103,7 +103,7 @@ struct BroadcastStateMachineConfig {
class BroadcastStateMachine : public StateMachine<5> {
public:
- static constexpr uint8_t kInstanceIdUndefined = 0xFF;
+ static constexpr uint8_t kAdvSidUndefined = 0xFF;
static constexpr uint8_t kPaIntervalMax = 0xA0; /* 160 * 0.625 = 100ms */
static constexpr uint8_t kPaIntervalMin = 0x50; /* 80 * 0.625 = 50ms */
@@ -133,11 +133,12 @@ class BroadcastStateMachine : public StateMachine<5> {
return static_cast<State>(StateMachine::GetState());
}
- inline uint8_t GetInstanceId() const { return instance_id_; }
+ inline uint8_t GetAdvertisingSid() const { return advertising_sid_; }
virtual bool Initialize() = 0;
virtual const BroadcastCodecWrapper& GetCodecConfig() const = 0;
- virtual std::optional<BigConfig> const& GetBigConfig() = 0;
+ virtual std::optional<BigConfig> const& GetBigConfig() const = 0;
+ virtual BroadcastStateMachineConfig const& GetStateMachineConfig() const = 0;
virtual void RequestOwnAddress(
base::Callback<void(uint8_t /* address_type*/, RawAddress /*address*/)>
cb) = 0;
@@ -146,7 +147,7 @@ class BroadcastStateMachine : public StateMachine<5> {
virtual uint8_t GetOwnAddressType() = 0;
virtual std::optional<bluetooth::le_audio::BroadcastCode> GetBroadcastCode()
const = 0;
- virtual bluetooth::le_audio::BroadcastId const& GetBroadcastId() const = 0;
+ virtual bluetooth::le_audio::BroadcastId GetBroadcastId() const = 0;
virtual void UpdateBroadcastAnnouncement(
BasicAudioAnnouncementData announcement) = 0;
void SetMuted(bool muted) { is_muted_ = muted; };
@@ -167,7 +168,7 @@ class BroadcastStateMachine : public StateMachine<5> {
static_cast<std::underlying_type<State>::type>(state));
}
- uint8_t instance_id_ = kInstanceIdUndefined;
+ uint8_t advertising_sid_ = kAdvSidUndefined;
bool is_muted_ = false;
RawAddress addr_ = RawAddress::kEmpty;
@@ -178,22 +179,19 @@ class IBroadcastStateMachineCallbacks {
public:
IBroadcastStateMachineCallbacks() = default;
virtual ~IBroadcastStateMachineCallbacks() = default;
- virtual void OnStateMachineCreateStatus(uint8_t instance_id,
+ virtual void OnStateMachineCreateStatus(uint32_t broadcast_id,
bool initialized) = 0;
- virtual void OnStateMachineDestroyed(uint8_t instance_id) = 0;
- virtual void OnStateMachineEvent(uint8_t instance_id,
+ virtual void OnStateMachineDestroyed(uint32_t broadcast_id) = 0;
+ virtual void OnStateMachineEvent(uint32_t broadcast_id,
BroadcastStateMachine::State state,
const void* data = nullptr) = 0;
- virtual void OnOwnAddressResponse(uint8_t instance_id, uint8_t addr_type,
+ virtual void OnOwnAddressResponse(uint32_t broadcast_id, uint8_t addr_type,
RawAddress address) = 0;
- virtual uint8_t GetNumRetransmit(uint8_t instance_id) = 0;
- virtual uint32_t GetSduItv(uint8_t instance_id) = 0;
- virtual uint16_t GetMaxTransportLatency(uint8_t instance_id) = 0;
+ virtual uint8_t GetNumRetransmit(uint32_t broadcast_id) = 0;
+ virtual uint32_t GetSduItv(uint32_t broadcast_id) = 0;
+ virtual uint16_t GetMaxTransportLatency(uint32_t broadcast_id) = 0;
};
-} /* namespace broadcaster */
-} /* namespace le_audio */
-
std::ostream& operator<<(
std::ostream& os,
const le_audio::broadcaster::BroadcastStateMachine::Message& state);
@@ -205,3 +203,13 @@ std::ostream& operator<<(
std::ostream& operator<<(
std::ostream& os,
const le_audio::broadcaster::BroadcastStateMachine& machine);
+
+std::ostream& operator<<(std::ostream& os,
+ const le_audio::broadcaster::BigConfig& machine);
+
+std::ostream& operator<<(
+ std::ostream& os,
+ const le_audio::broadcaster::BroadcastStateMachineConfig& machine);
+
+} /* namespace broadcaster */
+} /* namespace le_audio */
diff --git a/system/bta/le_audio/broadcaster/state_machine_test.cc b/system/bta/le_audio/broadcaster/state_machine_test.cc
index f6cf786e58..206487de0c 100644
--- a/system/bta/le_audio/broadcaster/state_machine_test.cc
+++ b/system/bta/le_audio/broadcaster/state_machine_test.cc
@@ -61,19 +61,19 @@ class MockBroadcastStatMachineCallbacks
~MockBroadcastStatMachineCallbacks() override = default;
MOCK_METHOD((void), OnStateMachineCreateStatus,
- (uint8_t instance_id, bool initialized), (override));
- MOCK_METHOD((void), OnStateMachineDestroyed, (uint8_t instance_id),
+ (uint32_t broadcast_id, bool initialized), (override));
+ MOCK_METHOD((void), OnStateMachineDestroyed, (uint32_t broadcast_id),
(override));
MOCK_METHOD((void), OnStateMachineEvent,
- (uint8_t instance_id, BroadcastStateMachine::State state,
+ (uint32_t broadcast_id, BroadcastStateMachine::State state,
const void* data),
(override));
MOCK_METHOD((void), OnOwnAddressResponse,
- (uint8_t instance_id, uint8_t addr_type, RawAddress addr),
+ (uint32_t broadcast_id, uint8_t addr_type, RawAddress addr),
(override));
- MOCK_METHOD((uint8_t), GetNumRetransmit, (uint8_t instance_id), (override));
- MOCK_METHOD((uint32_t), GetSduItv, (uint8_t instance_id), (override));
- MOCK_METHOD((uint16_t), GetMaxTransportLatency, (uint8_t instance_id),
+ MOCK_METHOD((uint8_t), GetNumRetransmit, (uint32_t broadcast_id), (override));
+ MOCK_METHOD((uint32_t), GetSduItv, (uint32_t broadcast_id), (override));
+ MOCK_METHOD((uint16_t), GetMaxTransportLatency, (uint32_t broadcast_id),
(override));
};
@@ -125,25 +125,25 @@ class StateMachineTest : public Test {
});
ON_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus)
- .WillByDefault([this](uint8_t instance_id, bool initialized) {
+ .WillByDefault([this](uint32_t broadcast_id, bool initialized) {
auto instance_it =
std::find_if(pending_broadcasts_.begin(),
- pending_broadcasts_.end(), [instance_id](auto& up) {
- return (up->GetInstanceId() == instance_id);
+ pending_broadcasts_.end(), [broadcast_id](auto& up) {
+ return (up->GetBroadcastId() == broadcast_id);
});
if (instance_it != pending_broadcasts_.end()) {
if (initialized) {
- broadcasts_[instance_id] = std::move(*instance_it);
+ broadcasts_[broadcast_id] = std::move(*instance_it);
}
pending_broadcasts_.erase(instance_it);
}
- instance_creation_promise_.set_value(instance_id);
+ instance_creation_promise_.set_value(broadcast_id);
});
ON_CALL(*(sm_callbacks_.get()), OnStateMachineDestroyed)
- .WillByDefault([this](uint8_t instance_id) {
- if (broadcasts_.count(instance_id)) {
- instance_destruction_promise_.set_value(instance_id);
+ .WillByDefault([this](uint32_t broadcast_id) {
+ if (broadcasts_.count(broadcast_id)) {
+ instance_destruction_promise_.set_value(broadcast_id);
}
});
@@ -160,44 +160,69 @@ class StateMachineTest : public Test {
ON_CALL(*mock_iso_manager_, CreateBig)
.WillByDefault([this](uint8_t big_id, big_create_params p) {
- if (!broadcasts_[big_id]) return;
+ auto bit =
+ std::find_if(broadcasts_.begin(), broadcasts_.end(),
+ [big_id](auto const& entry) {
+ return entry.second->GetAdvertisingSid() == big_id;
+ });
+ if (bit == broadcasts_.end()) return;
big_create_cmpl_evt evt;
evt.big_id = big_id;
- // For test convenience lets encode big_id into conn_hdl's
- // MSB
+ // For test convenience lets encode big_id into conn_hdl MSB.
+ // NOTE: In current implementation big_id is equal to advertising SID.
+ // This is an important detail exploited by the IsoManager mock
static uint8_t conn_lsb = 1;
uint16_t conn_msb = ((uint16_t)big_id) << 8;
for (auto i = 0; i < p.num_bis; ++i) {
evt.conn_handles.push_back(conn_msb | conn_lsb++);
}
- broadcasts_[big_id]->HandleHciEvent(HCI_BLE_CREATE_BIG_CPL_EVT, &evt);
+ bit->second->HandleHciEvent(HCI_BLE_CREATE_BIG_CPL_EVT, &evt);
});
ON_CALL(*mock_iso_manager_, SetupIsoDataPath)
.WillByDefault([this](uint16_t conn_handle, iso_data_path_params p) {
// Get the big_id encoded in conn_handle's MSB
- if (!broadcasts_[conn_handle >> 8]) return;
- broadcasts_[conn_handle >> 8]->OnSetupIsoDataPath(0, conn_handle);
+ uint8_t big_id = conn_handle >> 8;
+ auto bit =
+ std::find_if(broadcasts_.begin(), broadcasts_.end(),
+ [big_id](auto const& entry) {
+ return entry.second->GetAdvertisingSid() == big_id;
+ });
+ if (bit == broadcasts_.end()) return;
+ bit->second->OnSetupIsoDataPath(0, conn_handle);
});
ON_CALL(*mock_iso_manager_, RemoveIsoDataPath)
.WillByDefault([this](uint16_t conn_handle, uint8_t iso_direction) {
// Get the big_id encoded in conn_handle's MSB
- if (!broadcasts_[conn_handle >> 8]) return;
- broadcasts_[conn_handle >> 8]->OnRemoveIsoDataPath(0, conn_handle);
+ uint8_t big_id = conn_handle >> 8;
+ auto bit =
+ std::find_if(broadcasts_.begin(), broadcasts_.end(),
+ [big_id](auto const& entry) {
+ return entry.second->GetAdvertisingSid() == big_id;
+ });
+ if (bit == broadcasts_.end()) return;
+ bit->second->OnRemoveIsoDataPath(0, conn_handle);
});
ON_CALL(*mock_iso_manager_, TerminateBig)
.WillByDefault([this](uint8_t big_id, uint8_t reason) {
- if (!broadcasts_[big_id]) return;
+ // Get the big_id encoded in conn_handle's MSB
+ auto bit =
+ std::find_if(broadcasts_.begin(), broadcasts_.end(),
+ [big_id](auto const& entry) {
+ return entry.second->GetAdvertisingSid() == big_id;
+ });
+ if (bit == broadcasts_.end()) return;
+
big_terminate_cmpl_evt evt;
evt.big_id = big_id;
evt.reason = reason;
- broadcasts_[big_id]->HandleHciEvent(HCI_BLE_TERM_BIG_CPL_EVT, &evt);
+ bit->second->HandleHciEvent(HCI_BLE_TERM_BIG_CPL_EVT, &evt);
});
}
@@ -209,21 +234,22 @@ class StateMachineTest : public Test {
sm_callbacks_.reset();
}
- uint8_t InstantiateStateMachine(
+ uint32_t InstantiateStateMachine(
LeAudioBroadcaster::AudioProfile profile =
LeAudioBroadcaster::AudioProfile::SONIFICATION) {
// We will get the state machine create status update in an async callback
// so let's wait for it here.
- instance_creation_promise_ = std::promise<uint8_t>();
- std::future<uint8_t> instance_future =
+ instance_creation_promise_ = std::promise<uint32_t>();
+ std::future<uint32_t> instance_future =
instance_creation_promise_.get_future();
static uint8_t broadcast_id_lsb = 1;
auto codec_wrapper =
BroadcastCodecWrapper::getCodecConfigForProfile(profile);
+ auto broadcast_id = broadcast_id_lsb++;
pending_broadcasts_.push_back(BroadcastStateMachine::CreateInstance({
- .broadcast_id = {0, 0, broadcast_id_lsb++},
+ .broadcast_id = broadcast_id,
// .streaming_phy = ,
.codec_wrapper = std::move(codec_wrapper),
// .announcement = ,
@@ -239,10 +265,10 @@ class StateMachineTest : public Test {
IsoManager* iso_manager_;
MockIsoManager* mock_iso_manager_;
- std::map<uint8_t, std::unique_ptr<BroadcastStateMachine>> broadcasts_;
+ std::map<uint32_t, std::unique_ptr<BroadcastStateMachine>> broadcasts_;
std::vector<std::unique_ptr<BroadcastStateMachine>> pending_broadcasts_;
std::unique_ptr<MockBroadcastStatMachineCallbacks> sm_callbacks_;
- std::promise<uint8_t> instance_creation_promise_;
+ std::promise<uint32_t> instance_creation_promise_;
std::promise<uint8_t> instance_destruction_promise_;
};
@@ -265,8 +291,8 @@ TEST_F(StateMachineTest, CreateInstanceFailed) {
EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, false))
.Times(1);
- uint8_t instance_id = InstantiateStateMachine();
- ASSERT_NE(instance_id, BroadcastStateMachine::kInstanceIdUndefined);
+ auto broadcast_id = InstantiateStateMachine();
+ ASSERT_NE(broadcast_id, BroadcastStateMachine::kAdvSidUndefined);
ASSERT_TRUE(pending_broadcasts_.empty());
ASSERT_TRUE(broadcasts_.empty());
}
@@ -289,8 +315,8 @@ TEST_F(StateMachineTest, CreateInstanceTimeout) {
EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, false))
.Times(1);
- uint8_t instance_id = InstantiateStateMachine();
- ASSERT_NE(instance_id, BroadcastStateMachine::kInstanceIdUndefined);
+ auto broadcast_id = InstantiateStateMachine();
+ ASSERT_NE(broadcast_id, BroadcastStateMachine::kAdvSidUndefined);
ASSERT_TRUE(pending_broadcasts_.empty());
ASSERT_TRUE(broadcasts_.empty());
}
@@ -299,12 +325,12 @@ TEST_F(StateMachineTest, CreateInstanceSuccess) {
EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, true))
.Times(1);
- uint8_t instance_id = InstantiateStateMachine();
- ASSERT_NE(instance_id, BroadcastStateMachine::kInstanceIdUndefined);
+ auto broadcast_id = InstantiateStateMachine();
+ ASSERT_NE(broadcast_id, BroadcastStateMachine::kAdvSidUndefined);
ASSERT_TRUE(pending_broadcasts_.empty());
ASSERT_FALSE(broadcasts_.empty());
- ASSERT_EQ(broadcasts_[instance_id]->GetInstanceId(), instance_id);
- ASSERT_EQ(broadcasts_[instance_id]->GetState(),
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetBroadcastId(), broadcast_id);
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
BroadcastStateMachine::State::CONFIGURED);
}
@@ -312,8 +338,8 @@ TEST_F(StateMachineTest, DestroyInstanceSuccess) {
EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, true))
.Times(1);
- uint8_t instance_id = InstantiateStateMachine();
- ASSERT_NE(instance_id, BroadcastStateMachine::kInstanceIdUndefined);
+ auto broadcast_id = InstantiateStateMachine();
+ ASSERT_NE(broadcast_id, BroadcastStateMachine::kAdvSidUndefined);
ASSERT_FALSE(broadcasts_.empty());
instance_destruction_promise_ = std::promise<uint8_t>();
@@ -321,32 +347,32 @@ TEST_F(StateMachineTest, DestroyInstanceSuccess) {
instance_destruction_promise_.get_future();
broadcasts_.clear();
- EXPECT_EQ(instance_future.get(), instance_id);
+ EXPECT_EQ(instance_future.get(), broadcast_id);
}
TEST_F(StateMachineTest, GetAdvertisingAddress) {
EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, true))
.Times(1);
- uint8_t instance_id = InstantiateStateMachine();
- EXPECT_CALL(*(sm_callbacks_.get()), OnOwnAddressResponse(instance_id, _, _))
+ auto broadcast_id = InstantiateStateMachine();
+ EXPECT_CALL(*(sm_callbacks_.get()), OnOwnAddressResponse(broadcast_id, _, _))
.Times(1);
- broadcasts_[instance_id]->RequestOwnAddress();
+ broadcasts_[broadcast_id]->RequestOwnAddress();
}
TEST_F(StateMachineTest, Mute) {
EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, true))
.Times(1);
- uint8_t instance_id = InstantiateStateMachine();
+ auto broadcast_id = InstantiateStateMachine();
ASSERT_TRUE(pending_broadcasts_.empty());
ASSERT_FALSE(broadcasts_.empty());
- ASSERT_FALSE(broadcasts_[instance_id]->IsMuted());
- broadcasts_[instance_id]->SetMuted(true);
- ASSERT_TRUE(broadcasts_[instance_id]->IsMuted());
- broadcasts_[instance_id]->SetMuted(false);
- ASSERT_FALSE(broadcasts_[instance_id]->IsMuted());
+ ASSERT_FALSE(broadcasts_[broadcast_id]->IsMuted());
+ broadcasts_[broadcast_id]->SetMuted(true);
+ ASSERT_TRUE(broadcasts_[broadcast_id]->IsMuted());
+ broadcasts_[broadcast_id]->SetMuted(false);
+ ASSERT_FALSE(broadcasts_[broadcast_id]->IsMuted());
}
static BasicAudioAnnouncementData prepareAnnouncement(
@@ -381,7 +407,7 @@ TEST_F(StateMachineTest, UpdateAnnouncement) {
EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, true))
.Times(1);
- uint8_t instance_id = InstantiateStateMachine();
+ auto broadcast_id = InstantiateStateMachine();
std::vector<uint8_t> metadata = {};
BroadcastCodecWrapper codec_config(
{.coding_format = le_audio::types::kLeAudioCodingFormatLC3,
@@ -394,12 +420,13 @@ TEST_F(StateMachineTest, UpdateAnnouncement) {
32000, 40);
auto announcement = prepareAnnouncement(codec_config, metadata);
+ auto adv_sid = broadcasts_[broadcast_id]->GetAdvertisingSid();
std::vector<uint8_t> data;
EXPECT_CALL(*mock_ble_advertising_manager_,
- SetPeriodicAdvertisingData(instance_id, _, _))
+ SetPeriodicAdvertisingData(adv_sid, _, _))
.Times(2)
.WillRepeatedly(SaveArg<1>(&data));
- broadcasts_[instance_id]->UpdateBroadcastAnnouncement(
+ broadcasts_[broadcast_id]->UpdateBroadcastAnnouncement(
std::move(announcement));
uint8_t first_len = data.size();
@@ -412,7 +439,7 @@ TEST_F(StateMachineTest, UpdateAnnouncement) {
// Verify that changes in the announcement makes a difference
metadata = {0x02, 0x01, 0x03};
announcement = prepareAnnouncement(codec_config, metadata);
- broadcasts_[instance_id]->UpdateBroadcastAnnouncement(
+ broadcasts_[broadcast_id]->UpdateBroadcastAnnouncement(
std::move(announcement));
uint8_t second_len = data.size();
@@ -427,14 +454,19 @@ TEST_F(StateMachineTest, ProcessMessageStartWhenConfigured) {
auto sound_profile = LeAudioBroadcaster::AudioProfile::MEDIA;
uint8_t num_channels = 2;
- uint8_t instance_id = InstantiateStateMachine(sound_profile);
- ASSERT_EQ(broadcasts_[instance_id]->GetState(),
+ auto broadcast_id = InstantiateStateMachine(sound_profile);
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
BroadcastStateMachine::State::CONFIGURED);
uint8_t num_bises = 0;
EXPECT_CALL(*mock_iso_manager_, CreateBig)
.WillOnce([this, &num_bises](uint8_t big_id, big_create_params p) {
- if (!broadcasts_[big_id]) return;
+ auto bit =
+ std::find_if(broadcasts_.begin(), broadcasts_.end(),
+ [big_id](auto const& entry) {
+ return entry.second->GetAdvertisingSid() == big_id;
+ });
+ if (bit == broadcasts_.end()) return;
num_bises = p.num_bis;
@@ -449,21 +481,21 @@ TEST_F(StateMachineTest, ProcessMessageStartWhenConfigured) {
evt.conn_handles.push_back(conn_msb | conn_lsb++);
}
- broadcasts_[big_id]->HandleHciEvent(HCI_BLE_CREATE_BIG_CPL_EVT, &evt);
+ bit->second->HandleHciEvent(HCI_BLE_CREATE_BIG_CPL_EVT, &evt);
});
EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath).Times(num_channels);
EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath).Times(0);
EXPECT_CALL(*(sm_callbacks_.get()),
- OnStateMachineEvent(instance_id,
+ OnStateMachineEvent(broadcast_id,
BroadcastStateMachine::State::STREAMING, _))
.Times(1);
- broadcasts_[instance_id]->ProcessMessage(
+ broadcasts_[broadcast_id]->ProcessMessage(
BroadcastStateMachine::Message::START);
// Verify the right number of BISes in the BIG being created
ASSERT_EQ(num_bises, num_channels);
- ASSERT_EQ(broadcasts_[instance_id]->GetState(),
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
BroadcastStateMachine::State::STREAMING);
}
@@ -471,25 +503,25 @@ TEST_F(StateMachineTest, ProcessMessageStopWhenConfigured) {
EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, true))
.Times(1);
- uint8_t instance_id =
+ auto broadcast_id =
InstantiateStateMachine(LeAudioBroadcaster::AudioProfile::MEDIA);
- ASSERT_EQ(broadcasts_[instance_id]->GetState(),
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
BroadcastStateMachine::State::CONFIGURED);
EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath).Times(0);
EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath).Times(0);
EXPECT_CALL(*(sm_callbacks_.get()),
- OnStateMachineEvent(instance_id,
+ OnStateMachineEvent(broadcast_id,
BroadcastStateMachine::State::STOPPING, _))
.Times(1);
EXPECT_CALL(*(sm_callbacks_.get()),
- OnStateMachineEvent(instance_id,
+ OnStateMachineEvent(broadcast_id,
BroadcastStateMachine::State::STOPPED, _))
.Times(1);
- broadcasts_[instance_id]->ProcessMessage(
+ broadcasts_[broadcast_id]->ProcessMessage(
BroadcastStateMachine::Message::STOP);
- ASSERT_EQ(broadcasts_[instance_id]->GetState(),
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
BroadcastStateMachine::State::STOPPED);
}
@@ -497,156 +529,156 @@ TEST_F(StateMachineTest, ProcessMessageSuspendWhenConfigured) {
EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, true))
.Times(1);
- uint8_t instance_id =
+ auto broadcast_id =
InstantiateStateMachine(LeAudioBroadcaster::AudioProfile::MEDIA);
- ASSERT_EQ(broadcasts_[instance_id]->GetState(),
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
BroadcastStateMachine::State::CONFIGURED);
EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath).Times(0);
EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath).Times(0);
- EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineEvent(instance_id, _, _))
+ EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineEvent(broadcast_id, _, _))
.Times(0);
- broadcasts_[instance_id]->ProcessMessage(
+ broadcasts_[broadcast_id]->ProcessMessage(
BroadcastStateMachine::Message::SUSPEND);
// There shall be no change in state
- ASSERT_EQ(broadcasts_[instance_id]->GetState(),
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
BroadcastStateMachine::State::CONFIGURED);
}
TEST_F(StateMachineTest, ProcessMessageStartWhenStreaming) {
- uint8_t instance_id =
+ auto broadcast_id =
InstantiateStateMachine(LeAudioBroadcaster::AudioProfile::MEDIA);
- broadcasts_[instance_id]->ProcessMessage(
+ broadcasts_[broadcast_id]->ProcessMessage(
BroadcastStateMachine::Message::START);
- ASSERT_EQ(broadcasts_[instance_id]->GetState(),
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
BroadcastStateMachine::State::STREAMING);
EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath).Times(0);
EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath).Times(0);
- EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineEvent(instance_id, _, _))
+ EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineEvent(broadcast_id, _, _))
.Times(0);
- broadcasts_[instance_id]->ProcessMessage(
+ broadcasts_[broadcast_id]->ProcessMessage(
BroadcastStateMachine::Message::START);
// There shall be no change in state
- ASSERT_EQ(broadcasts_[instance_id]->GetState(),
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
BroadcastStateMachine::State::STREAMING);
}
TEST_F(StateMachineTest, ProcessMessageStopWhenStreaming) {
- uint8_t instance_id =
+ auto broadcast_id =
InstantiateStateMachine(LeAudioBroadcaster::AudioProfile::MEDIA);
- broadcasts_[instance_id]->ProcessMessage(
+ broadcasts_[broadcast_id]->ProcessMessage(
BroadcastStateMachine::Message::START);
- ASSERT_EQ(broadcasts_[instance_id]->GetState(),
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
BroadcastStateMachine::State::STREAMING);
EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath).Times(0);
EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath).Times(2);
EXPECT_CALL(*(sm_callbacks_.get()),
- OnStateMachineEvent(instance_id,
+ OnStateMachineEvent(broadcast_id,
BroadcastStateMachine::State::STOPPING, _))
.Times(1);
EXPECT_CALL(*(sm_callbacks_.get()),
- OnStateMachineEvent(instance_id,
+ OnStateMachineEvent(broadcast_id,
BroadcastStateMachine::State::STOPPED, _))
.Times(1);
- broadcasts_[instance_id]->ProcessMessage(
+ broadcasts_[broadcast_id]->ProcessMessage(
BroadcastStateMachine::Message::STOP);
- ASSERT_EQ(broadcasts_[instance_id]->GetState(),
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
BroadcastStateMachine::State::STOPPED);
}
TEST_F(StateMachineTest, ProcessMessageSuspendWhenStreaming) {
- uint8_t instance_id =
+ auto broadcast_id =
InstantiateStateMachine(LeAudioBroadcaster::AudioProfile::MEDIA);
- broadcasts_[instance_id]->ProcessMessage(
+ broadcasts_[broadcast_id]->ProcessMessage(
BroadcastStateMachine::Message::START);
- ASSERT_EQ(broadcasts_[instance_id]->GetState(),
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
BroadcastStateMachine::State::STREAMING);
EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath).Times(0);
EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath).Times(2);
EXPECT_CALL(*(sm_callbacks_.get()),
- OnStateMachineEvent(instance_id,
+ OnStateMachineEvent(broadcast_id,
BroadcastStateMachine::State::CONFIGURED, _))
.Times(1);
- broadcasts_[instance_id]->ProcessMessage(
+ broadcasts_[broadcast_id]->ProcessMessage(
BroadcastStateMachine::Message::SUSPEND);
- ASSERT_EQ(broadcasts_[instance_id]->GetState(),
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
BroadcastStateMachine::State::CONFIGURED);
}
TEST_F(StateMachineTest, ProcessMessageStartWhenStopped) {
- uint8_t instance_id =
+ auto broadcast_id =
InstantiateStateMachine(LeAudioBroadcaster::AudioProfile::MEDIA);
- broadcasts_[instance_id]->ProcessMessage(
+ broadcasts_[broadcast_id]->ProcessMessage(
BroadcastStateMachine::Message::STOP);
- ASSERT_EQ(broadcasts_[instance_id]->GetState(),
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
BroadcastStateMachine::State::STOPPED);
EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath).Times(2);
EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath).Times(0);
EXPECT_CALL(*(sm_callbacks_.get()),
- OnStateMachineEvent(instance_id,
+ OnStateMachineEvent(broadcast_id,
BroadcastStateMachine::State::CONFIGURING, _))
.Times(1);
EXPECT_CALL(*(sm_callbacks_.get()),
- OnStateMachineEvent(instance_id,
+ OnStateMachineEvent(broadcast_id,
BroadcastStateMachine::State::STREAMING, _))
.Times(1);
- broadcasts_[instance_id]->ProcessMessage(
+ broadcasts_[broadcast_id]->ProcessMessage(
BroadcastStateMachine::Message::START);
- ASSERT_EQ(broadcasts_[instance_id]->GetState(),
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
BroadcastStateMachine::State::STREAMING);
}
TEST_F(StateMachineTest, ProcessMessageStopWhenStopped) {
- uint8_t instance_id =
+ auto broadcast_id =
InstantiateStateMachine(LeAudioBroadcaster::AudioProfile::MEDIA);
- broadcasts_[instance_id]->ProcessMessage(
+ broadcasts_[broadcast_id]->ProcessMessage(
BroadcastStateMachine::Message::STOP);
- ASSERT_EQ(broadcasts_[instance_id]->GetState(),
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
BroadcastStateMachine::State::STOPPED);
EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath).Times(0);
EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath).Times(0);
- EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineEvent(instance_id, _, _))
+ EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineEvent(broadcast_id, _, _))
.Times(0);
- broadcasts_[instance_id]->ProcessMessage(
+ broadcasts_[broadcast_id]->ProcessMessage(
BroadcastStateMachine::Message::STOP);
// There shall be no change in state
- ASSERT_EQ(broadcasts_[instance_id]->GetState(),
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
BroadcastStateMachine::State::STOPPED);
}
TEST_F(StateMachineTest, ProcessMessageSuspendWhenStopped) {
- uint8_t instance_id =
+ auto broadcast_id =
InstantiateStateMachine(LeAudioBroadcaster::AudioProfile::MEDIA);
- broadcasts_[instance_id]->ProcessMessage(
+ broadcasts_[broadcast_id]->ProcessMessage(
BroadcastStateMachine::Message::STOP);
- ASSERT_EQ(broadcasts_[instance_id]->GetState(),
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
BroadcastStateMachine::State::STOPPED);
EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath).Times(0);
EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath).Times(0);
- EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineEvent(instance_id, _, _))
+ EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineEvent(broadcast_id, _, _))
.Times(0);
- broadcasts_[instance_id]->ProcessMessage(
+ broadcasts_[broadcast_id]->ProcessMessage(
BroadcastStateMachine::Message::SUSPEND);
// There shall be no change in state
- ASSERT_EQ(broadcasts_[instance_id]->GetState(),
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
BroadcastStateMachine::State::STOPPED);
}
@@ -654,79 +686,109 @@ TEST_F(StateMachineTest, OnSetupIsoDataPathError) {
EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, true))
.Times(1);
- uint8_t instance_id =
+ auto broadcast_id =
InstantiateStateMachine(LeAudioBroadcaster::AudioProfile::MEDIA);
- ASSERT_EQ(broadcasts_[instance_id]->GetState(),
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
BroadcastStateMachine::State::CONFIGURED);
EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath)
.WillOnce([this](uint16_t conn_handle, iso_data_path_params p) {
// Get the big_id encoded in conn_handle's MSB
- if (!broadcasts_[conn_handle >> 8]) return;
- broadcasts_[conn_handle >> 8]->OnSetupIsoDataPath(0, conn_handle);
+ uint8_t big_id = conn_handle >> 8;
+ auto bit =
+ std::find_if(broadcasts_.begin(), broadcasts_.end(),
+ [big_id](auto const& entry) {
+ return entry.second->GetAdvertisingSid() == big_id;
+ });
+ if (bit == broadcasts_.end()) return;
+ bit->second->OnSetupIsoDataPath(0, conn_handle);
})
.WillOnce([this](uint16_t conn_handle, iso_data_path_params p) {
// Get the big_id encoded in conn_handle's MSB
- if (!broadcasts_[conn_handle >> 8]) return;
- broadcasts_[conn_handle >> 8]->OnSetupIsoDataPath(1, conn_handle);
+ uint8_t big_id = conn_handle >> 8;
+ auto bit =
+ std::find_if(broadcasts_.begin(), broadcasts_.end(),
+ [big_id](auto const& entry) {
+ return entry.second->GetAdvertisingSid() == big_id;
+ });
+ if (bit == broadcasts_.end()) return;
+ bit->second->OnSetupIsoDataPath(1, conn_handle);
})
.RetiresOnSaturation();
- broadcasts_[instance_id]->ProcessMessage(
+ broadcasts_[broadcast_id]->ProcessMessage(
BroadcastStateMachine::Message::START);
// On datapath setup failure we should go back to configured with BIG being
// destroyed. Maybe it will work out next time for the new BIG.
- ASSERT_EQ(broadcasts_[instance_id]->GetState(),
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
BroadcastStateMachine::State::CONFIGURED);
// And still be able to start again
ON_CALL(*mock_iso_manager_, SetupIsoDataPath)
.WillByDefault([this](uint16_t conn_handle, iso_data_path_params p) {
// Get the big_id encoded in conn_handle's MSB
- if (!broadcasts_[conn_handle >> 8]) return;
- broadcasts_[conn_handle >> 8]->OnSetupIsoDataPath(0, conn_handle);
+ uint8_t big_id = conn_handle >> 8;
+ auto bit =
+ std::find_if(broadcasts_.begin(), broadcasts_.end(),
+ [big_id](auto const& entry) {
+ return entry.second->GetAdvertisingSid() == big_id;
+ });
+ if (bit == broadcasts_.end()) return;
+ bit->second->OnSetupIsoDataPath(0, conn_handle);
});
EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath).Times(2);
- broadcasts_[instance_id]->ProcessMessage(
+ broadcasts_[broadcast_id]->ProcessMessage(
BroadcastStateMachine::Message::START);
- ASSERT_EQ(broadcasts_[instance_id]->GetState(),
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
BroadcastStateMachine::State::STREAMING);
}
TEST_F(StateMachineTest, OnRemoveIsoDataPathError) {
- uint8_t instance_id =
+ auto broadcast_id =
InstantiateStateMachine(LeAudioBroadcaster::AudioProfile::MEDIA);
- broadcasts_[instance_id]->ProcessMessage(
+ broadcasts_[broadcast_id]->ProcessMessage(
BroadcastStateMachine::Message::START);
- ASSERT_EQ(broadcasts_[instance_id]->GetState(),
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
BroadcastStateMachine::State::STREAMING);
EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath)
.WillOnce([this](uint16_t conn_handle, uint8_t iso_direction) {
// Get the big_id encoded in conn_handle's MSB
- if (!broadcasts_[conn_handle >> 8]) return;
- broadcasts_[conn_handle >> 8]->OnRemoveIsoDataPath(0, conn_handle);
+ uint8_t big_id = conn_handle >> 8;
+ auto bit =
+ std::find_if(broadcasts_.begin(), broadcasts_.end(),
+ [big_id](auto const& entry) {
+ return entry.second->GetAdvertisingSid() == big_id;
+ });
+ if (bit == broadcasts_.end()) return;
+ bit->second->OnRemoveIsoDataPath(0, conn_handle);
})
.WillOnce([this](uint16_t conn_handle, uint8_t iso_direction) {
// Get the big_id encoded in conn_handle's MSB
- if (!broadcasts_[conn_handle >> 8]) return;
- broadcasts_[conn_handle >> 8]->OnRemoveIsoDataPath(1, conn_handle);
+ uint8_t big_id = conn_handle >> 8;
+ auto bit =
+ std::find_if(broadcasts_.begin(), broadcasts_.end(),
+ [big_id](auto const& entry) {
+ return entry.second->GetAdvertisingSid() == big_id;
+ });
+ if (bit == broadcasts_.end()) return;
+ bit->second->OnRemoveIsoDataPath(1, conn_handle);
})
.RetiresOnSaturation();
- broadcasts_[instance_id]->ProcessMessage(
+ broadcasts_[broadcast_id]->ProcessMessage(
BroadcastStateMachine::Message::SUSPEND);
// On datapath teardown failure we should stay in CONFIGURED with BIG being
// destroyed.
- ASSERT_EQ(broadcasts_[instance_id]->GetState(),
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
BroadcastStateMachine::State::CONFIGURED);
// And still be able to start again
- broadcasts_[instance_id]->ProcessMessage(
+ broadcasts_[broadcast_id]->ProcessMessage(
BroadcastStateMachine::Message::START);
- ASSERT_EQ(broadcasts_[instance_id]->GetState(),
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
BroadcastStateMachine::State::STREAMING);
}
@@ -737,22 +799,23 @@ TEST_F(StateMachineTest, GetConfig) {
auto sound_profile = LeAudioBroadcaster::AudioProfile::MEDIA;
uint8_t num_channels = 2;
- uint8_t instance_id = InstantiateStateMachine(sound_profile);
- ASSERT_EQ(broadcasts_[instance_id]->GetState(),
+ auto broadcast_id = InstantiateStateMachine(sound_profile);
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
BroadcastStateMachine::State::CONFIGURED);
std::optional<BigConfig> const& big_cfg =
- broadcasts_[instance_id]->GetBigConfig();
+ broadcasts_[broadcast_id]->GetBigConfig();
ASSERT_FALSE(big_cfg.has_value());
- broadcasts_[instance_id]->ProcessMessage(
+ broadcasts_[broadcast_id]->ProcessMessage(
BroadcastStateMachine::Message::START);
- ASSERT_EQ(broadcasts_[instance_id]->GetState(),
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
BroadcastStateMachine::State::STREAMING);
ASSERT_TRUE(big_cfg.has_value());
ASSERT_EQ(big_cfg->status, 0);
- ASSERT_EQ(big_cfg->big_id, instance_id);
+ // This is an implementation specific thing
+ ASSERT_EQ(big_cfg->big_id, broadcasts_[broadcast_id]->GetAdvertisingSid());
ASSERT_EQ(big_cfg->connection_handles.size(), num_channels);
}
@@ -760,13 +823,10 @@ TEST_F(StateMachineTest, GetBroadcastId) {
EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, true))
.Times(1);
- uint8_t instance_id = InstantiateStateMachine();
- ASSERT_EQ(broadcasts_[instance_id]->GetState(),
+ auto broadcast_id = InstantiateStateMachine();
+ ASSERT_NE(bluetooth::le_audio::kBroadcastIdInvalid, broadcast_id);
+ ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
BroadcastStateMachine::State::CONFIGURED);
-
- bluetooth::le_audio::BroadcastId const& broadcast_id =
- broadcasts_[instance_id]->GetBroadcastId();
- ASSERT_NE(bluetooth::le_audio::kBroadcastBroadcastIdInvalid, broadcast_id);
}
TEST_F(StateMachineTest, AnnouncementUUIDs) {
@@ -798,8 +858,8 @@ TEST_F(StateMachineTest, AnnouncementUUIDs) {
EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, true))
.Times(1);
- uint8_t instance_id = InstantiateStateMachine();
- ASSERT_NE(instance_id, BroadcastStateMachine::kInstanceIdUndefined);
+ auto broadcast_id = InstantiateStateMachine();
+ ASSERT_NE(broadcast_id, BroadcastStateMachine::kAdvSidUndefined);
// Check ext. advertising data for Broadcast Announcement UUID
ASSERT_NE(a_data[0], 0); // size
diff --git a/system/bta/le_audio/client.cc b/system/bta/le_audio/client.cc
index 6dc3364be5..d3274ac39c 100644
--- a/system/bta/le_audio/client.cc
+++ b/system/bta/le_audio/client.cc
@@ -1909,25 +1909,27 @@ class LeAudioClientImpl : public LeAudioClient {
bool mono = (left_cis_handle == 0) || (right_cis_handle == 0);
- LOG(INFO) << __func__ << " data size: " << (int)data.size()
- << " byte count: " << byte_count << " mono: " << mono;
if (!mono) {
- lc3_encode(lc3_encoder_left, (const int16_t*)data.data(), 2,
- chan_left_enc.size(), chan_left_enc.data());
- lc3_encode(lc3_encoder_right, ((const int16_t*)data.data()) + 1, 2,
- chan_right_enc.size(), chan_right_enc.data());
+ lc3_encode(lc3_encoder_left, LC3_PCM_FORMAT_S16,
+ (const int16_t*)data.data(), 2, chan_left_enc.size(),
+ chan_left_enc.data());
+ lc3_encode(lc3_encoder_right, LC3_PCM_FORMAT_S16,
+ ((const int16_t*)data.data()) + 1, 2, chan_right_enc.size(),
+ chan_right_enc.data());
} else {
std::vector<int16_t> chan_mono;
get_mono_stream(data, chan_mono);
if (left_cis_handle) {
- lc3_encode(lc3_encoder_left, (const int16_t*)chan_mono.data(), 1,
- chan_left_enc.size(), chan_left_enc.data());
+ lc3_encode(lc3_encoder_left, LC3_PCM_FORMAT_S16,
+ (const int16_t*)chan_mono.data(), 1, chan_left_enc.size(),
+ chan_left_enc.data());
}
if (right_cis_handle) {
- lc3_encode(lc3_encoder_right, (const int16_t*)chan_mono.data(), 1,
- chan_right_enc.size(), chan_right_enc.data());
+ lc3_encode(lc3_encoder_right, LC3_PCM_FORMAT_S16,
+ (const int16_t*)chan_mono.data(), 1, chan_right_enc.size(),
+ chan_right_enc.data());
}
}
@@ -1968,17 +1970,20 @@ class LeAudioClientImpl : public LeAudioClient {
std::vector<int16_t> chan_mono;
get_mono_stream(data, chan_mono);
- auto err = lc3_encode(lc3_encoder_left, (const int16_t*)chan_mono.data(),
- 1, byte_count, chan_encoded.data());
+ auto err = lc3_encode(lc3_encoder_left, LC3_PCM_FORMAT_S16,
+ (const int16_t*)chan_mono.data(), 1, byte_count,
+ chan_encoded.data());
if (err < 0) {
LOG(ERROR) << " error while encoding, error code: " << +err;
}
} else {
- lc3_encode(lc3_encoder_left, (const int16_t*)data.data(), 2, byte_count,
+ lc3_encode(lc3_encoder_left, LC3_PCM_FORMAT_S16,
+ (const int16_t*)data.data(), 2, byte_count,
chan_encoded.data());
- lc3_encode(lc3_encoder_right, (const int16_t*)data.data() + 1, 2,
- byte_count, chan_encoded.data() + byte_count);
+ lc3_encode(lc3_encoder_right, LC3_PCM_FORMAT_S16,
+ (const int16_t*)data.data() + 1, 2, byte_count,
+ chan_encoded.data() + byte_count);
}
/* Send data to the controller */
@@ -2127,12 +2132,18 @@ class LeAudioClientImpl : public LeAudioClient {
}
}
+ void CleanCachedMicrophoneData() {
+ cached_channel_data_.clear();
+ cached_channel_timestamp_ = 0;
+ cached_channel_is_left_ = false;
+ }
+
void SendAudioData(uint8_t* data, uint16_t size, uint16_t cis_conn_hdl,
uint32_t timestamp) {
/* Get only one channel for MONO microphone */
/* Gather data for channel */
if ((active_group_id_ == bluetooth::groups::kGroupUnknown) ||
- (audio_sender_state_ != AudioState::STARTED))
+ (audio_receiver_state_ != AudioState::STARTED))
return;
LeAudioDeviceGroup* group = aseGroups_.FindById(active_group_id_);
@@ -2202,8 +2213,8 @@ class LeAudioClientImpl : public LeAudioClient {
lc3_decoder_t decoder_to_use =
is_left ? lc3_decoder_left : lc3_decoder_right;
- err = lc3_decode(decoder_to_use, data, size, pcm_data_decoded.data(),
- 1 /* pitch */);
+ err = lc3_decode(decoder_to_use, data, size, LC3_PCM_FORMAT_S16,
+ pcm_data_decoded.data(), 1 /* pitch */);
if (err < 0) {
LOG(ERROR) << " bad decoding parameters: " << static_cast<int>(err);
@@ -2219,9 +2230,9 @@ class LeAudioClientImpl : public LeAudioClient {
&pcm_data_decoded, nullptr);
return;
}
-
/* both devices are connected */
- if (cached_channel_timestamp_ == 0) {
+
+ if (cached_channel_timestamp_ == 0 && cached_channel_data_.empty()) {
/* First packet received, cache it. We need both channel data to send it
* to AF. */
cached_channel_data_ = pcm_data_decoded;
@@ -2245,7 +2256,7 @@ class LeAudioClientImpl : public LeAudioClient {
&pcm_data_decoded, &cached_channel_data_);
}
- cached_channel_timestamp_ = 0;
+ CleanCachedMicrophoneData();
return;
}
@@ -2409,7 +2420,8 @@ class LeAudioClientImpl : public LeAudioClient {
uint16_t remote_delay_ms =
group->GetRemoteDelay(le_audio::types::kLeAudioDirectionSource);
- cached_channel_timestamp_ = 0;
+ CleanCachedMicrophoneData();
+
if (CodecManager::GetInstance()->GetCodecLocation() ==
le_audio::types::CodecLocation::HOST) {
if (lc3_decoder_left_mem) {
diff --git a/system/bta/le_audio/devices.cc b/system/bta/le_audio/devices.cc
index a147aea2fd..58ca4c46c4 100644
--- a/system/bta/le_audio/devices.cc
+++ b/system/bta/le_audio/devices.cc
@@ -958,6 +958,9 @@ bool LeAudioDevice::ConfigureAses(
*ase->codec_config.octets_per_codec_frame *
*ase->codec_config.codec_frames_blocks_per_sdu;
+ ase->retrans_nb = ent.qos.retransmission_number;
+ ase->max_transport_latency = ent.qos.max_transport_latency;
+
ase->metadata = GetMetadata(context_type);
DLOG(INFO) << __func__ << " device=" << address_
diff --git a/system/bta/le_audio/le_audio_set_configuration_provider_json.cc b/system/bta/le_audio/le_audio_set_configuration_provider_json.cc
index 354a81b395..b2fa48156f 100644
--- a/system/bta/le_audio/le_audio_set_configuration_provider_json.cc
+++ b/system/bta/le_audio/le_audio_set_configuration_provider_json.cc
@@ -27,6 +27,7 @@ using le_audio::set_configurations::AudioSetConfiguration;
using le_audio::set_configurations::AudioSetConfigurations;
using le_audio::set_configurations::CodecCapabilitySetting;
using le_audio::set_configurations::LeAudioCodecIdLc3;
+using le_audio::set_configurations::QosConfigSetting;
using le_audio::set_configurations::SetConfiguration;
using le_audio::types::LeAudioContextType;
@@ -199,7 +200,8 @@ struct AudioSetConfigurationProviderJson {
}
SetConfiguration SetConfigurationFromFlatSubconfig(
- const bluetooth::le_audio::AudioSetSubConfiguration* flat_subconfig) {
+ const bluetooth::le_audio::AudioSetSubConfiguration* flat_subconfig,
+ QosConfigSetting qos) {
auto strategy_int =
static_cast<int>(flat_subconfig->configuration_strategy());
@@ -228,21 +230,52 @@ struct AudioSetConfigurationProviderJson {
flat_subconfig->ase_cnt(), target_latency,
CodecCapabilitySettingFromFlat(flat_subconfig->codec_id(),
flat_subconfig->codec_configuration()),
- strategy);
+ qos, strategy);
}
AudioSetConfiguration AudioSetConfigurationFromFlat(
- const bluetooth::le_audio::AudioSetConfiguration* flat_cfg) {
+ const bluetooth::le_audio::AudioSetConfiguration* flat_cfg,
+ std::vector<const bluetooth::le_audio::CodecConfiguration*>* codec_cfgs,
+ std::vector<const bluetooth::le_audio::QosConfiguration*>* qos_cfgs) {
std::vector<SetConfiguration> subconfigs;
- if (flat_cfg->subconfigurations()) {
- /* Load subconfigurations */
- for (auto subconfig : *flat_cfg->subconfigurations()) {
- subconfigs.push_back(SetConfigurationFromFlatSubconfig(subconfig));
+ QosConfigSetting qos;
+ const bluetooth::le_audio::CodecConfiguration* codec_cfg = NULL;
+ const bluetooth::le_audio::QosConfiguration* qos_cfg = NULL;
+
+ const char* codec_config_key = flat_cfg->codec_config_name()->c_str();
+ const char* qos_config_key = flat_cfg->qos_config_name()->c_str();
+
+ for (auto i = qos_cfgs->begin(); i != qos_cfgs->end(); ++i) {
+ if (0 == strcmp((*i)->name()->c_str(), qos_config_key)) {
+ qos_cfg = *i;
+ break;
}
+ }
+ if (qos_cfg != NULL) {
+ qos.retransmission_number = qos_cfg->retransmission_number();
+ qos.max_transport_latency = qos_cfg->max_transport_latency();
+ } else {
+ LOG_ERROR("No qos config matching key %s found", qos_config_key);
+ }
+ for (auto i = codec_cfgs->begin(); i != codec_cfgs->end(); ++i) {
+ if (0 == strcmp((*i)->name()->c_str(), codec_config_key)) {
+ codec_cfg = *i;
+ break;
+ }
+ }
+ if (codec_cfg != NULL && codec_cfg->subconfigurations()) {
+ /* Load subconfigurations */
+ for (auto subconfig : *codec_cfg->subconfigurations()) {
+ subconfigs.push_back(SetConfigurationFromFlatSubconfig(subconfig, qos));
+ }
} else {
- LOG_ERROR("Configuration '%s' has no valid subconfigurations.",
- flat_cfg->name()->c_str());
+ if (codec_cfg == NULL) {
+ LOG_ERROR("No codec config matching key %s found", codec_config_key);
+ } else {
+ LOG_ERROR("Configuration '%s' has no valid subconfigurations.",
+ flat_cfg->name()->c_str());
+ }
}
return AudioSetConfiguration({flat_cfg->name()->c_str(), subconfigs});
@@ -277,13 +310,35 @@ struct AudioSetConfigurationProviderJson {
configurations_parser_.builder_.GetBufferPointer());
if (!configurations_root) return false;
+ auto flat_qos_configs = configurations_root->qos_configurations();
+ if ((flat_qos_configs == nullptr) || (flat_qos_configs->size() == 0))
+ return false;
+
+ LOG_DEBUG(": Updating %d qos config entries.", flat_qos_configs->size());
+ std::vector<const bluetooth::le_audio::QosConfiguration*> qos_cfgs;
+ for (auto const& flat_qos_cfg : *flat_qos_configs) {
+ qos_cfgs.push_back(flat_qos_cfg);
+ }
+
+ auto flat_codec_configs = configurations_root->codec_configurations();
+ if ((flat_codec_configs == nullptr) || (flat_codec_configs->size() == 0))
+ return false;
+
+ LOG_DEBUG(": Updating %d codec config entries.",
+ flat_codec_configs->size());
+ std::vector<const bluetooth::le_audio::CodecConfiguration*> codec_cfgs;
+ for (auto const& flat_codec_cfg : *flat_codec_configs) {
+ codec_cfgs.push_back(flat_codec_cfg);
+ }
+
auto flat_configs = configurations_root->configurations();
if ((flat_configs == nullptr) || (flat_configs->size() == 0)) return false;
LOG_DEBUG(": Updating %d config entries.", flat_configs->size());
for (auto const& flat_cfg : *flat_configs) {
configurations_.insert(
- {flat_cfg->name()->str(), AudioSetConfigurationFromFlat(flat_cfg)});
+ {flat_cfg->name()->str(),
+ AudioSetConfigurationFromFlat(flat_cfg, &codec_cfgs, &qos_cfgs)});
}
return true;
diff --git a/system/bta/le_audio/le_audio_types.h b/system/bta/le_audio/le_audio_types.h
index 866dabbc05..ab1410a1bb 100644
--- a/system/bta/le_audio/le_audio_types.h
+++ b/system/bta/le_audio/le_audio_types.h
@@ -595,9 +595,16 @@ struct CodecCapabilitySetting {
uint8_t GetConfigChannelCount() const;
};
+struct QosConfigSetting {
+ uint8_t retransmission_number;
+ uint16_t max_transport_latency;
+};
+
struct SetConfiguration {
SetConfiguration(uint8_t direction, uint8_t device_cnt, uint8_t ase_cnt,
uint8_t target_latency, CodecCapabilitySetting codec,
+ QosConfigSetting qos = {.retransmission_number = 0,
+ .max_transport_latency = 0},
le_audio::types::LeAudioConfigurationStrategy strategy =
le_audio::types::LeAudioConfigurationStrategy::
MONO_ONE_CIS_PER_DEVICE)
@@ -606,6 +613,7 @@ struct SetConfiguration {
ase_cnt(ase_cnt),
target_latency(target_latency),
codec(codec),
+ qos(qos),
strategy(strategy) {}
uint8_t direction; /* Direction of set */
@@ -613,6 +621,7 @@ struct SetConfiguration {
uint8_t ase_cnt; /* How many ASE we need in configuration */
uint8_t target_latency;
CodecCapabilitySetting codec;
+ QosConfigSetting qos;
types::LeAudioConfigurationStrategy strategy;
};
diff --git a/system/bta/le_audio/state_machine.cc b/system/bta/le_audio/state_machine.cc
index 86f7542327..97d8a47d76 100644
--- a/system/bta/le_audio/state_machine.cc
+++ b/system/bta/le_audio/state_machine.cc
@@ -860,7 +860,8 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {
if (iter != cis_cfgs.end()) continue;
auto ases_pair = leAudioDevice->GetAsesByCisId(cis);
- EXT_CIS_CFG cis_cfg;
+ EXT_CIS_CFG cis_cfg = {0, 0, 0, 0, 0, 0, 0};
+
cis_cfg.cis_id = ase->cis_id;
cis_cfg.phy_mtos =
group->GetPhyBitmask(le_audio::types::kLeAudioDirectionSink);
@@ -1153,12 +1154,20 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {
}
ase->framing = rsp.framing;
ase->preferred_phy = rsp.preferred_phy;
- ase->max_transport_latency = rsp.max_transport_latency;
+ /* Validate and update QoS settings to be consistent */
+ if ((!ase->max_transport_latency ||
+ ase->max_transport_latency > rsp.max_transport_latency) ||
+ !ase->retrans_nb) {
+ ase->max_transport_latency = rsp.max_transport_latency;
+ ase->retrans_nb = rsp.preferred_retrans_nb;
+ LOG(INFO) << __func__ << " Using server preferred QoS settings."
+ << " Max Transport Latency: " << +ase->max_transport_latency
+ << ", Retransmission Number: " << +ase->retrans_nb;
+ }
ase->pres_delay_min = rsp.pres_delay_min;
ase->pres_delay_max = rsp.pres_delay_max;
ase->preferred_pres_delay_min = rsp.preferred_pres_delay_min;
ase->preferred_pres_delay_max = rsp.preferred_pres_delay_max;
- ase->retrans_nb = rsp.preferred_retrans_nb;
ase->state = AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED;
@@ -1222,12 +1231,20 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {
ase->framing = rsp.framing;
ase->preferred_phy = rsp.preferred_phy;
- ase->max_transport_latency = rsp.max_transport_latency;
+ /* Validate and update QoS settings to be consistent */
+ if ((!ase->max_transport_latency ||
+ ase->max_transport_latency > rsp.max_transport_latency) ||
+ !ase->retrans_nb) {
+ ase->max_transport_latency = rsp.max_transport_latency;
+ ase->retrans_nb = rsp.preferred_retrans_nb;
+ LOG(INFO) << __func__ << " Using server preferred QoS settings."
+ << " Max Transport Latency: " << +ase->max_transport_latency
+ << ", Retransmission Number: " << +ase->retrans_nb;
+ }
ase->pres_delay_min = rsp.pres_delay_min;
ase->pres_delay_max = rsp.pres_delay_max;
ase->preferred_pres_delay_min = rsp.preferred_pres_delay_min;
ase->preferred_pres_delay_max = rsp.preferred_pres_delay_max;
- ase->retrans_nb = rsp.preferred_retrans_nb;
/* This may be a notification from a re-configured ASE */
ase->reconfigure = false;
diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc
index bb12ed1ece..18c8d4bdd7 100644
--- a/system/btif/src/btif_dm.cc
+++ b/system/btif/src/btif_dm.cc
@@ -967,9 +967,14 @@ static void btif_dm_auth_cmpl_evt(tBTA_DM_AUTH_CMPL* p_auth_cmpl) {
bt_status_t ret;
BTIF_TRACE_DEBUG("%s: Storing link key. key_type=0x%x, bond_type=%d",
__func__, p_auth_cmpl->key_type, pairing_cb.bond_type);
- ret = btif_storage_add_bonded_device(&bd_addr, p_auth_cmpl->key,
- p_auth_cmpl->key_type,
- pairing_cb.pin_code_len);
+ if (!bd_addr.IsEmpty()) {
+ ret = btif_storage_add_bonded_device(&bd_addr, p_auth_cmpl->key,
+ p_auth_cmpl->key_type,
+ pairing_cb.pin_code_len);
+ } else {
+ LOG_WARN("bd_addr is empty");
+ ret = BT_STATUS_FAIL;
+ }
ASSERTC(ret == BT_STATUS_SUCCESS, "storing link key failed", ret);
} else {
BTIF_TRACE_DEBUG(
@@ -2775,6 +2780,11 @@ void btif_dm_get_ble_local_keys(tBTA_DM_BLE_LOCAL_KEY_MASK* p_key_mask,
static void btif_dm_save_ble_bonding_keys(RawAddress& bd_addr) {
BTIF_TRACE_DEBUG("%s", __func__);
+ if (bd_addr.IsEmpty()) {
+ LOG_WARN("bd_addr is empty");
+ return;
+ }
+
if (pairing_cb.ble.is_penc_key_rcvd) {
btif_storage_add_ble_bonding_key(
&bd_addr, (uint8_t*)&pairing_cb.ble.penc_key, BTM_LE_KEY_PENC,
diff --git a/system/btif/src/btif_le_audio_broadcaster.cc b/system/btif/src/btif_le_audio_broadcaster.cc
index 57d14f93fc..342626f0dd 100644
--- a/system/btif/src/btif_le_audio_broadcaster.cc
+++ b/system/btif/src/btif_le_audio_broadcaster.cc
@@ -63,47 +63,40 @@ class LeAudioBroadcasterInterfaceImpl : public LeAudioBroadcasterInterface,
broadcast_code));
}
- void UpdateMetadata(uint8_t instance_id,
+ void UpdateMetadata(uint32_t broadcast_id,
std::vector<uint8_t> metadata) override {
DVLOG(2) << __func__;
do_in_main_thread(FROM_HERE, Bind(&LeAudioBroadcaster::UpdateMetadata,
Unretained(LeAudioBroadcaster::Get()),
- instance_id, std::move(metadata)));
+ broadcast_id, std::move(metadata)));
}
- void StartBroadcast(uint8_t instance_id) override {
+ void StartBroadcast(uint32_t broadcast_id) override {
DVLOG(2) << __func__;
- do_in_main_thread(FROM_HERE,
- Bind(&LeAudioBroadcaster::StartAudioBroadcast,
- Unretained(LeAudioBroadcaster::Get()), instance_id));
- }
-
- void StopBroadcast(uint8_t instance_id) override {
- DVLOG(2) << __func__;
- do_in_main_thread(FROM_HERE,
- Bind(&LeAudioBroadcaster::StopAudioBroadcast,
- Unretained(LeAudioBroadcaster::Get()), instance_id));
+ do_in_main_thread(
+ FROM_HERE, Bind(&LeAudioBroadcaster::StartAudioBroadcast,
+ Unretained(LeAudioBroadcaster::Get()), broadcast_id));
}
- void PauseBroadcast(uint8_t instance_id) override {
+ void StopBroadcast(uint32_t broadcast_id) override {
DVLOG(2) << __func__;
- do_in_main_thread(FROM_HERE,
- Bind(&LeAudioBroadcaster::SuspendAudioBroadcast,
- Unretained(LeAudioBroadcaster::Get()), instance_id));
+ do_in_main_thread(
+ FROM_HERE, Bind(&LeAudioBroadcaster::StopAudioBroadcast,
+ Unretained(LeAudioBroadcaster::Get()), broadcast_id));
}
- void DestroyBroadcast(uint8_t instance_id) override {
+ void PauseBroadcast(uint32_t broadcast_id) override {
DVLOG(2) << __func__;
- do_in_main_thread(FROM_HERE,
- Bind(&LeAudioBroadcaster::DestroyAudioBroadcast,
- Unretained(LeAudioBroadcaster::Get()), instance_id));
+ do_in_main_thread(
+ FROM_HERE, Bind(&LeAudioBroadcaster::SuspendAudioBroadcast,
+ Unretained(LeAudioBroadcaster::Get()), broadcast_id));
}
- void GetBroadcastId(uint8_t instance_id) override {
+ void DestroyBroadcast(uint32_t broadcast_id) override {
DVLOG(2) << __func__;
- do_in_main_thread(FROM_HERE,
- Bind(&LeAudioBroadcaster::GetBroadcastId,
- Unretained(LeAudioBroadcaster::Get()), instance_id));
+ do_in_main_thread(
+ FROM_HERE, Bind(&LeAudioBroadcaster::DestroyAudioBroadcast,
+ Unretained(LeAudioBroadcaster::Get()), broadcast_id));
}
void GetAllBroadcastStates(void) override {
@@ -113,34 +106,26 @@ class LeAudioBroadcasterInterfaceImpl : public LeAudioBroadcasterInterface,
Unretained(LeAudioBroadcaster::Get())));
}
- void OnBroadcastCreated(uint8_t instance_id, bool success) override {
+ void OnBroadcastCreated(uint32_t broadcast_id, bool success) override {
DVLOG(2) << __func__;
do_in_jni_thread(FROM_HERE,
Bind(&LeAudioBroadcasterCallbacks::OnBroadcastCreated,
- Unretained(callbacks_), instance_id, success));
+ Unretained(callbacks_), broadcast_id, success));
}
- void OnBroadcastDestroyed(uint8_t instance_id) override {
+ void OnBroadcastDestroyed(uint32_t broadcast_id) override {
DVLOG(2) << __func__;
do_in_jni_thread(FROM_HERE,
Bind(&LeAudioBroadcasterCallbacks::OnBroadcastDestroyed,
- Unretained(callbacks_), instance_id));
+ Unretained(callbacks_), broadcast_id));
}
- void OnBroadcastStateChanged(uint8_t instance_id,
+ void OnBroadcastStateChanged(uint32_t broadcast_id,
BroadcastState state) override {
DVLOG(2) << __func__;
do_in_jni_thread(FROM_HERE,
Bind(&LeAudioBroadcasterCallbacks::OnBroadcastStateChanged,
- Unretained(callbacks_), instance_id, state));
- }
-
- void OnBroadcastId(uint8_t instance_id,
- const BroadcastId& broadcast_id) override {
- DVLOG(2) << __func__;
- do_in_jni_thread(FROM_HERE,
- Bind(&LeAudioBroadcasterCallbacks::OnBroadcastId,
- Unretained(callbacks_), instance_id, broadcast_id));
+ Unretained(callbacks_), broadcast_id, state));
}
void Stop(void) override {
diff --git a/system/embdrv/lc3/fuzzer/liblc3_fuzzer.cpp b/system/embdrv/lc3/fuzzer/liblc3_fuzzer.cpp
index a5a7ae7f29..00ff5a2e74 100644
--- a/system/embdrv/lc3/fuzzer/liblc3_fuzzer.cpp
+++ b/system/embdrv/lc3/fuzzer/liblc3_fuzzer.cpp
@@ -18,6 +18,8 @@
#include "include/lc3.h"
void TestEncoder(FuzzedDataProvider& fdp) {
+ enum lc3_pcm_format pcm_format =
+ fdp.PickValueInArray({LC3_PCM_FORMAT_S16, LC3_PCM_FORMAT_S24});
int dt_us = fdp.PickValueInArray({10000, 7500});
int sr_hz =
fdp.PickValueInArray({8000, 16000, 24000, 32000, /*44100,*/ 48000});
@@ -39,8 +41,8 @@ void TestEncoder(FuzzedDataProvider& fdp) {
lc3_setup_encoder(dt_us, sr_hz, 0, lc3_encoder_mem);
std::vector<uint8_t> output(output_byte_count);
- lc3_encode(lc3_encoder, (const int16_t*)input_frames.data(), 1, output.size(),
- output.data());
+ lc3_encode(lc3_encoder, pcm_format, (const int16_t*)input_frames.data(), 1,
+ output.size(), output.data());
free(lc3_encoder_mem);
lc3_encoder_mem = nullptr;
@@ -48,6 +50,8 @@ void TestEncoder(FuzzedDataProvider& fdp) {
}
void TestDecoder(FuzzedDataProvider& fdp) {
+ enum lc3_pcm_format pcm_format =
+ fdp.PickValueInArray({LC3_PCM_FORMAT_S16, LC3_PCM_FORMAT_S24});
int dt_us = fdp.PickValueInArray({10000, 7500});
int sr_hz =
fdp.PickValueInArray({8000, 16000, 24000, 32000, /*44100,*/ 48000});
@@ -68,11 +72,11 @@ void TestDecoder(FuzzedDataProvider& fdp) {
lc3_setup_decoder(dt_us, sr_hz, 0, lc3_decoder_mem);
std::vector<uint16_t> output(num_frames);
- lc3_decode(lc3_decoder, input.data(), input.size(), (int16_t*)output.data(),
- 1);
+ lc3_decode(lc3_decoder, input.data(), input.size(), pcm_format,
+ (int16_t*)output.data(), 1);
/* Empty input performs PLC (packet loss concealment) */
- lc3_decode(lc3_decoder, nullptr, 0, (int16_t*)output.data(), 1);
+ lc3_decode(lc3_decoder, nullptr, 0, pcm_format, (int16_t*)output.data(), 1);
free(lc3_decoder_mem);
lc3_decoder_mem = nullptr;
diff --git a/system/embdrv/lc3/include/lc3.h b/system/embdrv/lc3/include/lc3.h
index f8dc8b3492..652d694697 100644
--- a/system/embdrv/lc3/include/lc3.h
+++ b/system/embdrv/lc3/include/lc3.h
@@ -145,6 +145,19 @@ extern "C" {
/**
+ * PCM Sample Format
+ * S16 Signed 16 bits, in 16 bits words (int16_t)
+ * S24 Signed 24 bits, using low three bytes of 32 bits words (int32_t).
+ * The high byte sign extends the sample value (bits 31..24 set to b23).
+ */
+
+enum lc3_pcm_format {
+ LC3_PCM_FORMAT_S16,
+ LC3_PCM_FORMAT_S24,
+};
+
+
+/**
* Handle
*/
@@ -231,13 +244,14 @@ lc3_encoder_t lc3_setup_encoder(
/**
* Encode a frame
* encoder Handle of the encoder
- * pcm, pitch Input PCM samples, and count between two consecutives
+ * fmt PCM input format
+ * pcm, stride Input PCM samples, and count between two consecutives
* nbytes Target size, in bytes, of the frame (20 to 400)
* out Output buffer of `nbytes` size
* return 0: On success -1: Wrong parameters
*/
-int lc3_encode(lc3_encoder_t encoder,
- const int16_t *pcm, int pitch, int nbytes, void *out);
+int lc3_encode(lc3_encoder_t encoder, enum lc3_pcm_format fmt,
+ const void *pcm, int stride, int nbytes, void *out);
/**
* Return size needed for an decoder
@@ -271,11 +285,12 @@ lc3_decoder_t lc3_setup_decoder(
* Decode a frame
* decoder Handle of the decoder
* in, nbytes Input bitstream, and size in bytes, NULL performs PLC
- * pcm, pitch Output PCM samples, and count between two consecutives
+ * fmt PCM output format
+ * pcm, stride Output PCM samples, and count between two consecutives
* return 0: On success 1: PLC operated -1: Wrong parameters
*/
-int lc3_decode(lc3_decoder_t decoder,
- const void *in, int nbytes, int16_t *pcm, int pitch);
+int lc3_decode(lc3_decoder_t decoder, const void *in, int nbytes,
+ enum lc3_pcm_format fmt, void *pcm, int stride);
#ifdef __cplusplus
diff --git a/system/embdrv/lc3/src/bits.h b/system/embdrv/lc3/src/bits.h
index 475fc26ca6..faef3370bd 100644
--- a/system/embdrv/lc3/src/bits.h
+++ b/system/embdrv/lc3/src/bits.h
@@ -286,9 +286,9 @@ static inline unsigned lc3_get_symbol(
const struct lc3_ac_symbol *symbols = model->s;
struct lc3_bits_ac *ac = &bits->ac;
- uint16_t range = ac->range >> 10;
+ unsigned range = (ac->range >> 10) & 0xffff;
- ac->error |= (ac->low >= ((unsigned)range << 10));
+ ac->error |= (ac->low >= (range << 10));
if (ac->error)
ac->low = 0;
diff --git a/system/embdrv/lc3/src/lc3.c b/system/embdrv/lc3/src/lc3.c
index 6fd7575014..69774422dd 100644
--- a/system/embdrv/lc3/src/lc3.c
+++ b/system/embdrv/lc3/src/lc3.c
@@ -147,18 +147,39 @@ int lc3_delay_samples(int dt_us, int sr_hz)
/**
* Input PCM Samples from signed 16 bits
* encoder Encoder state
- * pcm, pitch Input PCM samples, and count between two consecutives
+ * pcm, stride Input PCM samples, and count between two consecutives
*/
static void load_s16(
- struct lc3_encoder *encoder, const int16_t *pcm, int pitch)
+ struct lc3_encoder *encoder, const void *_pcm, int stride)
{
+ const int16_t *pcm = _pcm;
+
+ enum lc3_dt dt = encoder->dt;
+ enum lc3_srate sr = encoder->sr_pcm;
+ float *xs = encoder->xs;
+ int ns = LC3_NS(dt, sr);
+
+ for (int i = 0; i < ns; i++)
+ xs[i] = pcm[i*stride];
+}
+
+/**
+ * Input PCM Samples from signed 24 bits
+ * encoder Encoder state
+ * pcm, stride Input PCM samples, and count between two consecutives
+ */
+static void load_s24(
+ struct lc3_encoder *encoder, const void *_pcm, int stride)
+{
+ const int32_t *pcm = _pcm;
+
enum lc3_dt dt = encoder->dt;
enum lc3_srate sr = encoder->sr_pcm;
float *xs = encoder->xs;
int ns = LC3_NS(dt, sr);
for (int i = 0; i < ns; i++)
- xs[i] = pcm[i*pitch];
+ xs[i] = ldexpf(pcm[i*stride], -8);
}
/**
@@ -295,9 +316,14 @@ struct lc3_encoder *lc3_setup_encoder(
/**
* Encode a frame
*/
-int lc3_encode(struct lc3_encoder *encoder,
- const int16_t *pcm, int pitch, int nbytes, void *out)
+int lc3_encode(struct lc3_encoder *encoder, enum lc3_pcm_format fmt,
+ const void *pcm, int stride, int nbytes, void *out)
{
+ static void (* const load[])(struct lc3_encoder *, const void *, int) = {
+ [LC3_PCM_FORMAT_S16] = load_s16,
+ [LC3_PCM_FORMAT_S24] = load_s24,
+ };
+
/* --- Check parameters --- */
if (!encoder || nbytes < LC3_MIN_FRAME_BYTES
@@ -309,7 +335,7 @@ int lc3_encode(struct lc3_encoder *encoder,
struct side_data side;
int16_t xq[LC3_NE(encoder->dt, encoder->sr)];
- load_s16(encoder, pcm, pitch);
+ load[fmt](encoder, pcm, stride);
analyze(encoder, nbytes, &side, xq);
@@ -326,23 +352,49 @@ int lc3_encode(struct lc3_encoder *encoder,
/**
* Output PCM Samples to signed 16 bits
* decoder Decoder state
- * pcm, pitch Output PCM samples, and count between two consecutives
+ * pcm, stride Output PCM samples, and count between two consecutives
*/
static void store_s16(
- struct lc3_decoder *decoder, int16_t *pcm, int pitch)
+ struct lc3_decoder *decoder, void *_pcm, int stride)
{
+ int16_t *pcm = _pcm;
+
enum lc3_dt dt = decoder->dt;
enum lc3_srate sr = decoder->sr_pcm;
float *xs = decoder->xs;
int ns = LC3_NS(dt, sr);
- for ( ; ns > 0; ns--, xs++, pcm += pitch) {
+ for ( ; ns > 0; ns--, xs++, pcm += stride) {
int s = *xs >= 0 ? (int)(*xs + 0.5f) : (int)(*xs - 0.5f);
*pcm = LC3_CLIP(s, INT16_MIN, INT16_MAX);
}
}
/**
+ * Output PCM Samples to signed 24 bits
+ * decoder Decoder state
+ * pcm, stride Output PCM samples, and count between two consecutives
+ */
+static void store_s24(
+ struct lc3_decoder *decoder, void *_pcm, int stride)
+{
+ int32_t *pcm = _pcm;
+ const int32_t int24_max = (1 << 23) - 1;
+ const int32_t int24_min = -(1 << 23);
+
+ enum lc3_dt dt = decoder->dt;
+ enum lc3_srate sr = decoder->sr_pcm;
+ float *xs = decoder->xs;
+ int ns = LC3_NS(dt, sr);
+
+ for ( ; ns > 0; ns--, xs++, pcm += stride) {
+ int32_t s = *xs >= 0 ? (int32_t)(ldexpf(*xs, 8) + 0.5f)
+ : (int32_t)(ldexpf(*xs, 8) - 0.5f);
+ *pcm = LC3_CLIP(s, int24_min, int24_max);
+ }
+}
+
+/**
* Decode bitstream
* decoder Decoder state
* data, nbytes Input bitstream buffer
@@ -484,9 +536,14 @@ struct lc3_decoder *lc3_setup_decoder(
/**
* Decode a frame
*/
-int lc3_decode(struct lc3_decoder *decoder,
- const void *in, int nbytes, int16_t *pcm, int pitch)
+int lc3_decode(struct lc3_decoder *decoder, const void *in, int nbytes,
+ enum lc3_pcm_format fmt, void *pcm, int stride)
{
+ static void (* const store[])(struct lc3_decoder *, void *, int) = {
+ [LC3_PCM_FORMAT_S16] = store_s16,
+ [LC3_PCM_FORMAT_S24] = store_s24,
+ };
+
/* --- Check parameters --- */
if (!decoder)
@@ -504,7 +561,7 @@ int lc3_decode(struct lc3_decoder *decoder,
synthesize(decoder, ret ? NULL : &side, nbytes);
- store_s16(decoder, pcm, pitch);
+ store[fmt](decoder, pcm, stride);
return ret;
}
diff --git a/system/embdrv/lc3/src/tns.c b/system/embdrv/lc3/src/tns.c
index 8545d78380..7c6d1e81ed 100644
--- a/system/embdrv/lc3/src/tns.c
+++ b/system/embdrv/lc3/src/tns.c
@@ -375,7 +375,7 @@ void lc3_tns_analyze(enum lc3_dt dt, enum lc3_bandwidth bw,
void lc3_tns_synthesize(enum lc3_dt dt, enum lc3_bandwidth bw,
const struct lc3_tns_data *data, float *x)
{
- float rc[2][8] = { 0 };
+ float rc[2][8] = { };
for (int f = 0; f < data->nfilters; f++)
if (data->rc_order[f])
diff --git a/system/gd/common/strings.h b/system/gd/common/strings.h
index 3c0d314ccf..01944f55eb 100644
--- a/system/gd/common/strings.h
+++ b/system/gd/common/strings.h
@@ -36,6 +36,13 @@
namespace bluetooth {
namespace common {
+template <typename T>
+inline std::string ToString(const T& value) {
+ std::stringstream tmp;
+ tmp << value;
+ return tmp.str();
+}
+
// Convert number into a hex string prefixed with 0x
template <typename T>
std::string ToHexString(T x) {
diff --git a/system/gd/common/strings_test.cc b/system/gd/common/strings_test.cc
index 7da1ccd087..64f2142973 100644
--- a/system/gd/common/strings_test.cc
+++ b/system/gd/common/strings_test.cc
@@ -256,4 +256,15 @@ TEST(StringsTest, string_format_time_with_ms_test) {
ASSERT_THAT(StringFormatTimeWithMilliseconds(format, time_point2, gmtime), StrEq("2009-02-13 23:31:30.001"));
}
+class ExampleClass {};
+std::ostream& operator<<(std::ostream& os, const ExampleClass& obj) {
+ os << "ExampleClass";
+ return os;
+}
+
+TEST(StringsTest, example_class_to_string_test) {
+ ExampleClass obj;
+ ASSERT_THAT(ToString(obj), StrEq("ExampleClass"));
+}
+
} // namespace testing
diff --git a/system/gd/hci/acl_manager/le_impl.h b/system/gd/hci/acl_manager/le_impl.h
index c1c5ff732b..a9c2ac98c3 100644
--- a/system/gd/hci/acl_manager/le_impl.h
+++ b/system/gd/hci/acl_manager/le_impl.h
@@ -16,6 +16,8 @@
#pragma once
+#include <base/strings/stringprintf.h>
+
#include <atomic>
#include <memory>
@@ -46,6 +48,29 @@ constexpr uint8_t PHY_LE_1M = 0x01;
constexpr uint8_t PHY_LE_2M = 0x02;
constexpr uint8_t PHY_LE_CODED = 0x04;
+enum class ConnectabilityState {
+ DISARMED = 0,
+ ARMING = 1,
+ ARMED = 2,
+ DISARMING = 3,
+};
+
+#define CASE_RETURN_TEXT(code) \
+ case code: \
+ return #code
+
+inline std::string connectability_state_machine_text(const ConnectabilityState& state) {
+ switch (state) {
+ CASE_RETURN_TEXT(ConnectabilityState::DISARMED);
+ CASE_RETURN_TEXT(ConnectabilityState::ARMING);
+ CASE_RETURN_TEXT(ConnectabilityState::ARMED);
+ CASE_RETURN_TEXT(ConnectabilityState::DISARMING);
+ default:
+ return base::StringPrintf("UNKNOWN[%d]", state);
+ }
+}
+#undef CASE_RETURN_TEXT
+
struct le_acl_connection {
le_acl_connection(AddressWithType remote_address, AclConnection::QueueDownEnd* queue_down_end, os::Handler* handler)
: remote_address_(remote_address),
@@ -201,6 +226,16 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
AddressWithType empty(Address::kEmpty, AddressType::RANDOM_DEVICE_ADDRESS);
return empty;
}
+
+ bool alreadyConnected(AddressWithType address_with_type) {
+ for (auto it = le_acl_connections_.begin(); it != le_acl_connections_.end(); it++) {
+ if (it->second.remote_address_ == address_with_type) {
+ return true;
+ }
+ }
+ return false;
+ }
+
} connections;
public:
@@ -233,6 +268,7 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
auto status = connection_complete.GetStatus();
auto address = connection_complete.GetPeerAddress();
auto peer_address_type = connection_complete.GetPeerAddressType();
+ connectability_state_ = ConnectabilityState::DISARMED;
if (status == ErrorCode::UNKNOWN_CONNECTION && pause_connection) {
// connection canceled by LeAddressManager.OnPause(), will auto reconnect by LeAddressManager.OnResume()
return;
@@ -299,6 +335,7 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
auto address = connection_complete.GetPeerAddress();
auto peer_address_type = connection_complete.GetPeerAddressType();
auto peer_resolvable_address = connection_complete.GetPeerResolvablePrivateAddress();
+ connectability_state_ = ConnectabilityState::DISARMED;
if (status == ErrorCode::UNKNOWN_CONNECTION && pause_connection) {
// connection canceled by LeAddressManager.OnPause(), will auto reconnect by LeAddressManager.OnResume()
return;
@@ -370,10 +407,6 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
static constexpr bool kRemoveConnectionAfterwards = true;
void on_le_disconnect(uint16_t handle, ErrorCode reason) {
AddressWithType remote_address = connections.getAddressWithType(handle);
- if (background_connections_.count(remote_address) == 1) {
- LOG_INFO("re-add device to connect list");
- add_device_to_connect_list(remote_address);
- }
bool event_also_routes_to_other_receivers = connections.crash_on_unknown_handle_;
connections.crash_on_unknown_handle_ = false;
connections.execute(
@@ -384,10 +417,14 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
},
kRemoveConnectionAfterwards);
connections.crash_on_unknown_handle_ = event_also_routes_to_other_receivers;
- if (!connect_list.empty()) {
+
+ if (background_connections_.count(remote_address) == 1) {
+ LOG_INFO("re-add device to connect list");
+ add_device_to_connect_list(remote_address);
+ }
+ if (!connect_list.empty() && connectability_state_ == ConnectabilityState::DISARMED) {
LOG_INFO("connect_list is not empty, send a new connection request");
- AddressWithType empty(Address::kEmpty, AddressType::RANDOM_DEVICE_ADDRESS);
- create_le_connection(empty, false, false);
+ arm_connectability();
}
}
@@ -477,6 +514,11 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
}
void add_device_to_connect_list(AddressWithType address_with_type) {
+ if (connections.alreadyConnected(address_with_type)) {
+ LOG_INFO("Device already connected, return");
+ return;
+ }
+
connect_list.insert(address_with_type);
register_with_address_manager();
le_address_manager_->AddDeviceToConnectList(
@@ -515,11 +557,50 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
void on_extended_create_connection(CommandStatusView status) {
ASSERT(status.IsValid());
ASSERT(status.GetCommandOpCode() == OpCode::LE_EXTENDED_CREATE_CONNECTION);
+ if (connectability_state_ != ConnectabilityState::ARMING) {
+ LOG_ERROR(
+ "Received connectability arm notification for unexpected state:%s",
+ connectability_state_machine_text(connectability_state_).c_str());
+ }
+ connectability_state_ =
+ (status.GetStatus() == ErrorCode::SUCCESS) ? ConnectabilityState::ARMED : ConnectabilityState::DISARMED;
}
void on_create_connection(CommandStatusView status) {
ASSERT(status.IsValid());
ASSERT(status.GetCommandOpCode() == OpCode::LE_CREATE_CONNECTION);
+ if (connectability_state_ != ConnectabilityState::ARMING) {
+ LOG_ERROR(
+ "Received connectability arm notification for unexpected state:%s",
+ connectability_state_machine_text(connectability_state_).c_str());
+ }
+ connectability_state_ =
+ (status.GetStatus() == ErrorCode::SUCCESS) ? ConnectabilityState::ARMED : ConnectabilityState::DISARMED;
+ }
+
+ void arm_connectability() {
+ if (connectability_state_ != ConnectabilityState::DISARMED) {
+ LOG_ERROR(
+ "Attempting to re-arm le connection state machine in unexpected state:%s",
+ connectability_state_machine_text(connectability_state_).c_str());
+ return;
+ }
+ connectability_state_ = ConnectabilityState::ARMING;
+ AddressWithType empty(Address::kEmpty, AddressType::RANDOM_DEVICE_ADDRESS);
+ create_le_connection(empty, false, false);
+ }
+
+ void disarm_connectability() {
+ if (connectability_state_ != ConnectabilityState::ARMED) {
+ LOG_ERROR(
+ "Attempting to re-arm le connection state machine in unexpected state:%s",
+ connectability_state_machine_text(connectability_state_).c_str());
+ return;
+ }
+ connectability_state_ = ConnectabilityState::DISARMING;
+ le_acl_connection_interface_->EnqueueCommand(
+ LeCreateConnectionCancelBuilder::Create(),
+ handler_->BindOnce(&le_impl::on_create_connection_cancel_complete, common::Unretained(this)));
}
void create_le_connection(AddressWithType address_with_type, bool add_to_connect_list, bool is_direct) {
@@ -528,6 +609,11 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
return;
}
+ if (connections.alreadyConnected(address_with_type)) {
+ LOG_INFO("Device already connected, return");
+ return;
+ }
+
// TODO: Configure default LE connection parameters?
if (add_to_connect_list) {
add_device_to_connect_list(address_with_type);
@@ -664,9 +750,7 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
create_connection_timeout_alarms_.erase(address_with_type);
if (background_connections_.find(address_with_type) != background_connections_.end()) {
direct_connections_.erase(address_with_type);
- le_acl_connection_interface_->EnqueueCommand(
- LeCreateConnectionCancelBuilder::Create(),
- handler_->BindOnce(&le_impl::on_create_connection_cancel_complete, common::Unretained(this)));
+ disarm_connectability();
} else {
cancel_connect(address_with_type);
}
@@ -765,21 +849,18 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
void OnPause() override {
pause_connection = true;
- if (connecting_le_.empty()) {
+ if (connectability_state_ == ConnectabilityState::DISARMED) {
le_address_manager_->AckPause(this);
return;
}
canceled_connections_ = connecting_le_;
- le_acl_connection_interface_->EnqueueCommand(
- LeCreateConnectionCancelBuilder::Create(),
- handler_->BindOnce(&le_impl::on_create_connection_cancel_complete, common::Unretained(this)));
- le_address_manager_->AckPause(this);
+ disarm_connectability();
}
void OnResume() override {
pause_connection = false;
if (!canceled_connections_.empty()) {
- create_le_connection(*canceled_connections_.begin(), false, false);
+ arm_connectability();
}
canceled_connections_.clear();
le_address_manager_->AckResume(this);
@@ -794,6 +875,15 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
std::string error_code = ErrorCodeText(status);
LOG_WARN("Received on_create_connection_cancel_complete with error code %s", error_code.c_str());
}
+ if (connectability_state_ != ConnectabilityState::DISARMING) {
+ LOG_ERROR(
+ "Attempting to disarm le connection state machine in unexpected state:%s",
+ connectability_state_machine_text(connectability_state_).c_str());
+ }
+ connectability_state_ = ConnectabilityState::DISARMED;
+ if (pause_connection) {
+ le_address_manager_->AckPause(this);
+ }
}
void register_with_address_manager() {
@@ -832,6 +922,7 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
bool address_manager_registered = false;
bool ready_to_unregister = false;
bool pause_connection = false;
+ ConnectabilityState connectability_state_{ConnectabilityState::DISARMED};
std::map<AddressWithType, os::Alarm> create_connection_timeout_alarms_;
};
diff --git a/system/gd/hci/le_address_manager.cc b/system/gd/hci/le_address_manager.cc
index c3c11ceb5d..68bfeccd71 100644
--- a/system/gd/hci/le_address_manager.cc
+++ b/system/gd/hci/le_address_manager.cc
@@ -411,7 +411,11 @@ void LeAddressManager::AddDeviceToResolvingList(
Command enable = {CommandType::SET_ADDRESS_RESOLUTION_ENABLE, std::move(enable_builder)};
cached_commands_.push(std::move(enable));
- pause_registered_clients();
+ if (registered_clients_.empty()) {
+ handle_next_command();
+ } else {
+ pause_registered_clients();
+ }
}
void LeAddressManager::RemoveDeviceFromConnectList(
@@ -438,7 +442,11 @@ void LeAddressManager::RemoveDeviceFromResolvingList(
Command enable = {CommandType::SET_ADDRESS_RESOLUTION_ENABLE, std::move(enable_builder)};
cached_commands_.push(std::move(enable));
- pause_registered_clients();
+ if (registered_clients_.empty()) {
+ handle_next_command();
+ } else {
+ pause_registered_clients();
+ }
}
void LeAddressManager::ClearConnectList() {
@@ -496,7 +504,8 @@ void LeAddressManager::OnCommandComplete(bluetooth::hci::CommandCompleteView vie
void LeAddressManager::check_cached_commands() {
for (auto client : registered_clients_) {
- if (client.second != ClientState::PAUSED) {
+ if (client.second != ClientState::PAUSED && !cached_commands_.empty()) {
+ pause_registered_clients();
return;
}
}
diff --git a/system/gd/hci/le_advertising_manager.cc b/system/gd/hci/le_advertising_manager.cc
index 03a001833d..afc874c592 100644
--- a/system/gd/hci/le_advertising_manager.cc
+++ b/system/gd/hci/le_advertising_manager.cc
@@ -33,6 +33,7 @@ namespace bluetooth {
namespace hci {
const ModuleFactory LeAdvertisingManager::Factory = ModuleFactory([]() { return new LeAdvertisingManager(); });
+constexpr int kIdLocal = 0xff; // Id for advertiser not register from Java layer
enum class AdvertisingApiType {
LEGACY = 1,
@@ -51,6 +52,8 @@ enum class AdvertisingFlag : uint8_t {
struct Advertiser {
os::Handler* handler;
AddressWithType current_address;
+ base::Callback<void(uint8_t /* status */)> status_callback;
+ base::Callback<void(uint8_t /* status */)> timeout_callback;
common::Callback<void(Address, AddressType)> scan_callback;
common::Callback<void(ErrorCode, uint8_t, uint8_t)> set_terminated_callback;
int8_t tx_power;
@@ -186,7 +189,14 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
auto status = event_view.GetStatus();
acl_manager_->OnAdvertisingSetTerminated(status, event_view.GetConnectionHandle(), advertiser_address);
if (status == ErrorCode::LIMIT_REACHED || status == ErrorCode::ADVERTISING_TIMEOUT) {
- advertising_callbacks_->OnAdvertisingEnabled(advertiser_id, false, (uint8_t)status);
+ if (id_map_[advertiser_id] == kIdLocal) {
+ if (!advertising_sets_[advertiser_id].timeout_callback.is_null()) {
+ advertising_sets_[advertiser_id].timeout_callback.Run((uint8_t)status);
+ advertising_sets_[advertiser_id].timeout_callback.Reset();
+ }
+ } else {
+ advertising_callbacks_->OnAdvertisingEnabled(advertiser_id, false, (uint8_t)status);
+ }
return;
}
@@ -304,6 +314,21 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
}
}
+ void start_advertising(
+ AdvertiserId id,
+ const ExtendedAdvertisingConfig config,
+ uint16_t duration,
+ const base::Callback<void(uint8_t /* status */)>& status_callback,
+ const base::Callback<void(uint8_t /* status */)>& timeout_callback,
+ const common::Callback<void(Address, AddressType)>& scan_callback,
+ const common::Callback<void(ErrorCode, uint8_t, uint8_t)>& set_terminated_callback,
+ os::Handler* handler) {
+ advertising_sets_[id].status_callback = status_callback;
+ advertising_sets_[id].timeout_callback = timeout_callback;
+
+ create_extended_advertiser(kIdLocal, id, config, scan_callback, set_terminated_callback, duration, 0, handler);
+ }
+
void create_extended_advertiser(
int reg_id,
AdvertiserId id,
@@ -975,6 +1000,7 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
std::mutex id_mutex_;
size_t num_instances_;
std::vector<hci::EnabledSet> enabled_sets_;
+ // map to mapping the id from java layer and advertier id
std::map<uint8_t, int> id_map_;
AdvertisingApiType advertising_api_type_{0};
@@ -1016,6 +1042,14 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
continue;
}
+ if (id_map_[id] == kIdLocal) {
+ if (!advertising_sets_[enabled_set.advertising_handle_].status_callback.is_null()) {
+ advertising_sets_[enabled_set.advertising_handle_].status_callback.Run(advertising_status);
+ advertising_sets_[enabled_set.advertising_handle_].status_callback.Reset();
+ }
+ continue;
+ }
+
if (started) {
advertising_callbacks_->OnAdvertisingEnabled(id, enable, advertising_status);
} else {
@@ -1050,6 +1084,14 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
continue;
}
+ if (id_map_[id] == kIdLocal) {
+ if (!advertising_sets_[enabled_set.advertising_handle_].status_callback.is_null()) {
+ advertising_sets_[enabled_set.advertising_handle_].status_callback.Run(advertising_status);
+ advertising_sets_[enabled_set.advertising_handle_].status_callback.Reset();
+ }
+ continue;
+ }
+
if (started) {
advertising_callbacks_->OnAdvertisingEnabled(id, enable, advertising_status);
} else {
@@ -1072,7 +1114,7 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
}
advertising_sets_[id].tx_power = complete_view.GetSelectedTxPower();
- if (advertising_sets_[id].started) {
+ if (advertising_sets_[id].started && id_map_[id] != kIdLocal) {
advertising_callbacks_->OnAdvertisingParametersUpdated(id, advertising_sets_[id].tx_power, advertising_status);
}
}
@@ -1088,7 +1130,7 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
advertising_status = AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR;
}
- if (advertising_callbacks_ == nullptr || !advertising_sets_[id].started) {
+ if (advertising_callbacks_ == nullptr || !advertising_sets_[id].started || id_map_[id] == kIdLocal) {
return;
}
@@ -1129,8 +1171,9 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
advertising_status = AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR;
}
- // Do not trigger callback if the advertiser not stated yet
- if (advertising_callbacks_ == nullptr || !advertising_sets_[id].started) {
+ // Do not trigger callback if the advertiser not stated yet, or the advertiser is not register
+ // from Java layer
+ if (advertising_callbacks_ == nullptr || !advertising_sets_[id].started || id_map_[id] == kIdLocal) {
return;
}
@@ -1300,6 +1343,38 @@ AdvertiserId LeAdvertisingManager::ExtendedCreateAdvertiser(
return id;
}
+void LeAdvertisingManager::StartAdvertising(
+ AdvertiserId advertiser_id,
+ const ExtendedAdvertisingConfig config,
+ uint16_t duration,
+ const base::Callback<void(uint8_t /* status */)>& status_callback,
+ const base::Callback<void(uint8_t /* status */)>& timeout_callback,
+ const common::Callback<void(Address, AddressType)>& scan_callback,
+ const common::Callback<void(ErrorCode, uint8_t, uint8_t)>& set_terminated_callback,
+ os::Handler* handler) {
+ CallOn(
+ pimpl_.get(),
+ &impl::start_advertising,
+ advertiser_id,
+ config,
+ duration,
+ status_callback,
+ timeout_callback,
+ scan_callback,
+ set_terminated_callback,
+ handler);
+}
+
+void LeAdvertisingManager::RegisterAdvertiser(
+ base::Callback<void(uint8_t /* inst_id */, uint8_t /* status */)> callback) {
+ AdvertiserId id = pimpl_->allocate_advertiser();
+ if (id == kInvalidId) {
+ callback.Run(kInvalidId, AdvertisingCallback::AdvertisingStatus::TOO_MANY_ADVERTISERS);
+ } else {
+ callback.Run(id, AdvertisingCallback::AdvertisingStatus::SUCCESS);
+ }
+}
+
void LeAdvertisingManager::GetOwnAddress(uint8_t advertiser_id) {
CallOn(pimpl_.get(), &impl::get_own_address, advertiser_id);
}
diff --git a/system/gd/hci/le_advertising_manager.h b/system/gd/hci/le_advertising_manager.h
index 557b110d8d..3ef4de6396 100644
--- a/system/gd/hci/le_advertising_manager.h
+++ b/system/gd/hci/le_advertising_manager.h
@@ -116,8 +116,20 @@ class LeAdvertisingManager : public bluetooth::Module {
uint8_t max_extended_advertising_events,
os::Handler* handler);
+ void StartAdvertising(
+ AdvertiserId advertiser_id,
+ const ExtendedAdvertisingConfig config,
+ uint16_t duration,
+ const base::Callback<void(uint8_t /* status */)>& status_callback,
+ const base::Callback<void(uint8_t /* status */)>& timeout_callback,
+ const common::Callback<void(Address, AddressType)>& scan_callback,
+ const common::Callback<void(ErrorCode, uint8_t, uint8_t)>& set_terminated_callback,
+ os::Handler* handler);
+
void GetOwnAddress(uint8_t advertiser_id);
+ void RegisterAdvertiser(base::Callback<void(uint8_t /* inst_id */, uint8_t /* status */)> callback);
+
void SetParameters(AdvertiserId advertiser_id, ExtendedAdvertisingConfig config);
void SetData(AdvertiserId advertiser_id, bool set_scan_rsp, std::vector<GapData> data);
diff --git a/system/gd/hci/le_scanning_callback.h b/system/gd/hci/le_scanning_callback.h
index d0ef782a7c..5f91208a45 100644
--- a/system/gd/hci/le_scanning_callback.h
+++ b/system/gd/hci/le_scanning_callback.h
@@ -89,6 +89,7 @@ class AdvertisingPacketContentFilterCommand {
uint16_t company_mask;
std::vector<uint8_t> data;
std::vector<uint8_t> data_mask;
+ std::array<uint8_t, 16> irk;
};
class AdvertisingFilterParameter {
diff --git a/system/gd/hci/le_scanning_manager.cc b/system/gd/hci/le_scanning_manager.cc
index 857d2495e5..3bd8f8cbce 100644
--- a/system/gd/hci/le_scanning_manager.cc
+++ b/system/gd/hci/le_scanning_manager.cc
@@ -712,7 +712,7 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback
switch (filter.filter_type) {
case ApcfFilterType::BROADCASTER_ADDRESS: {
- update_address_filter(apcf_action, filter_index, filter.address, filter.application_address_type);
+ update_address_filter(apcf_action, filter_index, filter.address, filter.application_address_type, filter.irk);
break;
}
case ApcfFilterType::SERVICE_UUID:
@@ -741,11 +741,36 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback
}
void update_address_filter(
- ApcfAction action, uint8_t filter_index, Address address, ApcfApplicationAddressType address_type) {
+ ApcfAction action,
+ uint8_t filter_index,
+ Address address,
+ ApcfApplicationAddressType address_type,
+ std::array<uint8_t, 16> irk) {
if (action != ApcfAction::CLEAR) {
+ /*
+ * The vendor command (APCF Filtering 0x0157) takes Public (0) or Random (1)
+ * or Addresses type not applicable (2).
+ *
+ * Advertising results have four types:
+ *  - Public = 0
+ *  - Random = 1
+ *  - Public ID = 2
+ *  - Random ID = 3
+ *
+ * e.g. specifying PUBLIC (0) will only return results with a public
+ * address. It will ignore resolved addresses, since they return PUBLIC
+ * IDENTITY (2). For this, Addresses type not applicable (0x02) must be specified.
+ * This should also cover if the RPA is derived from RANDOM STATIC.
+ */
le_scanning_interface_->EnqueueCommand(
- LeAdvFilterBroadcasterAddressBuilder::Create(action, filter_index, address, address_type),
+ LeAdvFilterBroadcasterAddressBuilder::Create(
+ action, filter_index, address, ApcfApplicationAddressType::NOT_APPLICABLE),
module_handler_->BindOnceOn(this, &impl::on_advertising_filter_complete));
+ if (!is_empty_128bit(irk)) {
+ std::array<uint8_t, 16> empty_irk;
+ le_address_manager_->AddDeviceToResolvingList(
+ static_cast<PeerAddressType>(address_type), address, irk, empty_irk);
+ }
} else {
le_scanning_interface_->EnqueueCommand(
LeAdvFilterClearBroadcasterAddressBuilder::Create(filter_index),
@@ -753,6 +778,15 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback
}
}
+ bool is_empty_128bit(const std::array<uint8_t, 16> data) {
+ for (int i = 0; i < 16; i++) {
+ if (data[i] != (uint8_t)0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
void update_uuid_filter(
ApcfAction action, uint8_t filter_index, ApcfFilterType filter_type, Uuid uuid, Uuid uuid_mask) {
std::vector<uint8_t> combined_data = {};
diff --git a/system/gd/os/fuzz/fake_timerfd.cc b/system/gd/os/fuzz/fake_timerfd.cc
index 5b7389beba..8154e44edc 100644
--- a/system/gd/os/fuzz/fake_timerfd.cc
+++ b/system/gd/os/fuzz/fake_timerfd.cc
@@ -122,7 +122,7 @@ static bool fire_next_event(uint64_t new_clock) {
void fake_timerfd_advance(uint64_t ms) {
uint64_t new_clock = clock + ms;
- if (new_clock > max_clock) {
+ if (new_clock < clock) {
new_clock = max_clock;
}
while (fire_next_event(new_clock)) {
diff --git a/system/gd/os/linux_generic/alarm.cc b/system/gd/os/linux_generic/alarm.cc
index cd859b5fe7..22bd3b2282 100644
--- a/system/gd/os/linux_generic/alarm.cc
+++ b/system/gd/os/linux_generic/alarm.cc
@@ -77,7 +77,11 @@ void Alarm::on_fire() {
lock.unlock();
std::move(task).Run();
ASSERT(bytes_read == static_cast<ssize_t>(sizeof(uint64_t)));
- ASSERT(times_invoked == static_cast<uint64_t>(1));
+ ASSERT_LOG(
+ times_invoked == static_cast<uint64_t>(1),
+ "Invoked number of times:%lu fd:%d",
+ (unsigned long)times_invoked,
+ fd_);
}
} // namespace os
diff --git a/system/gd/packet/parser/fields/array_field.cc b/system/gd/packet/parser/fields/array_field.cc
index c856e5b712..c95734d098 100644
--- a/system/gd/packet/parser/fields/array_field.cc
+++ b/system/gd/packet/parser/fields/array_field.cc
@@ -200,10 +200,11 @@ std::string ArrayField::GetRustDataType() const {
return "[" + element_field_->GetRustDataType() + "; " + std::to_string(array_size_) + "]";
}
-void ArrayField::GenRustGetter(std::ostream& s, Size start_offset, Size) const {
+void ArrayField::GenRustGetter(std::ostream& s, Size start_offset, Size, std::string) const {
s << "let " << GetName() << " = ";
s << "bytes[" << start_offset.bytes() << "..";
- s << start_offset.bytes() + GetSize().bytes() << "].try_into().unwrap();";
+ s << start_offset.bytes() + GetSize().bytes() << "].try_into()";
+ s << ".map_err(|_| Error::InvalidPacketError)?;";
}
void ArrayField::GenRustWriter(std::ostream& s, Size start_offset, Size) const {
diff --git a/system/gd/packet/parser/fields/array_field.h b/system/gd/packet/parser/fields/array_field.h
index 0bd487d397..d19a069edb 100644
--- a/system/gd/packet/parser/fields/array_field.h
+++ b/system/gd/packet/parser/fields/array_field.h
@@ -66,7 +66,7 @@ class ArrayField : public PacketField {
virtual std::string GetRustDataType() const override;
- void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
+ void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset, std::string parent_name) const override;
void GenRustWriter(std::ostream& s, Size start_offset, Size end_offset) const override;
diff --git a/system/gd/packet/parser/fields/body_field.cc b/system/gd/packet/parser/fields/body_field.cc
index 557f184161..d0d61dd52f 100644
--- a/system/gd/packet/parser/fields/body_field.cc
+++ b/system/gd/packet/parser/fields/body_field.cc
@@ -80,7 +80,6 @@ std::string BodyField::GetRustDataType() const {
return GetDataType();
}
-void BodyField::GenRustGetter(std::ostream&, Size, Size) const {
-}
+void BodyField::GenRustGetter(std::ostream&, Size, Size, std::string) const {}
void BodyField::GenRustWriter(std::ostream&, Size, Size) const {}
diff --git a/system/gd/packet/parser/fields/body_field.h b/system/gd/packet/parser/fields/body_field.h
index c31af7414c..2712bf0522 100644
--- a/system/gd/packet/parser/fields/body_field.h
+++ b/system/gd/packet/parser/fields/body_field.h
@@ -54,7 +54,7 @@ class BodyField : public PacketField {
virtual std::string GetRustDataType() const override;
- void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
+ void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset, std::string) const override;
void GenRustWriter(std::ostream& s, Size start_offset, Size end_offset) const override;
diff --git a/system/gd/packet/parser/fields/checksum_field.cc b/system/gd/packet/parser/fields/checksum_field.cc
index bcbcac2fab..6344450563 100644
--- a/system/gd/packet/parser/fields/checksum_field.cc
+++ b/system/gd/packet/parser/fields/checksum_field.cc
@@ -64,7 +64,6 @@ void ChecksumField::GenStringRepresentation(std::ostream& s, std::string) const
s << "\"CHECKSUM\"";
}
-void ChecksumField::GenRustGetter(std::ostream&, Size, Size) const {
-}
+void ChecksumField::GenRustGetter(std::ostream&, Size, Size, std::string) const {}
void ChecksumField::GenRustWriter(std::ostream&, Size, Size) const {}
diff --git a/system/gd/packet/parser/fields/checksum_field.h b/system/gd/packet/parser/fields/checksum_field.h
index 2b5b221479..3a6908e98d 100644
--- a/system/gd/packet/parser/fields/checksum_field.h
+++ b/system/gd/packet/parser/fields/checksum_field.h
@@ -48,7 +48,7 @@ class ChecksumField : public ScalarField {
virtual void GenStringRepresentation(std::ostream& s, std::string accessor) const override;
- void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
+ void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset, std::string) const override;
void GenRustWriter(std::ostream& s, Size start_offset, Size end_offset) const override;
diff --git a/system/gd/packet/parser/fields/checksum_start_field.cc b/system/gd/packet/parser/fields/checksum_start_field.cc
index e0c03b828a..22b2891679 100644
--- a/system/gd/packet/parser/fields/checksum_start_field.cc
+++ b/system/gd/packet/parser/fields/checksum_start_field.cc
@@ -70,7 +70,6 @@ std::string ChecksumStartField::GetRustDataType() const {
return GetDataType();
}
-void ChecksumStartField::GenRustGetter(std::ostream&, Size, Size) const {
-}
+void ChecksumStartField::GenRustGetter(std::ostream&, Size, Size, std::string) const {}
void ChecksumStartField::GenRustWriter(std::ostream&, Size, Size) const {}
diff --git a/system/gd/packet/parser/fields/checksum_start_field.h b/system/gd/packet/parser/fields/checksum_start_field.h
index 82e71ba8c4..67ddc9568f 100644
--- a/system/gd/packet/parser/fields/checksum_start_field.h
+++ b/system/gd/packet/parser/fields/checksum_start_field.h
@@ -55,7 +55,7 @@ class ChecksumStartField : public PacketField {
virtual std::string GetRustDataType() const override;
- void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
+ void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset, std::string) const override;
void GenRustWriter(std::ostream& s, Size start_offset, Size end_offset) const override;
diff --git a/system/gd/packet/parser/fields/custom_field.cc b/system/gd/packet/parser/fields/custom_field.cc
index e4761abc98..295fbf5ca5 100644
--- a/system/gd/packet/parser/fields/custom_field.cc
+++ b/system/gd/packet/parser/fields/custom_field.cc
@@ -104,7 +104,6 @@ std::string CustomField::GetRustDataType() const {
return type_name_;
}
-void CustomField::GenRustGetter(std::ostream&, Size, Size) const {
-}
+void CustomField::GenRustGetter(std::ostream&, Size, Size, std::string) const {}
void CustomField::GenRustWriter(std::ostream&, Size, Size) const {}
diff --git a/system/gd/packet/parser/fields/custom_field.h b/system/gd/packet/parser/fields/custom_field.h
index 55642c9c58..25e196d2bb 100644
--- a/system/gd/packet/parser/fields/custom_field.h
+++ b/system/gd/packet/parser/fields/custom_field.h
@@ -55,7 +55,7 @@ class CustomField : public PacketField {
virtual std::string GetRustDataType() const override;
- void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
+ void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset, std::string) const override;
void GenRustWriter(std::ostream& s, Size start_offset, Size end_offset) const override;
diff --git a/system/gd/packet/parser/fields/custom_field_fixed_size.cc b/system/gd/packet/parser/fields/custom_field_fixed_size.cc
index 8dc27fa3e1..a603259d30 100644
--- a/system/gd/packet/parser/fields/custom_field_fixed_size.cc
+++ b/system/gd/packet/parser/fields/custom_field_fixed_size.cc
@@ -77,7 +77,7 @@ std::string CustomFieldFixedSize::GetRustParseDataType() const {
return "[u8; " + std::to_string(GetSize().bytes()) + "]";
}
-void CustomFieldFixedSize::GenRustGetter(std::ostream& s, Size start_offset, Size end_offset) const {
+void CustomFieldFixedSize::GenRustGetter(std::ostream& s, Size start_offset, Size end_offset, std::string) const {
Size size = GetSize();
int num_leading_bits = GetRustBitOffset(s, start_offset, end_offset, GetSize());
if (num_leading_bits != 0) {
@@ -88,7 +88,8 @@ void CustomFieldFixedSize::GenRustGetter(std::ostream& s, Size start_offset, Siz
}
s << "let " << GetName() << " = bytes[" << start_offset.bytes() << "..";
- s << start_offset.bytes() + size.bytes() << "].try_into().unwrap();";
+ s << start_offset.bytes() + size.bytes() << "].try_into()";
+ s << ".map_err(|_| Error::InvalidPacketError)?;";
}
void CustomFieldFixedSize::GenRustWriter(std::ostream& s, Size start_offset, Size end_offset) const {
diff --git a/system/gd/packet/parser/fields/custom_field_fixed_size.h b/system/gd/packet/parser/fields/custom_field_fixed_size.h
index 8423f803b0..b21c5d8065 100644
--- a/system/gd/packet/parser/fields/custom_field_fixed_size.h
+++ b/system/gd/packet/parser/fields/custom_field_fixed_size.h
@@ -43,7 +43,7 @@ class CustomFieldFixedSize : public ScalarField {
virtual void GenStringRepresentation(std::ostream& s, std::string accessor) const override;
- void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
+ void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset, std::string) const override;
void GenRustWriter(std::ostream& s, Size start_offset, Size end_offset) const override;
diff --git a/system/gd/packet/parser/fields/fixed_scalar_field.cc b/system/gd/packet/parser/fields/fixed_scalar_field.cc
index c745b12069..3a5b760733 100644
--- a/system/gd/packet/parser/fields/fixed_scalar_field.cc
+++ b/system/gd/packet/parser/fields/fixed_scalar_field.cc
@@ -43,6 +43,7 @@ void FixedScalarField::GenRustWriter(std::ostream& s, Size start_offset, Size en
FixedField::GenRustWriter(s, start_offset, end_offset);
}
-void FixedScalarField::GenRustGetter(std::ostream& s, Size start_offset, Size end_offset) const {
- FixedField::GenRustGetter(s, start_offset, end_offset);
+void FixedScalarField::GenRustGetter(
+ std::ostream& s, Size start_offset, Size end_offset, std::string parent_name) const {
+ FixedField::GenRustGetter(s, start_offset, end_offset, parent_name);
}
diff --git a/system/gd/packet/parser/fields/fixed_scalar_field.h b/system/gd/packet/parser/fields/fixed_scalar_field.h
index 2304ba4a0d..595c96df71 100644
--- a/system/gd/packet/parser/fields/fixed_scalar_field.h
+++ b/system/gd/packet/parser/fields/fixed_scalar_field.h
@@ -39,7 +39,7 @@ class FixedScalarField : public FixedField {
static const std::string field_type;
- void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
+ void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset, std::string) const override;
void GenRustWriter(std::ostream& s, Size start_offset, Size end_offset) const override;
diff --git a/system/gd/packet/parser/fields/group_field.cc b/system/gd/packet/parser/fields/group_field.cc
index f2e3b95f8e..1de8fb75f7 100644
--- a/system/gd/packet/parser/fields/group_field.cc
+++ b/system/gd/packet/parser/fields/group_field.cc
@@ -87,7 +87,6 @@ std::string GroupField::GetRustDataType() const {
return GetDataType();
}
-void GroupField::GenRustGetter(std::ostream&, Size, Size) const {
-}
+void GroupField::GenRustGetter(std::ostream&, Size, Size, std::string) const {}
void GroupField::GenRustWriter(std::ostream&, Size, Size) const {}
diff --git a/system/gd/packet/parser/fields/group_field.h b/system/gd/packet/parser/fields/group_field.h
index 691fb229f1..f058f986f7 100644
--- a/system/gd/packet/parser/fields/group_field.h
+++ b/system/gd/packet/parser/fields/group_field.h
@@ -57,7 +57,7 @@ class GroupField : public PacketField {
virtual std::string GetRustDataType() const override;
- void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
+ void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset, std::string) const override;
void GenRustWriter(std::ostream& s, Size start_offset, Size end_offset) const override;
diff --git a/system/gd/packet/parser/fields/packet_field.cc b/system/gd/packet/parser/fields/packet_field.cc
index 4ce02e22e5..608fb28bfb 100644
--- a/system/gd/packet/parser/fields/packet_field.cc
+++ b/system/gd/packet/parser/fields/packet_field.cc
@@ -131,14 +131,14 @@ bool PacketField::GenRustNameAndType(std::ostream& s) const {
return true;
}
-void PacketField::GenBoundsCheck(std::ostream& s, Size start_offset, Size, std::string context) const {
+void PacketField::GenBoundsCheck(std::ostream& s, Size start_offset, Size, std::string parent_name) const {
Size size = GetSize();
if (size.bits() < 8) {
return;
}
s << "if bytes.len() < " << start_offset.bytes() + size.bytes() << " {";
s << " return Err(Error::InvalidLengthError{";
- s << " obj: \"" << context << "\".to_string(),";
+ s << " obj: \"" << parent_name << "\".to_string(),";
s << " field: \"" << GetName() << "\".to_string(),";
s << " wanted: " << start_offset.bytes() + size.bytes() << ",";
s << " got: bytes.len()});";
diff --git a/system/gd/packet/parser/fields/packet_field.h b/system/gd/packet/parser/fields/packet_field.h
index 128536223b..c3df79b912 100644
--- a/system/gd/packet/parser/fields/packet_field.h
+++ b/system/gd/packet/parser/fields/packet_field.h
@@ -124,7 +124,7 @@ class PacketField : public Loggable {
virtual int GetRustBitOffset(
std::ostream& s, Size start_offset, Size end_offset, Size size) const;
- virtual void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset) const = 0;
+ virtual void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset, std::string) const = 0;
virtual void GenRustWriter(std::ostream& s, Size start_offset, Size end_offset) const = 0;
diff --git a/system/gd/packet/parser/fields/padding_field.cc b/system/gd/packet/parser/fields/padding_field.cc
index e6a2c366bd..155bed6622 100644
--- a/system/gd/packet/parser/fields/padding_field.cc
+++ b/system/gd/packet/parser/fields/padding_field.cc
@@ -66,7 +66,6 @@ std::string PaddingField::GetRustDataType() const {
return "There's no type for Padding fields";
}
-void PaddingField::GenRustGetter(std::ostream&, Size, Size) const {
-}
+void PaddingField::GenRustGetter(std::ostream&, Size, Size, std::string) const {}
void PaddingField::GenRustWriter(std::ostream&, Size, Size) const {}
diff --git a/system/gd/packet/parser/fields/padding_field.h b/system/gd/packet/parser/fields/padding_field.h
index ea40ccded7..ca9664f4b5 100644
--- a/system/gd/packet/parser/fields/padding_field.h
+++ b/system/gd/packet/parser/fields/padding_field.h
@@ -53,7 +53,7 @@ class PaddingField : public PacketField {
virtual std::string GetRustDataType() const override;
- void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
+ void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset, std::string) const override;
void GenRustWriter(std::ostream& s, Size start_offset, Size end_offset) const override;
diff --git a/system/gd/packet/parser/fields/payload_field.cc b/system/gd/packet/parser/fields/payload_field.cc
index 844488242e..93491a1476 100644
--- a/system/gd/packet/parser/fields/payload_field.cc
+++ b/system/gd/packet/parser/fields/payload_field.cc
@@ -117,7 +117,29 @@ std::string PayloadField::GetRustDataType() const {
return "Vec::<u8>";
}
-void PayloadField::GenRustGetter(std::ostream& s, Size start_offset, Size) const {
+void PayloadField::GenBoundsCheck(std::ostream& s, Size start_offset, Size, std::string parent_name) const {
+ if (size_field_ != nullptr) {
+ s << "let want_ = " << start_offset.bytes() << " + (" << size_field_->GetName() << " as usize)";
+ if (!size_modifier_.empty()) {
+ s << " - ((" << size_modifier_.substr(1) << ") / 8)";
+ }
+ s << ";";
+ s << "if bytes.len() < want_ {";
+ s << " return Err(Error::InvalidLengthError{";
+ s << " obj: \"" << parent_name << "\".to_string(),";
+ s << " field: \"" << GetName() << "\".to_string(),";
+ s << " wanted: want_,";
+ s << " got: bytes.len()});";
+ s << "}";
+ if (!size_modifier_.empty()) {
+ s << "if ((" << size_field_->GetName() << " as usize) < ((" << size_modifier_.substr(1) << ") / 8)) {";
+ s << " return Err(Error::ImpossibleStructError);";
+ s << "}";
+ }
+ }
+}
+
+void PayloadField::GenRustGetter(std::ostream& s, Size start_offset, Size, std::string) const {
s << "let " << GetName() << ": " << GetRustDataType() << " = ";
if (size_field_ == nullptr) {
s << "bytes[" << start_offset.bytes() << "..].into();";
diff --git a/system/gd/packet/parser/fields/payload_field.h b/system/gd/packet/parser/fields/payload_field.h
index f86f27522b..aae05fb843 100644
--- a/system/gd/packet/parser/fields/payload_field.h
+++ b/system/gd/packet/parser/fields/payload_field.h
@@ -58,11 +58,11 @@ class PayloadField : public PacketField {
virtual std::string GetRustDataType() const override;
- void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
+ void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset, std::string) const override;
void GenRustWriter(std::ostream& s, Size start_offset, Size end_offset) const override;
- void GenBoundsCheck(std::ostream&, Size, Size, std::string) const override{};
+ void GenBoundsCheck(std::ostream&, Size, Size, std::string) const override;
// Payload fields can only be dynamically sized.
const SizeField* size_field_;
diff --git a/system/gd/packet/parser/fields/reserved_field.cc b/system/gd/packet/parser/fields/reserved_field.cc
index ac05338310..76fdf631fb 100644
--- a/system/gd/packet/parser/fields/reserved_field.cc
+++ b/system/gd/packet/parser/fields/reserved_field.cc
@@ -72,7 +72,6 @@ std::string ReservedField::GetRustDataType() const {
return util::GetRustTypeForSize(size_);
}
-void ReservedField::GenRustGetter(std::ostream&, Size, Size) const {
-}
+void ReservedField::GenRustGetter(std::ostream&, Size, Size, std::string) const {}
void ReservedField::GenRustWriter(std::ostream&, Size, Size) const {}
diff --git a/system/gd/packet/parser/fields/reserved_field.h b/system/gd/packet/parser/fields/reserved_field.h
index 7fabe499a1..f17418167b 100644
--- a/system/gd/packet/parser/fields/reserved_field.h
+++ b/system/gd/packet/parser/fields/reserved_field.h
@@ -49,7 +49,7 @@ class ReservedField : public PacketField {
virtual std::string GetRustDataType() const override;
- void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
+ void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset, std::string) const override;
void GenRustWriter(std::ostream& s, Size start_offset, Size end_offset) const override;
diff --git a/system/gd/packet/parser/fields/scalar_field.cc b/system/gd/packet/parser/fields/scalar_field.cc
index de5e31c9b2..10c85284c7 100644
--- a/system/gd/packet/parser/fields/scalar_field.cc
+++ b/system/gd/packet/parser/fields/scalar_field.cc
@@ -160,7 +160,7 @@ int ScalarField::GetRustBitOffset(
return num_leading_bits;
}
-void ScalarField::GenRustGetter(std::ostream& s, Size start_offset, Size end_offset) const {
+void ScalarField::GenRustGetter(std::ostream& s, Size start_offset, Size end_offset, std::string parent_name) const {
Size size = GetSize();
int num_leading_bits = GetRustBitOffset(s, start_offset, end_offset, GetSize());
@@ -207,7 +207,13 @@ void ScalarField::GenRustGetter(std::ostream& s, Size start_offset, Size end_off
// needs casting from primitive
if (GetRustParseDataType() != GetRustDataType()) {
s << "let " << GetName() << " = ";
- s << GetRustDataType() << "::from_" << GetRustParseDataType() << "(" << GetName() << ").unwrap();";
+ s << GetRustDataType() << "::from_" << GetRustParseDataType() << "(" << GetName() << ").ok_or_else(||";
+ s << "Error::InvalidEnumValueError {";
+ s << " obj: \"" << parent_name << "\".to_string(),";
+ s << " field: \"" << GetName() << "\".to_string(),";
+ s << " value: " << GetName() << " as u64,";
+ s << " type_: \"" << GetRustDataType() << "\".to_string(),";
+ s << "})?;";
}
}
diff --git a/system/gd/packet/parser/fields/scalar_field.h b/system/gd/packet/parser/fields/scalar_field.h
index 81616cee78..09fd16e236 100644
--- a/system/gd/packet/parser/fields/scalar_field.h
+++ b/system/gd/packet/parser/fields/scalar_field.h
@@ -58,7 +58,7 @@ class ScalarField : public PacketField {
virtual int GetRustBitOffset(std::ostream& s, Size start_offset,
Size end_offset, Size size) const override;
- void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
+ void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset, std::string) const override;
void GenRustWriter(std::ostream& s, Size start_offset, Size end_offset) const override;
diff --git a/system/gd/packet/parser/fields/struct_field.cc b/system/gd/packet/parser/fields/struct_field.cc
index 75ad1abb05..6555e60bb2 100644
--- a/system/gd/packet/parser/fields/struct_field.cc
+++ b/system/gd/packet/parser/fields/struct_field.cc
@@ -96,10 +96,10 @@ void StructField::GenBoundsCheck(std::ostream&, Size, Size, std::string) const {
// implicitly checked by the struct parser
}
-void StructField::GenRustGetter(std::ostream& s, Size start_offset, Size) const {
+void StructField::GenRustGetter(std::ostream& s, Size start_offset, Size, std::string) const {
s << "let " << GetName() << " = ";
s << GetRustDataType() << "::parse(&bytes[" << start_offset.bytes() << "..";
- s << start_offset.bytes() + GetSize().bytes() << "]).unwrap();";
+ s << start_offset.bytes() + GetSize().bytes() << "])?;";
}
void StructField::GenRustWriter(std::ostream& s, Size start_offset, Size) const {
diff --git a/system/gd/packet/parser/fields/struct_field.h b/system/gd/packet/parser/fields/struct_field.h
index acc5fb459c..051b9ef2d2 100644
--- a/system/gd/packet/parser/fields/struct_field.h
+++ b/system/gd/packet/parser/fields/struct_field.h
@@ -53,7 +53,7 @@ class StructField : public PacketField {
virtual std::string GetRustDataType() const override;
- void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
+ void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset, std::string) const override;
void GenRustWriter(std::ostream& s, Size start_offset, Size end_offset) const override;
diff --git a/system/gd/packet/parser/fields/variable_length_struct_field.cc b/system/gd/packet/parser/fields/variable_length_struct_field.cc
index 628b43ad34..6506d8f298 100644
--- a/system/gd/packet/parser/fields/variable_length_struct_field.cc
+++ b/system/gd/packet/parser/fields/variable_length_struct_field.cc
@@ -96,7 +96,6 @@ std::string VariableLengthStructField::GetRustDataType() const {
return ret;
}
-void VariableLengthStructField::GenRustGetter(std::ostream&, Size, Size) const {
-}
+void VariableLengthStructField::GenRustGetter(std::ostream&, Size, Size, std::string) const {}
void VariableLengthStructField::GenRustWriter(std::ostream&, Size, Size) const {}
diff --git a/system/gd/packet/parser/fields/variable_length_struct_field.h b/system/gd/packet/parser/fields/variable_length_struct_field.h
index 2774d4e7a5..a6c66d69ee 100644
--- a/system/gd/packet/parser/fields/variable_length_struct_field.h
+++ b/system/gd/packet/parser/fields/variable_length_struct_field.h
@@ -53,7 +53,7 @@ class VariableLengthStructField : public PacketField {
virtual std::string GetRustDataType() const override;
- void GenRustGetter(std::ostream&, Size, Size) const override;
+ void GenRustGetter(std::ostream&, Size, Size, std::string) const override;
void GenRustWriter(std::ostream& s, Size start_offset, Size end_offset) const override;
diff --git a/system/gd/packet/parser/fields/vector_field.cc b/system/gd/packet/parser/fields/vector_field.cc
index 9c8ca0715f..7678d99794 100644
--- a/system/gd/packet/parser/fields/vector_field.cc
+++ b/system/gd/packet/parser/fields/vector_field.cc
@@ -254,54 +254,54 @@ std::string VectorField::GetRustDataType() const {
return "Vec::<" + element_field_->GetRustDataType() + ">";
}
-void VectorField::GenBoundsCheck(std::ostream& s, Size start_offset, Size, std::string context) const {
+void VectorField::GenBoundsCheck(std::ostream& s, Size start_offset, Size, std::string parent_name) const {
auto element_field_type = GetElementField()->GetFieldType();
auto element_field = GetElementField();
- auto element_size = element_field->GetSize().bytes();
+ auto element_size = element_field->GetSize();
- if (element_field_type == ScalarField::kFieldType) {
- if (size_field_ == nullptr) {
- s << "let rem_ = (bytes.len() - " << start_offset.bytes() << ") % " << element_size << ";";
- s << "if rem_ != 0 {";
- s << " return Err(Error::InvalidLengthError{";
- s << " obj: \"" << context << "\".to_string(),";
- s << " field: \"" << GetName() << "\".to_string(),";
- s << " wanted: bytes.len() + rem_,";
- s << " got: bytes.len()});";
- s << "}";
- } else if (size_field_->GetFieldType() == CountField::kFieldType) {
- s << "let want_ = " << start_offset.bytes() << " + ((" << size_field_->GetName() << " as usize) * "
- << element_size << ");";
- s << "if bytes.len() < want_ {";
- s << " return Err(Error::InvalidLengthError{";
- s << " obj: \"" << context << "\".to_string(),";
- s << " field: \"" << GetName() << "\".to_string(),";
- s << " wanted: want_,";
- s << " got: bytes.len()});";
- s << "}";
- } else {
- s << "let want_ = " << start_offset.bytes() << " + (" << size_field_->GetName() << " as usize)";
- if (GetSizeModifier() != "") {
- s << " - ((" << GetSizeModifier().substr(1) << ") / 8)";
- }
- s << ";";
- s << "if bytes.len() < want_ {";
- s << " return Err(Error::InvalidLengthError{";
- s << " obj: \"" << context << "\".to_string(),";
- s << " field: \"" << GetName() << "\".to_string(),";
- s << " wanted: want_,";
- s << " got: bytes.len()});";
+ if (size_field_ != nullptr && size_field_->GetFieldType() == SizeField::kFieldType) {
+ s << "let want_ = " << start_offset.bytes() << " + (" << size_field_->GetName() << " as usize)";
+ if (GetSizeModifier() != "") {
+ s << " - ((" << GetSizeModifier().substr(1) << ") / 8)";
+ }
+ s << ";";
+ s << "if bytes.len() < want_ {";
+ s << " return Err(Error::InvalidLengthError{";
+ s << " obj: \"" << parent_name << "\".to_string(),";
+ s << " field: \"" << GetName() << "\".to_string(),";
+ s << " wanted: want_,";
+ s << " got: bytes.len()});";
+ s << "}";
+ if (GetSizeModifier() != "") {
+ s << "if ((" << size_field_->GetName() << " as usize) < ((" << GetSizeModifier().substr(1) << ") / 8)) {";
+ s << " return Err(Error::ImpossibleStructError);";
s << "}";
- if (GetSizeModifier() != "") {
- s << "if ((" << size_field_->GetName() << " as usize) < ((" << GetSizeModifier().substr(1) << ") / 8)) {";
- s << " return Err(Error::ImpossibleStructError);";
- s << "}";
- }
}
+ } else if (
+ size_field_ != nullptr && size_field_->GetFieldType() == CountField::kFieldType && !element_size.empty() &&
+ !element_size.has_dynamic()) {
+ s << "let want_ = " << start_offset.bytes() << " + ((" << size_field_->GetName() << " as usize) * "
+ << element_size.bytes() << ");";
+ s << "if bytes.len() < want_ {";
+ s << " return Err(Error::InvalidLengthError{";
+ s << " obj: \"" << parent_name << "\".to_string(),";
+ s << " field: \"" << GetName() << "\".to_string(),";
+ s << " wanted: want_,";
+ s << " got: bytes.len()});";
+ s << "}";
+ } else if (size_field_ == nullptr && element_field_type == ScalarField::kFieldType) {
+ s << "let rem_ = (bytes.len() - " << start_offset.bytes() << ") % " << element_size.bytes() << ";";
+ s << "if rem_ != 0 {";
+ s << " return Err(Error::InvalidLengthError{";
+ s << " obj: \"" << parent_name << "\".to_string(),";
+ s << " field: \"" << GetName() << "\".to_string(),";
+ s << " wanted: bytes.len() + rem_,";
+ s << " got: bytes.len()});";
+ s << "}";
}
}
-void VectorField::GenRustGetter(std::ostream& s, Size start_offset, Size) const {
+void VectorField::GenRustGetter(std::ostream& s, Size start_offset, Size, std::string) const {
auto element_field_type = GetElementField()->GetFieldType();
auto element_field = GetElementField();
auto element_size = element_field->GetSize().bytes();
diff --git a/system/gd/packet/parser/fields/vector_field.h b/system/gd/packet/parser/fields/vector_field.h
index e6b5330393..aa53eb4991 100644
--- a/system/gd/packet/parser/fields/vector_field.h
+++ b/system/gd/packet/parser/fields/vector_field.h
@@ -71,11 +71,11 @@ class VectorField : public PacketField {
virtual std::string GetRustDataType() const override;
- void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
+ void GenRustGetter(std::ostream& s, Size start_offset, Size end_offset, std::string) const override;
void GenRustWriter(std::ostream& s, Size start_offset, Size end_offset) const override;
- void GenBoundsCheck(std::ostream& s, Size start_offset, Size end_offset, std::string context) const override;
+ void GenBoundsCheck(std::ostream& s, Size start_offset, Size end_offset, std::string parent_name) const override;
const std::string name_;
diff --git a/system/gd/packet/parser/gen_rust.cc b/system/gd/packet/parser/gen_rust.cc
index 75e814a578..1097083941 100644
--- a/system/gd/packet/parser/gen_rust.cc
+++ b/system/gd/packet/parser/gen_rust.cc
@@ -50,6 +50,13 @@ pub enum Error {
},
#[error("Due to size restrictions a struct could not be parsed.")]
ImpossibleStructError,
+ #[error("when parsing field {obj}.{field}, {value} is not a valid {type_} value")]
+ InvalidEnumValueError {
+ obj: String,
+ field: String,
+ value: u64,
+ type_: String,
+ },
}
#[derive(Debug, Error)]
diff --git a/system/gd/packet/parser/packet_def.cc b/system/gd/packet/parser/packet_def.cc
index d30be830d3..3fe2218c9a 100644
--- a/system/gd/packet/parser/packet_def.cc
+++ b/system/gd/packet/parser/packet_def.cc
@@ -929,7 +929,7 @@ void PacketDef::GenRustStructImpls(std::ostream& s) const {
}
field->GenBoundsCheck(s, start_field_offset, end_field_offset, name_);
- field->GenRustGetter(s, start_field_offset, end_field_offset);
+ field->GenRustGetter(s, start_field_offset, end_field_offset, name_);
}
auto payload_field = fields_.GetFieldsWithTypes({
diff --git a/system/gd/packet/parser/parent_def.cc b/system/gd/packet/parser/parent_def.cc
index e4b7353cb3..0df4a5d3cd 100644
--- a/system/gd/packet/parser/parent_def.cc
+++ b/system/gd/packet/parser/parent_def.cc
@@ -618,7 +618,7 @@ void ParentDef::GenRustConformanceCheck(std::ostream& s) const {
auto end_offset = GetOffsetForField(field->GetName(), true);
auto f = (FixedScalarField*)field;
- f->GenRustGetter(s, start_offset, end_offset);
+ f->GenRustGetter(s, start_offset, end_offset, name_);
s << "if " << f->GetName() << " != ";
f->GenValue(s);
s << " { return false; } ";
diff --git a/system/gd/packet/parser/struct_def.cc b/system/gd/packet/parser/struct_def.cc
index d602e25e9e..4f6e981e58 100644
--- a/system/gd/packet/parser/struct_def.cc
+++ b/system/gd/packet/parser/struct_def.cc
@@ -384,7 +384,7 @@ void StructDef::GenRustImpls(std::ostream& s) const {
}
field->GenBoundsCheck(s, start_field_offset, end_field_offset, name_);
- field->GenRustGetter(s, start_field_offset, end_field_offset);
+ field->GenRustGetter(s, start_field_offset, end_field_offset, name_);
}
fields = fields_.GetFieldsWithoutTypes({
diff --git a/system/gd/packet/parser/test/rust_test_packets.pdl b/system/gd/packet/parser/test/rust_test_packets.pdl
index 387a553778..d791979f3d 100644
--- a/system/gd/packet/parser/test/rust_test_packets.pdl
+++ b/system/gd/packet/parser/test/rust_test_packets.pdl
@@ -1,5 +1,45 @@
little_endian_packets
+custom_field Boolean: 8 "Boolean"
+enum Enum : 8 {
+ // Keep 0x0 as invalid value
+ ONE = 1,
+ TWO = 2,
+}
+
+struct Struct {
+ v: Enum,
+ u: 8,
+}
+
+packet TestEnum {
+ v: Enum,
+}
+
+packet TestCustomField {
+ v: Boolean,
+}
+
+packet TestArraySize {
+ _size_(array) : 8,
+ array : Struct[],
+}
+
+packet TestArrayCount {
+ _count_(array) : 8,
+ array : Struct[],
+}
+
+packet TestPayloadSize {
+ _size_(_payload_) : 8,
+ _payload_,
+}
+
+packet TestBodySize {
+ _size_(_body_) : 8,
+ _body_,
+}
+
// Test Packets #1
enum OpCode: 8 {
ADD_ERR = 0,
@@ -122,5 +162,3 @@ test ChildThree {
test GrandChildThreeFive {
"\x01\x02\x03\x01",
}
-
-
diff --git a/system/gd/rust/linux/client/src/dbus_iface.rs b/system/gd/rust/linux/client/src/dbus_iface.rs
index 5a93233bba..20b11329f9 100644
--- a/system/gd/rust/linux/client/src/dbus_iface.rs
+++ b/system/gd/rust/linux/client/src/dbus_iface.rs
@@ -237,8 +237,6 @@ impl BluetoothDBus {
}
}
-trait DBusExportable {}
-
#[generate_dbus_interface_client]
impl IBluetooth for BluetoothDBus {
#[dbus_method("RegisterCallback")]
diff --git a/system/gd/rust/linux/mgmt/src/bin/btmanagerd/bluetooth_manager.rs b/system/gd/rust/linux/mgmt/src/bin/btmanagerd/bluetooth_manager.rs
index 8daf0b7efb..706fb11113 100644
--- a/system/gd/rust/linux/mgmt/src/bin/btmanagerd/bluetooth_manager.rs
+++ b/system/gd/rust/linux/mgmt/src/bin/btmanagerd/bluetooth_manager.rs
@@ -61,6 +61,11 @@ impl BluetoothManager {
pub(crate) fn callback_disconnected(&mut self, id: u32) {
self.callbacks.remove(&id);
}
+
+ pub(crate) fn get_floss_enabled_internal(&mut self) -> bool {
+ let enabled = self.manager_context.floss_enabled.load(Ordering::Relaxed);
+ enabled
+ }
}
impl IBluetoothManager for BluetoothManager {
@@ -115,8 +120,7 @@ impl IBluetoothManager for BluetoothManager {
}
fn get_floss_enabled(&mut self) -> bool {
- let enabled = self.manager_context.floss_enabled.load(Ordering::Relaxed);
- enabled
+ self.get_floss_enabled_internal()
}
fn set_floss_enabled(&mut self, enabled: bool) {
diff --git a/system/gd/rust/linux/mgmt/src/bin/btmanagerd/bluetooth_manager_dbus.rs b/system/gd/rust/linux/mgmt/src/bin/btmanagerd/bluetooth_manager_dbus.rs
index 9ff9cea800..ee8373d402 100644
--- a/system/gd/rust/linux/mgmt/src/bin/btmanagerd/bluetooth_manager_dbus.rs
+++ b/system/gd/rust/linux/mgmt/src/bin/btmanagerd/bluetooth_manager_dbus.rs
@@ -1,7 +1,7 @@
use dbus::arg::RefArg;
use dbus::strings::Path;
use dbus_macros::{dbus_method, dbus_propmap, dbus_proxy_obj, generate_dbus_exporter};
-use dbus_projection::DisconnectWatcher;
+use dbus_projection::{dbus_generated, DisconnectWatcher};
use manager_service::iface_bluetooth_manager::{
AdapterWithEnabled, IBluetoothManager, IBluetoothManagerCallback,
@@ -22,30 +22,38 @@ struct BluetoothManagerDBus {}
#[generate_dbus_exporter(export_bluetooth_manager_dbus_obj, "org.chromium.bluetooth.Manager")]
impl IBluetoothManager for BluetoothManagerDBus {
#[dbus_method("Start")]
- fn start(&mut self, _hci_interface: i32) {}
+ fn start(&mut self, hci_interface: i32) {
+ dbus_generated!()
+ }
#[dbus_method("Stop")]
- fn stop(&mut self, _hci_interface: i32) {}
+ fn stop(&mut self, hci_interface: i32) {
+ dbus_generated!()
+ }
#[dbus_method("GetAdapterEnabled")]
- fn get_adapter_enabled(&mut self, _hci_interface: i32) -> bool {
- false
+ fn get_adapter_enabled(&mut self, hci_interface: i32) -> bool {
+ dbus_generated!()
}
#[dbus_method("RegisterCallback")]
- fn register_callback(&mut self, _callback: Box<dyn IBluetoothManagerCallback + Send>) {}
+ fn register_callback(&mut self, callback: Box<dyn IBluetoothManagerCallback + Send>) {
+ dbus_generated!()
+ }
#[dbus_method("GetFlossEnabled")]
fn get_floss_enabled(&mut self) -> bool {
- false
+ dbus_generated!()
}
#[dbus_method("SetFlossEnabled")]
- fn set_floss_enabled(&mut self, _enabled: bool) {}
+ fn set_floss_enabled(&mut self, enabled: bool) {
+ dbus_generated!()
+ }
#[dbus_method("GetAvailableAdapters")]
fn get_available_adapters(&mut self) -> Vec<AdapterWithEnabled> {
- vec![]
+ dbus_generated!()
}
}
diff --git a/system/gd/rust/linux/mgmt/src/bin/btmanagerd/state_machine.rs b/system/gd/rust/linux/mgmt/src/bin/btmanagerd/state_machine.rs
index 52b5ff0ed0..aa17c6d27d 100644
--- a/system/gd/rust/linux/mgmt/src/bin/btmanagerd/state_machine.rs
+++ b/system/gd/rust/linux/mgmt/src/bin/btmanagerd/state_machine.rs
@@ -5,11 +5,12 @@ use log::{debug, error, info, warn};
use nix::sys::signal::{self, Signal};
use nix::unistd::Pid;
use regex::Regex;
+use std::cmp;
use std::process::{Child, Command, Stdio};
use std::sync::Arc;
-use std::time::Duration;
use tokio::io::unix::AsyncFd;
use tokio::sync::mpsc;
+use tokio::time::{sleep, Duration};
// Directory for Bluetooth pid file
pub const PID_DIR: &str = "/var/run/bluetooth";
@@ -84,6 +85,10 @@ pub struct StateMachineProxy {
const TX_SEND_TIMEOUT_DURATION: Duration = Duration::from_secs(3);
const COMMAND_TIMEOUT_DURATION: Duration = Duration::from_secs(3);
+/// Maximum amount of time (in seconds) we should wait before polling for
+/// /sys/class/bluetooth to become available.
+const HCI_DEVICE_SLEEP_MAX_SECONDS: u64 = 64;
+
impl StateMachineProxy {
pub fn start_bluetooth(&self, hci_interface: i32) {
let tx = self.tx.clone();
@@ -122,8 +127,8 @@ fn pid_inotify_async_fd() -> AsyncFd<inotify::Inotify> {
let mut pid_detector = inotify::Inotify::init().expect("cannot use inotify");
pid_detector
.add_watch(PID_DIR, inotify::WatchMask::CREATE | inotify::WatchMask::DELETE)
- .expect("failed to add watch");
- AsyncFd::new(pid_detector).expect("failed to add async fd")
+ .expect("failed to add watch on pid directory");
+ AsyncFd::new(pid_detector).expect("failed to add async fd for pid detector")
}
/// Given an pid path, returns the adapter index for that pid path.
@@ -132,15 +137,29 @@ fn get_hci_index_from_pid_path(path: &str) -> Option<i32> {
re.captures(path)?.get(1)?.as_str().parse().ok()
}
-fn hci_devices_inotify_async_fd() -> AsyncFd<inotify::Inotify> {
- let mut detector = inotify::Inotify::init().expect("cannot use inotify");
- detector
- .add_watch(
+fn hci_devices_inotify_async_fd() -> Option<AsyncFd<inotify::Inotify>> {
+ let detector = inotify::Inotify::init().and_then(|mut detector| {
+ match detector.add_watch(
config_util::HCI_DEVICES_DIR,
inotify::WatchMask::CREATE | inotify::WatchMask::DELETE,
- )
- .expect("failed to add watch");
- AsyncFd::new(detector).expect("failed to add async fd")
+ ) {
+ Ok(_) => Ok(detector),
+ Err(e) => Err(e),
+ }
+ });
+ match detector {
+ Ok(d) => match AsyncFd::new(d) {
+ Ok(afd) => Some(afd),
+ Err(_) => {
+ warn!("Could not init asyncfd for {}", config_util::HCI_DEVICES_DIR);
+ None
+ }
+ },
+ Err(_) => {
+ warn!("Could not init inotify: {}", config_util::HCI_DEVICES_DIR);
+ None
+ }
+ }
}
/// On startup, get and cache all hci devices by emitting the callback
@@ -190,6 +209,8 @@ pub async fn mainloop(
});
let init_tx = context.tx.clone();
+ let floss_enabled = bluetooth_manager.lock().unwrap().get_floss_enabled_internal();
+
tokio::spawn(async move {
// Get a list of active pid files to determine initial adapter status
let files = config_util::list_pid_files(PID_DIR);
@@ -203,18 +224,22 @@ pub async fn mainloop(
.unwrap();
}
- // Initialize adapter states based on saved config
- let hci_devices = config_util::list_hci_devices();
- for device in hci_devices.iter() {
- let is_enabled = config_util::is_hci_n_enabled(*device);
- if is_enabled {
- let _ = init_tx
- .send_timeout(
- Message::AdapterStateChange(AdapterStateActions::StartBluetooth(*device)),
- TX_SEND_TIMEOUT_DURATION,
- )
- .await
- .unwrap();
+ // Initialize adapter states based on saved config only if floss is enabled.
+ if floss_enabled {
+ let hci_devices = config_util::list_hci_devices();
+ for device in hci_devices.iter() {
+ let is_enabled = config_util::is_hci_n_enabled(*device);
+ if is_enabled {
+ let _ = init_tx
+ .send_timeout(
+ Message::AdapterStateChange(AdapterStateActions::StartBluetooth(
+ *device,
+ )),
+ TX_SEND_TIMEOUT_DURATION,
+ )
+ .await
+ .unwrap();
+ }
}
}
});
@@ -244,7 +269,7 @@ pub async fn mainloop(
.unwrap();
}
}
- Err(_) | Ok(Err(_)) => panic!("why can't we read while the asyncfd is ready?"),
+ Err(_) | Ok(Err(_)) => panic!("Inotify watcher on {} failed.", PID_DIR),
}
fd_ready.clear_ready();
drop(fd_ready);
@@ -252,35 +277,67 @@ pub async fn mainloop(
});
// Set up an HCI device listener to emit HCI device inotify messages
- let mut hci_devices_async_fd = hci_devices_inotify_async_fd();
let hci_tx = context.tx.clone();
tokio::spawn(async move {
debug!("Spawned hci notify task");
+
+ // Try to create an inotify on /sys/class/bluetooth and listen for any
+ // changes. If we fail to create the inotify, we go into a polling mode
+ // which will do exponential backoff waiting for Bluetooth to become
+ // available.
+ //
+ // TODO(b/226644782) - Eventually we need to replace this inotify
+ // listener with something that talks to MGMT via socket(AF_BLUETOOTH).
+ // We should poll on INDEX_ADDED/INDEX_REMOVED rather than inotify the
+ // /sys/class/bluetooth directory.
+ let mut sleep_duration = 1;
loop {
- let r = hci_devices_async_fd.readable_mut();
- let mut fd_ready = r.await.unwrap();
- let mut buffer: [u8; 1024] = [0; 1024];
- debug!("Found new hci device entries. Reading them.");
- match fd_ready.try_io(|inner| inner.get_mut().read_events(&mut buffer)) {
- Ok(Ok(events)) => {
- for event in events {
- let _ = hci_tx
- .send_timeout(
- Message::HciDeviceChange(
- event.mask,
- event_name_to_string(event.name),
- ),
- TX_SEND_TIMEOUT_DURATION,
- )
- .await
- .unwrap();
+ match hci_devices_inotify_async_fd() {
+ Some(mut hci_inotify) => {
+ sleep_duration = 1;
+
+ // This inner loop runs successfully as long as the hci inotify is valid.
+ loop {
+ let r = hci_inotify.readable_mut();
+ let mut fd_ready = r.await.unwrap();
+ let mut buffer: [u8; 1024] = [0; 1024];
+ debug!("Found new hci device entries. Reading them.");
+ match fd_ready.try_io(|inner| inner.get_mut().read_events(&mut buffer)) {
+ Ok(Ok(events)) => {
+ for event in events {
+ let _ = hci_tx
+ .send_timeout(
+ Message::HciDeviceChange(
+ event.mask,
+ event_name_to_string(event.name),
+ ),
+ TX_SEND_TIMEOUT_DURATION,
+ )
+ .await
+ .unwrap();
+ }
+ }
+ // In the case where inotify fails, we want to reconfigure the inotify
+ // again.
+ Err(_) | Ok(Err(_)) => {
+ warn!(
+ "Inotify watcher on {} failed.",
+ config_util::HCI_DEVICES_DIR
+ );
+ break;
+ }
+ }
+ fd_ready.clear_ready();
+ drop(fd_ready);
}
}
- Err(_) | Ok(Err(_)) => panic!("why can't we read while the asyncfd is ready?"),
+ None => {
+ // Exponential backoff until we succeed.
+ sleep_duration = cmp::min(sleep_duration * 2, HCI_DEVICE_SLEEP_MAX_SECONDS);
+ sleep(Duration::from_secs(sleep_duration)).await;
+ }
}
- fd_ready.clear_ready();
- drop(fd_ready);
}
});
@@ -337,7 +394,7 @@ pub async fn mainloop(
true => {
command_timeout.cancel();
}
- false => error!("unexpected BluetoothStarted pid{} hci{}", pid, hci),
+ false => warn!("unexpected BluetoothStarted pid{} hci{}", pid, hci),
}
}
AdapterStateActions::BluetoothStopped(i) => {
@@ -387,9 +444,7 @@ pub async fn mainloop(
.await
.unwrap();
}
- (hci, s) => {
- warn!("invalid file hci={:?} pid_file={:?}", hci, s)
- }
+ _ => debug!("Invalid pid path: {}", fname),
}
}
(inotify::EventMask::DELETE, Some(fname)) => {
diff --git a/system/gd/rust/linux/service/src/iface_bluetooth.rs b/system/gd/rust/linux/service/src/iface_bluetooth.rs
index 9d84b1d3c5..37769b67b1 100644
--- a/system/gd/rust/linux/service/src/iface_bluetooth.rs
+++ b/system/gd/rust/linux/service/src/iface_bluetooth.rs
@@ -194,17 +194,17 @@ impl IBluetooth for IBluetoothDBus {
}
#[dbus_method("CreateBond")]
- fn create_bond(&self, _device: BluetoothDevice, _transport: BtTransport) -> bool {
+ fn create_bond(&self, device: BluetoothDevice, transport: BtTransport) -> bool {
dbus_generated!()
}
#[dbus_method("CancelBondProcess")]
- fn cancel_bond_process(&self, _device: BluetoothDevice) -> bool {
+ fn cancel_bond_process(&self, device: BluetoothDevice) -> bool {
dbus_generated!()
}
#[dbus_method("RemoveBond")]
- fn remove_bond(&self, _device: BluetoothDevice) -> bool {
+ fn remove_bond(&self, device: BluetoothDevice) -> bool {
dbus_generated!()
}
@@ -214,22 +214,22 @@ impl IBluetooth for IBluetoothDBus {
}
#[dbus_method("GetBondState")]
- fn get_bond_state(&self, _device: BluetoothDevice) -> u32 {
+ fn get_bond_state(&self, device: BluetoothDevice) -> u32 {
dbus_generated!()
}
#[dbus_method("SetPin")]
- fn set_pin(&self, _device: BluetoothDevice, _accept: bool, _pin_code: Vec<u8>) -> bool {
+ fn set_pin(&self, device: BluetoothDevice, accept: bool, pin_code: Vec<u8>) -> bool {
dbus_generated!()
}
#[dbus_method("SetPasskey")]
- fn set_passkey(&self, _device: BluetoothDevice, _accept: bool, _passkey: Vec<u8>) -> bool {
+ fn set_passkey(&self, device: BluetoothDevice, accept: bool, passkey: Vec<u8>) -> bool {
dbus_generated!()
}
#[dbus_method("SetPairingConfirmation")]
- fn set_pairing_confirmation(&self, _device: BluetoothDevice, _accept: bool) -> bool {
+ fn set_pairing_confirmation(&self, device: BluetoothDevice, accept: bool) -> bool {
dbus_generated!()
}
@@ -254,37 +254,37 @@ impl IBluetooth for IBluetoothDBus {
}
#[dbus_method("GetConnectionState")]
- fn get_connection_state(&self, _device: BluetoothDevice) -> u32 {
+ fn get_connection_state(&self, device: BluetoothDevice) -> u32 {
dbus_generated!()
}
#[dbus_method("GetProfileConnectionState")]
- fn get_profile_connection_state(&self, _profile: Profile) -> u32 {
+ fn get_profile_connection_state(&self, profile: Profile) -> u32 {
dbus_generated!()
}
#[dbus_method("GetRemoteUuids")]
- fn get_remote_uuids(&self, _device: BluetoothDevice) -> Vec<Uuid128Bit> {
+ fn get_remote_uuids(&self, device: BluetoothDevice) -> Vec<Uuid128Bit> {
dbus_generated!()
}
#[dbus_method("FetchRemoteUuids")]
- fn fetch_remote_uuids(&self, _device: BluetoothDevice) -> bool {
+ fn fetch_remote_uuids(&self, device: BluetoothDevice) -> bool {
dbus_generated!()
}
#[dbus_method("SdpSearch")]
- fn sdp_search(&self, _device: BluetoothDevice, _uuid: Uuid128Bit) -> bool {
+ fn sdp_search(&self, device: BluetoothDevice, uuid: Uuid128Bit) -> bool {
dbus_generated!()
}
#[dbus_method("ConnectAllEnabledProfiles")]
- fn connect_all_enabled_profiles(&self, _device: BluetoothDevice) -> bool {
+ fn connect_all_enabled_profiles(&self, device: BluetoothDevice) -> bool {
dbus_generated!()
}
#[dbus_method("DisconnectAllEnabledProfiles")]
- fn disconnect_all_enabled_profiles(&self, _device: BluetoothDevice) -> bool {
+ fn disconnect_all_enabled_profiles(&self, device: BluetoothDevice) -> bool {
dbus_generated!()
}
}
diff --git a/system/gd/rust/linux/service/src/iface_bluetooth_gatt.rs b/system/gd/rust/linux/service/src/iface_bluetooth_gatt.rs
index 8adf3e71a3..c595fa0749 100644
--- a/system/gd/rust/linux/service/src/iface_bluetooth_gatt.rs
+++ b/system/gd/rust/linux/service/src/iface_bluetooth_gatt.rs
@@ -30,7 +30,7 @@ struct BluetoothGattCallbackDBus {}
#[dbus_proxy_obj(BluetoothGattCallback, "org.chromium.bluetooth.BluetoothGattCallback")]
impl IBluetoothGattCallback for BluetoothGattCallbackDBus {
#[dbus_method("OnClientRegistered")]
- fn on_client_registered(&self, _status: i32, _scanner_id: i32) {
+ fn on_client_registered(&self, status: i32, scanner_id: i32) {
dbus_generated!()
}
@@ -142,7 +142,7 @@ struct ScannerCallbackDBus {}
#[dbus_proxy_obj(ScannerCallback, "org.chromium.bluetooth.ScannerCallback")]
impl IScannerCallback for ScannerCallbackDBus {
#[dbus_method("OnScannerRegistered")]
- fn on_scanner_registered(&self, _status: i32, _scanner_id: i32) {
+ fn on_scanner_registered(&self, status: i32, scanner_id: i32) {
dbus_generated!()
}
}
diff --git a/system/gd/rust/linux/stack/src/bluetooth_gatt.rs b/system/gd/rust/linux/stack/src/bluetooth_gatt.rs
index 92d6cc7e8c..6f2653eb14 100644
--- a/system/gd/rust/linux/stack/src/bluetooth_gatt.rs
+++ b/system/gd/rust/linux/stack/src/bluetooth_gatt.rs
@@ -1458,6 +1458,8 @@ mod tests {
fn unregister(&mut self, _id: u32) -> bool {
false
}
+
+ fn export_for_rpc(self: Box<Self>) {}
}
use super::*;
diff --git a/system/gd/rust/linux/stack/src/bluetooth_media.rs b/system/gd/rust/linux/stack/src/bluetooth_media.rs
index 0f2488aa10..5b7d820460 100644
--- a/system/gd/rust/linux/stack/src/bluetooth_media.rs
+++ b/system/gd/rust/linux/stack/src/bluetooth_media.rs
@@ -22,9 +22,13 @@ use std::sync::Arc;
use std::sync::Mutex;
use tokio::sync::mpsc::Sender;
+use tokio::task::JoinHandle;
+use tokio::time::{sleep, Duration};
use crate::Message;
+const DEFAULT_PROFILE_DISCOVERY_TIMEOUT_SEC: u64 = 5;
+
pub trait IBluetoothMedia {
///
fn register_callback(&mut self, callback: Box<dyn IBluetoothMediaCallback + Send>) -> bool;
@@ -86,7 +90,7 @@ pub enum MediaActions {
pub struct BluetoothMedia {
intf: Arc<Mutex<BluetoothInterface>>,
initialized: bool,
- callbacks: Vec<(u32, Box<dyn IBluetoothMediaCallback + Send>)>,
+ callbacks: Arc<Mutex<Vec<(u32, Box<dyn IBluetoothMediaCallback + Send>)>>>,
callback_last_id: u32,
tx: Sender<Message>,
a2dp: Option<A2dp>,
@@ -95,6 +99,8 @@ pub struct BluetoothMedia {
hfp: Option<Hfp>,
hfp_states: HashMap<RawAddress, BthfConnectionState>,
selectable_caps: HashMap<RawAddress, Vec<A2dpCodecConfig>>,
+ hfp_caps: HashMap<RawAddress, HfpCodecCapability>,
+ device_added_tasks: Arc<Mutex<HashMap<RawAddress, Option<JoinHandle<()>>>>>,
}
impl BluetoothMedia {
@@ -102,7 +108,7 @@ impl BluetoothMedia {
BluetoothMedia {
intf,
initialized: false,
- callbacks: vec![],
+ callbacks: Arc::new(Mutex::new(vec![])),
callback_last_id: 0,
tx,
a2dp: None,
@@ -111,6 +117,8 @@ impl BluetoothMedia {
hfp: None,
hfp_states: HashMap::new(),
selectable_caps: HashMap::new(),
+ hfp_caps: HashMap::new(),
+ device_added_tasks: Arc::new(Mutex::new(HashMap::new())),
}
}
@@ -124,36 +132,20 @@ impl BluetoothMedia {
}
match state {
BtavConnectionState::Connected => {
- if let Some(caps) = self.selectable_caps.get(&addr) {
- for cap in caps {
- // TODO: support codecs other than SBC.
- if A2dpCodecIndex::SrcSbc != A2dpCodecIndex::from(cap.codec_type) {
- continue;
- }
-
- // TODO: Coordinate with HFP. Should only trigger once.
- self.for_all_callbacks(|callback| {
- callback.on_bluetooth_audio_device_added(
- addr.to_string(),
- cap.sample_rate,
- cap.bits_per_sample,
- cap.channel_mode,
- HfpCodecCapability::UNSUPPORTED.bits(),
- );
- });
- return;
- }
- }
+ info!("[{}]: a2dp connected.", addr.to_string());
+ self.notify_media_capability_added(addr);
+ self.a2dp_states.insert(addr, state);
}
- BtavConnectionState::Connecting => {}
- BtavConnectionState::Disconnected => {
- self.for_all_callbacks(|callback| {
- callback.on_bluetooth_audio_device_removed(addr.to_string());
- });
+ BtavConnectionState::Disconnected => match self.a2dp_states.remove(&addr) {
+ Some(_) => self.notify_media_capability_removed(addr),
+ None => {
+ warn!("[{}]: Unknown address a2dp disconnected.", addr.to_string());
+ }
+ },
+ _ => {
+ self.a2dp_states.insert(addr, state);
}
- BtavConnectionState::Disconnecting => {}
- };
- self.a2dp_states.insert(addr, state);
+ }
}
A2dpCallbacks::AudioState(_addr, _state) => {}
A2dpCallbacks::AudioConfig(addr, _config, _local_caps, selectable_caps) => {
@@ -195,29 +187,29 @@ impl BluetoothMedia {
}
match state {
BthfConnectionState::Connected => {
- info!("{} HFP connected.", addr.to_string());
+ info!("[{}]: hfp connected.", addr.to_string());
}
BthfConnectionState::SlcConnected => {
- info!("{} HFP SLC connected.", addr.to_string());
- // TODO: Coordinate with A2DP. Should only trigger once.
- self.for_all_callbacks(|callback| {
- callback.on_bluetooth_audio_device_added(
- addr.to_string(),
- 0,
- 0,
- 0,
- HfpCodecCapability::CVSD.bits(),
- );
- });
+ info!("[{}]: hfp slc connected.", addr.to_string());
+ // TODO(b/214148074): Support WBS
+ self.hfp_caps.insert(addr, HfpCodecCapability::CVSD);
+ self.notify_media_capability_added(addr);
}
BthfConnectionState::Disconnected => {
- info!("{} HFP disconnected.", addr.to_string());
+ info!("[{}]: hfp disconnected.", addr.to_string());
+ match self.hfp_states.remove(&addr) {
+ Some(_) => self.notify_media_capability_removed(addr),
+ None => {
+ warn!("[{}] Unknown address hfp disconnected.", addr.to_string())
+ }
+ }
+ return;
}
BthfConnectionState::Connecting => {
- info!("{} HFP connecting.", addr.to_string());
+ info!("[{}]: hfp connecting.", addr.to_string());
}
BthfConnectionState::Disconnecting => {
- info!("{} HFP disconnecting.", addr.to_string());
+ info!("[{}]: hfp disconnecting.", addr.to_string());
}
}
@@ -227,29 +219,141 @@ impl BluetoothMedia {
if self.hfp_states.get(&addr).is_none()
|| BthfConnectionState::SlcConnected != *self.hfp_states.get(&addr).unwrap()
{
- warn!("{} not connected or SLC not ready", addr.to_string());
+ warn!("[{}]: Unknown address hfp or slc not ready", addr.to_string());
return;
}
match state {
BthfAudioState::Connected => {
- info!("{} HFP audio connected.", addr.to_string());
+ info!("[{}]: hfp audio connected.", addr.to_string());
}
BthfAudioState::Disconnected => {
- info!("{} HFP audio disconnected.", addr.to_string());
+ info!("[{}]: hfp audio disconnected.", addr.to_string());
}
BthfAudioState::Connecting => {
- info!("{} HFP audio connecting.", addr.to_string());
+ info!("[{}]: hfp audio connecting.", addr.to_string());
}
BthfAudioState::Disconnecting => {
- info!("{} HFP audio disconnecting.", addr.to_string());
+ info!("[{}]: hfp audio disconnecting.", addr.to_string());
+ }
+ }
+ }
+ }
+ }
+
+ fn notify_media_capability_added(&self, addr: RawAddress) {
+ // Return true if the device added message is sent by the call.
+ fn dedup_added_cb(
+ device_added_tasks: Arc<Mutex<HashMap<RawAddress, Option<JoinHandle<()>>>>>,
+ addr: RawAddress,
+ callbacks: Arc<Mutex<Vec<(u32, Box<dyn IBluetoothMediaCallback + Send>)>>>,
+ cap: A2dpCodecConfig,
+ hfp_cap: HfpCodecCapability,
+ is_delayed: bool,
+ ) -> bool {
+ // Closure used to lock and trigger the device added callbacks.
+ let trigger_device_added = || {
+ for callback in &*callbacks.lock().unwrap() {
+ callback.1.on_bluetooth_audio_device_added(
+ addr.to_string(),
+ cap.sample_rate,
+ cap.bits_per_sample,
+ cap.channel_mode,
+ hfp_cap.bits(),
+ );
+ }
+ };
+ let mut guard = device_added_tasks.lock().unwrap();
+ let task = guard.insert(addr, None);
+ match task {
+ // None handler means the device has just been added
+ Some(handler) if handler.is_none() => {
+ warn!("[{}]: A device with the same address has been added.", addr.to_string());
+ false
+ }
+ // Not None handler means there is a pending task.
+ Some(handler) => {
+ trigger_device_added();
+
+ // Abort the delayed callback if the caller is not delayed.
+ // Otherwise, it is the delayed callback task itself.
+ // The abort call can be out of the critical section as we
+ // have updated the device_added_tasks and send the message.
+ drop(guard);
+ if !is_delayed {
+ handler.unwrap().abort();
}
+ true
}
+ // The delayed callback task has been removed and couldn't be found.
+ None if is_delayed => false,
+ // No delayed callback and the device hasn't been added.
+ None => {
+ trigger_device_added();
+ true
+ }
+ }
+ }
+
+ let cur_a2dp_cap = self.selectable_caps.get(&addr).and_then(|a2dp_caps| {
+ a2dp_caps
+ .iter()
+ .find(|cap| A2dpCodecIndex::SrcSbc == A2dpCodecIndex::from(cap.codec_type))
+ });
+ let cur_hfp_cap = self.hfp_caps.get(&addr);
+ match (cur_a2dp_cap, cur_hfp_cap) {
+ (None, None) => warn!(
+ "[{}]: Try to add a device without a2dp and hfp capability.",
+ addr.to_string()
+ ),
+ (Some(cap), Some(hfp_cap)) => {
+ dedup_added_cb(
+ self.device_added_tasks.clone(),
+ addr,
+ self.callbacks.clone(),
+ *cap,
+ *hfp_cap,
+ false,
+ );
}
+ (_, _) => {
+ let mut guard = self.device_added_tasks.lock().unwrap();
+ if guard.get(&addr).is_none() {
+ let callbacks = self.callbacks.clone();
+ let device_added_tasks = self.device_added_tasks.clone();
+ let cap = cur_a2dp_cap.unwrap_or(&A2dpCodecConfig::default()).clone();
+ let hfp_cap = cur_hfp_cap.unwrap_or(&HfpCodecCapability::UNSUPPORTED).clone();
+ let task = topstack::get_runtime().spawn(async move {
+ sleep(Duration::from_secs(DEFAULT_PROFILE_DISCOVERY_TIMEOUT_SEC)).await;
+ if dedup_added_cb(device_added_tasks, addr, callbacks, cap, hfp_cap, true) {
+ warn!(
+ "[{}]: Add a device with only hfp or a2dp capability after timeout.",
+ addr.to_string()
+ );
+ }
+ });
+ guard.insert(addr, Some(task));
+ }
+ }
+ }
+ }
+
+ fn notify_media_capability_removed(&self, addr: RawAddress) {
+ if let Some(task) = self.device_added_tasks.lock().unwrap().remove(&addr) {
+ match task {
+ // Abort what is pending
+ Some(handler) => handler.abort(),
+ // This addr has been added so tell audio server to remove it
+ None => self.for_all_callbacks(|callback| {
+ callback.on_bluetooth_audio_device_removed(addr.to_string());
+ }),
+ }
+ } else {
+ warn!("[{}]: Device hasn't been added yet.", addr.to_string());
}
}
fn for_all_callbacks<F: Fn(&Box<dyn IBluetoothMediaCallback + Send>)>(&self, f: F) {
- for callback in &self.callbacks {
+ for callback in &*self.callbacks.lock().unwrap() {
f(&callback.1);
}
}
@@ -305,7 +409,7 @@ fn get_hfp_dispatcher(tx: Sender<Message>) -> HfpCallbacksDispatcher {
impl IBluetoothMedia for BluetoothMedia {
fn register_callback(&mut self, callback: Box<dyn IBluetoothMediaCallback + Send>) -> bool {
self.callback_last_id += 1;
- self.callbacks.push((self.callback_last_id, callback));
+ self.callbacks.lock().unwrap().push((self.callback_last_id, callback));
true
}
diff --git a/system/gd/rust/packets/test_lib.rs b/system/gd/rust/packets/test_lib.rs
index d689572c30..960178c81d 100644
--- a/system/gd/rust/packets/test_lib.rs
+++ b/system/gd/rust/packets/test_lib.rs
@@ -4,10 +4,98 @@
#![allow(unused)]
#![allow(missing_docs)]
-pub mod custom_types;
+use std::convert::TryFrom;
+use std::fmt;
-pub mod hci {
- use crate::custom_types::*;
+pub mod test_packets {
+
+ // Custom boolean type
+ #[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Debug)]
+ pub struct Boolean {
+ pub value: u8,
+ }
+
+ impl fmt::Display for Boolean {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{:02x}", self.value)
+ }
+ }
+
+ #[derive(Debug, Clone)]
+ pub struct InvalidBooleanError;
+
+ impl TryFrom<&[u8]> for Boolean {
+ type Error = InvalidBooleanError;
+
+ fn try_from(slice: &[u8]) -> std::result::Result<Self, Self::Error> {
+ if slice.len() != 1 || slice[0] > 1 {
+ Err(InvalidBooleanError)
+ } else {
+ Ok(Boolean { value: slice[0] })
+ }
+ }
+ }
+
+ impl From<Boolean> for [u8; 1] {
+ fn from(b: Boolean) -> [u8; 1] {
+ [b.value]
+ }
+ }
include!(concat!(env!("OUT_DIR"), "/rust_test_packets.rs"));
}
+
+#[cfg(test)]
+pub mod test {
+ use crate::test_packets::*;
+
+ #[test]
+ fn test_invalid_enum_field_value() {
+ // 0x0 is not a recognized Enum value.
+ let input = [0x0];
+ let res = TestEnumPacket::parse(&input);
+ assert!(res.is_err());
+ }
+
+ #[test]
+ fn test_invalid_custom_field_value() {
+ // 0x2 is not a recognized Boolean value.
+ let input = [0x2];
+ let res = TestCustomFieldPacket::parse(&input);
+ assert!(res.is_err());
+ }
+
+ #[test]
+ fn test_invalid_array_size() {
+ // Size 4, have 2.
+ let input = [0x4, 0x0, 0x0];
+ let res = TestArraySizePacket::parse(&input);
+ assert!(res.is_err());
+ }
+
+ #[test]
+ fn test_invalid_array_count() {
+ // Count 2, have 1.
+ let input = [0x2, 0x0, 0x0];
+ let res = TestArrayCountPacket::parse(&input);
+ assert!(res.is_err());
+ }
+
+ #[test]
+ fn test_invalid_payload_size() {
+ // Size 2, have 1.
+ let input = [0x2, 0x0];
+ let res = TestPayloadSizePacket::parse(&input);
+ assert!(res.is_err());
+ }
+
+ #[test]
+ fn test_invalid_body_size() {
+ // Size 2, have 1.
+ // Body does not have a concrete representation,
+ // the size and payload are both discarded.
+ let input = [0x2, 0x0];
+ let res = TestBodySizePacket::parse(&input);
+ assert!(res.is_ok());
+ }
+}
diff --git a/system/gd/rust/topshim/src/profiles/a2dp.rs b/system/gd/rust/topshim/src/profiles/a2dp.rs
index d2c31a5589..96764454bd 100644
--- a/system/gd/rust/topshim/src/profiles/a2dp.rs
+++ b/system/gd/rust/topshim/src/profiles/a2dp.rs
@@ -133,7 +133,7 @@ pub mod ffi {
address: [u8; 6],
}
- #[derive(Debug)]
+ #[derive(Debug, Copy, Clone)]
pub struct A2dpCodecConfig {
codec_type: i32,
codec_priority: i32,
diff --git a/system/include/hardware/bt_le_audio.h b/system/include/hardware/bt_le_audio.h
index 3b61399f9d..8276986d48 100644
--- a/system/include/hardware/bt_le_audio.h
+++ b/system/include/hardware/bt_le_audio.h
@@ -145,8 +145,6 @@ class LeAudioClientInterface {
btle_audio_codec_config_t output_codec_config) = 0;
};
-static constexpr uint8_t INSTANCE_ID_UNDEFINED = 0xFF;
-
/* Represents the broadcast source state. */
enum class BroadcastState {
STOPPED = 0,
@@ -162,25 +160,21 @@ enum class BroadcastAudioProfile {
MEDIA,
};
-constexpr uint8_t kBroadcastAnnouncementBroadcastIdSize = 3;
-using BroadcastId = std::array<uint8_t, kBroadcastAnnouncementBroadcastIdSize>;
-constexpr BroadcastId kBroadcastBroadcastIdInvalid = {0, 0, 0};
+using BroadcastId = uint32_t;
+static constexpr BroadcastId kBroadcastIdInvalid = 0x00000000;
using BroadcastCode = std::array<uint8_t, 16>;
class LeAudioBroadcasterCallbacks {
public:
virtual ~LeAudioBroadcasterCallbacks() = default;
/* Callback for the newly created broadcast event. */
- virtual void OnBroadcastCreated(uint8_t instance_id, bool success) = 0;
+ virtual void OnBroadcastCreated(uint32_t broadcast_id, bool success) = 0;
/* Callback for the destroyed broadcast event. */
- virtual void OnBroadcastDestroyed(uint8_t instance_id) = 0;
+ virtual void OnBroadcastDestroyed(uint32_t broadcast_id) = 0;
/* Callback for the broadcast source state event. */
- virtual void OnBroadcastStateChanged(uint8_t instance_id,
+ virtual void OnBroadcastStateChanged(uint32_t broadcast_id,
BroadcastState state) = 0;
- /* Callback for the broadcaster identifier. */
- virtual void OnBroadcastId(uint8_t instance_id,
- const BroadcastId& broadcast_id) = 0;
};
class LeAudioBroadcasterInterface {
@@ -197,19 +191,17 @@ class LeAudioBroadcasterInterface {
BroadcastAudioProfile profile,
std::optional<BroadcastCode> broadcast_code) = 0;
/* Update the ongoing Broadcast metadata */
- virtual void UpdateMetadata(uint8_t instance_id,
+ virtual void UpdateMetadata(uint32_t broadcast_id,
std::vector<uint8_t> metadata) = 0;
/* Start the existing Broadcast stream */
- virtual void StartBroadcast(uint8_t instance_id) = 0;
+ virtual void StartBroadcast(uint32_t broadcast_id) = 0;
/* Pause the ongoing Broadcast stream */
- virtual void PauseBroadcast(uint8_t instance_id) = 0;
+ virtual void PauseBroadcast(uint32_t broadcast_id) = 0;
/* Stop the Broadcast (no stream, no periodic advertisements */
- virtual void StopBroadcast(uint8_t instance_id) = 0;
+ virtual void StopBroadcast(uint32_t broadcast_id) = 0;
/* Destroy the existing Broadcast instance */
- virtual void DestroyBroadcast(uint8_t instance_id) = 0;
- /* Get Broadcasts identifier */
- virtual void GetBroadcastId(uint8_t instance_id) = 0;
+ virtual void DestroyBroadcast(uint32_t broadcast_id) = 0;
/* Get all broadcast states */
virtual void GetAllBroadcastStates(void) = 0;
diff --git a/system/main/shim/acl.cc b/system/main/shim/acl.cc
index b635424ac8..613bf70122 100644
--- a/system/main/shim/acl.cc
+++ b/system/main/shim/acl.cc
@@ -1505,7 +1505,7 @@ void shim::legacy::Acl::OnLeConnectSuccess(
RawAddress local_rpa = RawAddress::kEmpty; /* TODO enhanced */
RawAddress peer_rpa = RawAddress::kEmpty; /* TODO enhanced */
- uint8_t peer_addr_type = 0; /* TODO public */
+ tBLE_ADDR_TYPE peer_addr_type = BLE_ADDR_PUBLIC; /* TODO public */
// Once an le connection has successfully been established
// the device address is removed from the controller accept list.
diff --git a/system/main/shim/acl_api.cc b/system/main/shim/acl_api.cc
index 878d47002b..09b1823f2c 100644
--- a/system/main/shim/acl_api.cc
+++ b/system/main/shim/acl_api.cc
@@ -102,11 +102,11 @@ void bluetooth::shim::ACL_IgnoreAllLeConnections() {
void bluetooth::shim::ACL_ReadConnectionAddress(const RawAddress& pseudo_addr,
RawAddress& conn_addr,
- uint8_t* p_addr_type) {
+ tBLE_ADDR_TYPE* p_addr_type) {
auto local_address =
Stack::GetInstance()->GetAcl()->GetConnectionLocalAddress(pseudo_addr);
conn_addr = ToRawAddress(local_address.GetAddress());
- *p_addr_type = static_cast<uint8_t>(local_address.GetAddressType());
+ *p_addr_type = static_cast<tBLE_ADDR_TYPE>(local_address.GetAddressType());
}
void bluetooth::shim::ACL_AddToAddressResolution(
diff --git a/system/main/shim/acl_api.h b/system/main/shim/acl_api.h
index 42f7808ca1..b7688b9b4a 100644
--- a/system/main/shim/acl_api.h
+++ b/system/main/shim/acl_api.h
@@ -39,7 +39,8 @@ void ACL_Shutdown();
void ACL_IgnoreAllLeConnections();
void ACL_ReadConnectionAddress(const RawAddress& pseudo_addr,
- RawAddress& conn_addr, uint8_t* p_addr_type);
+ RawAddress& conn_addr,
+ tBLE_ADDR_TYPE* p_addr_type);
void ACL_AddToAddressResolution(const tBLE_BD_ADDR& legacy_address_with_type,
const Octet16& peer_irk,
diff --git a/system/main/shim/acl_legacy_interface.h b/system/main/shim/acl_legacy_interface.h
index 226b00e8f7..040f013341 100644
--- a/system/main/shim/acl_legacy_interface.h
+++ b/system/main/shim/acl_legacy_interface.h
@@ -45,7 +45,7 @@ typedef struct {
tHCI_ROLE role, uint16_t conn_interval,
uint16_t conn_latency, uint16_t conn_timeout,
const RawAddress& local_rpa, const RawAddress& peer_rpa,
- uint8_t peer_addr_type);
+ tBLE_ADDR_TYPE peer_addr_type);
void (*on_failed)(const tBLE_BD_ADDR& address_with_type, uint16_t handle,
bool enhanced, tHCI_STATUS status);
void (*on_disconnected)(tHCI_STATUS status, uint16_t handle,
diff --git a/system/main/shim/btm.cc b/system/main/shim/btm.cc
index 29827208d3..422c1a2dff 100644
--- a/system/main/shim/btm.cc
+++ b/system/main/shim/btm.cc
@@ -18,6 +18,8 @@
#include "main/shim/btm.h"
+#include <base/logging.h>
+
#include <algorithm>
#include <chrono>
#include <cstddef>
@@ -40,12 +42,11 @@
#include "main/shim/shim.h"
#include "stack/btm/btm_dev.h"
#include "stack/btm/btm_int_types.h"
+#include "types/ble_address_with_type.h"
#include "types/bluetooth/uuid.h"
#include "types/bt_transport.h"
#include "types/raw_address.h"
-#include <base/logging.h>
-
extern tBTM_CB btm_cb;
static constexpr size_t kRemoteDeviceNameLength = 248;
@@ -60,10 +61,11 @@ extern void btm_process_inq_complete(tHCI_STATUS status, uint8_t result_type);
extern void btm_ble_process_adv_addr(RawAddress& raw_address,
tBLE_ADDR_TYPE* address_type);
extern void btm_ble_process_adv_pkt_cont(
- uint16_t event_type, uint8_t address_type, const RawAddress& raw_address,
- uint8_t primary_phy, uint8_t secondary_phy, uint8_t advertising_sid,
- int8_t tx_power, int8_t rssi, uint16_t periodic_adv_int, uint8_t data_len,
- const uint8_t* data, const RawAddress& original_bda);
+ uint16_t event_type, tBLE_ADDR_TYPE address_type,
+ const RawAddress& raw_address, uint8_t primary_phy, uint8_t secondary_phy,
+ uint8_t advertising_sid, int8_t tx_power, int8_t rssi,
+ uint16_t periodic_adv_int, uint8_t data_len, const uint8_t* data,
+ const RawAddress& original_bda);
extern void btm_api_process_inquiry_result(const RawAddress& raw_address,
uint8_t page_scan_rep_mode,
@@ -676,7 +678,7 @@ hci::AddressWithType Btm::GetAddressAndType(const RawAddress& bd_addr) {
p_dev_rec->ble.identity_address_with_type.type);
} else {
return ToAddressWithType(p_dev_rec->ble.pseudo_addr,
- p_dev_rec->ble.ble_addr_type);
+ p_dev_rec->ble.AddressType());
}
}
LOG(ERROR) << "Unknown bd_addr. Use public address";
diff --git a/system/main/shim/btm_api.cc b/system/main/shim/btm_api.cc
index 646a67cab0..6e799313f3 100644
--- a/system/main/shim/btm_api.cc
+++ b/system/main/shim/btm_api.cc
@@ -40,6 +40,7 @@
#include "stack/btm/btm_int_types.h"
#include "stack/include/bt_hdr.h"
#include "stack/include/bt_octets.h"
+#include "types/ble_address_with_type.h"
#include "types/bluetooth/uuid.h"
#include "types/raw_address.h"
@@ -897,12 +898,6 @@ void bluetooth::shim::BTM_AddEirService(uint32_t* p_eir_uuid, uint16_t uuid16) {
CHECK(p_eir_uuid != nullptr);
}
-void bluetooth::shim::BTM_RemoveEirService(uint32_t* p_eir_uuid,
- uint16_t uuid16) {
- LOG_INFO("UNIMPLEMENTED %s", __func__);
- CHECK(p_eir_uuid != nullptr);
-}
-
void bluetooth::shim::BTM_SecAddBleDevice(const RawAddress& bd_addr,
tBT_DEVICE_TYPE dev_type,
tBLE_ADDR_TYPE addr_type) {
@@ -1236,8 +1231,8 @@ void bluetooth::shim::BTM_ConfirmReqReply(tBTM_STATUS res,
const RawAddress& bd_addr) {
// Send for both Classic and LE until we can determine the type
bool accept = res == BTM_SUCCESS;
- hci::AddressWithType address = ToAddressWithType(bd_addr, 0);
- hci::AddressWithType address2 = ToAddressWithType(bd_addr, 1);
+ hci::AddressWithType address = ToAddressWithType(bd_addr, BLE_ADDR_PUBLIC);
+ hci::AddressWithType address2 = ToAddressWithType(bd_addr, BLE_ADDR_RANDOM);
auto security_manager =
bluetooth::shim::GetSecurityModule()->GetSecurityManager();
if (ShimUi::GetInstance()->waiting_for_pairing_prompt_) {
diff --git a/system/main/shim/btm_api.h b/system/main/shim/btm_api.h
index 3117c42351..91dc6b6f14 100644
--- a/system/main/shim/btm_api.h
+++ b/system/main/shim/btm_api.h
@@ -336,21 +336,6 @@ void BTM_AddEirService(uint32_t* p_eir_uuid, uint16_t uuid16);
/*******************************************************************************
*
- * Function BTM_RemoveEirService
- *
- * Description This function is called to remove a service from the bit map
- * UUID list.
- *
- * Parameters p_eir_uuid - bit mask of UUID list for EIR
- * uuid16 - UUID 16-bit
- *
- * Returns None
- *
- ******************************************************************************/
-void BTM_RemoveEirService(uint32_t* p_eir_uuid, uint16_t uuid16);
-
-/*******************************************************************************
- *
* Function BTM_SecAddBleDevice
*
* Description Add/modify device. This function will be normally called
diff --git a/system/main/shim/l2c_api.cc b/system/main/shim/l2c_api.cc
index 42115cd0b6..ecbe502b83 100644
--- a/system/main/shim/l2c_api.cc
+++ b/system/main/shim/l2c_api.cc
@@ -18,6 +18,8 @@
#include "main/shim/l2c_api.h"
+#include <base/logging.h>
+
#include <future>
#include <unordered_map>
#include <unordered_set>
@@ -42,10 +44,9 @@
#include "stack/include/btu.h"
#include "stack/include/gatt_api.h"
#include "stack/include/sco_hci_link_interface.h"
+#include "types/ble_address_with_type.h"
#include "types/raw_address.h"
-#include <base/logging.h>
-
extern void gatt_notify_conn_update(const RawAddress& remote, uint16_t interval,
uint16_t latency, uint16_t timeout,
tHCI_STATUS status);
@@ -1200,7 +1201,8 @@ bool L2CA_IsLeLink(uint16_t acl_handle) {
}
void L2CA_ReadConnectionAddr(const RawAddress& pseudo_addr,
- RawAddress& conn_addr, uint8_t* p_addr_type) {
+ RawAddress& conn_addr,
+ tBLE_ADDR_TYPE* p_addr_type) {
auto* helper = &le_fixed_channel_helper_.find(kSmpCid)->second;
auto channel = helper->channels_.find(ToGdAddress(pseudo_addr));
if (channel == helper->channels_.end() || channel->second == nullptr) {
@@ -1209,12 +1211,12 @@ void L2CA_ReadConnectionAddr(const RawAddress& pseudo_addr,
}
auto local = channel->second->GetLinkOptions()->GetLocalAddress();
conn_addr = ToRawAddress(local.GetAddress());
- *p_addr_type = static_cast<uint8_t>(local.GetAddressType());
+ *p_addr_type = static_cast<tBLE_ADDR_TYPE>(local.GetAddressType());
}
bool L2CA_ReadRemoteConnectionAddr(const RawAddress& pseudo_addr,
RawAddress& conn_addr,
- uint8_t* p_addr_type) {
+ tBLE_ADDR_TYPE* p_addr_type) {
auto remote = ToGdAddress(pseudo_addr);
if (le_link_property_listener_shim_.info_.count(remote) == 0) {
LOG(ERROR) << __func__ << ": Unknown address";
diff --git a/system/main/shim/l2c_api.h b/system/main/shim/l2c_api.h
index a100cea862..0fe3fbd1ed 100644
--- a/system/main/shim/l2c_api.h
+++ b/system/main/shim/l2c_api.h
@@ -22,6 +22,7 @@
#include "stack/include/bt_hdr.h"
#include "stack/include/l2c_api.h"
+#include "types/ble_address_with_type.h"
#include "types/hci_role.h"
#include "types/raw_address.h"
@@ -484,10 +485,12 @@ uint16_t L2CA_GetNumLinks();
bool L2CA_IsLeLink(uint16_t acl_handle);
void L2CA_ReadConnectionAddr(const RawAddress& pseudo_addr,
- RawAddress& conn_addr, uint8_t* p_addr_type);
+ RawAddress& conn_addr,
+ tBLE_ADDR_TYPE* p_addr_type);
bool L2CA_ReadRemoteConnectionAddr(const RawAddress& pseudo_addr,
- RawAddress& conn_addr, uint8_t* p_addr_type);
+ RawAddress& conn_addr,
+ tBLE_ADDR_TYPE* p_addr_type);
} // namespace shim
} // namespace bluetooth
diff --git a/system/main/shim/le_advertising_manager.cc b/system/main/shim/le_advertising_manager.cc
index e0bccabdf3..54508f6e48 100644
--- a/system/main/shim/le_advertising_manager.cc
+++ b/system/main/shim/le_advertising_manager.cc
@@ -59,9 +59,9 @@ class BleAdvertiserInterfaceImpl : public BleAdvertiserInterface,
bluetooth::shim::GetAdvertising()->RegisterAdvertisingCallback(this);
}
- // nobody use this function
void RegisterAdvertiser(IdStatusCallback cb) override {
LOG(INFO) << __func__ << " in shim layer";
+ bluetooth::shim::GetAdvertising()->RegisterAdvertiser(cb);
}
void Unregister(uint8_t advertiser_id) override {
@@ -73,6 +73,7 @@ class BleAdvertiserInterfaceImpl : public BleAdvertiserInterface,
void GetOwnAddress(uint8_t advertiser_id, GetAddressCallback cb) override {
LOG(INFO) << __func__ << " in shim layer";
+ address_callbacks_[advertiser_id] = cb;
bluetooth::shim::GetAdvertising()->GetOwnAddress(advertiser_id);
}
@@ -123,6 +124,41 @@ class BleAdvertiserInterfaceImpl : public BleAdvertiserInterface,
std::vector<uint8_t> scan_response_data, int timeout_s,
MultiAdvCb timeout_cb) override {
LOG(INFO) << __func__ << " in shim layer";
+
+ bluetooth::hci::ExtendedAdvertisingConfig config{};
+ parse_parameter(config, params);
+
+ size_t offset = 0;
+ while (offset < advertise_data.size()) {
+ GapData gap_data;
+ uint8_t len = advertise_data[offset];
+ auto begin = advertise_data.begin() + offset;
+ auto end = begin + len + 1; // 1 byte for len
+ auto data_copy = std::make_shared<std::vector<uint8_t>>(begin, end);
+ bluetooth::packet::PacketView<bluetooth::packet::kLittleEndian> packet(
+ data_copy);
+ GapData::Parse(&gap_data, packet.begin());
+ config.advertisement.push_back(gap_data);
+ offset += len + 1; // 1 byte for len
+ }
+
+ offset = 0;
+ while (offset < scan_response_data.size()) {
+ GapData gap_data;
+ uint8_t len = scan_response_data[offset];
+ auto begin = scan_response_data.begin() + offset;
+ auto end = begin + len + 1; // 1 byte for len
+ auto data_copy = std::make_shared<std::vector<uint8_t>>(begin, end);
+ bluetooth::packet::PacketView<bluetooth::packet::kLittleEndian> packet(
+ data_copy);
+ GapData::Parse(&gap_data, packet.begin());
+ config.scan_response.push_back(gap_data);
+ offset += len + 1; // 1 byte for len
+ }
+
+ bluetooth::shim::GetAdvertising()->StartAdvertising(
+ advertiser_id, config, timeout_s * 100, cb, timeout_cb, scan_callback,
+ set_terminated_callback, bluetooth::shim::GetGdShimHandler());
}
void StartAdvertisingSet(int reg_id, IdTxPowerStatusCallback register_cb,
@@ -331,6 +367,11 @@ class BleAdvertiserInterfaceImpl : public BleAdvertiserInterface,
void OnOwnAddressRead(uint8_t advertiser_id, uint8_t address_type,
bluetooth::hci::Address address) {
RawAddress raw_address = bluetooth::ToRawAddress(address);
+ if (address_callbacks_.find(advertiser_id) != address_callbacks_.end()) {
+ address_callbacks_[advertiser_id].Run(address_type, raw_address);
+ address_callbacks_.erase(advertiser_id);
+ return;
+ }
do_in_jni_thread(FROM_HERE,
base::Bind(&AdvertisingCallbacks::OnOwnAddressRead,
base::Unretained(advertising_callbacks_),
@@ -368,6 +409,7 @@ class BleAdvertiserInterfaceImpl : public BleAdvertiserInterface,
// TODO set own_address_type based on address policy
config.own_address_type = OwnAddressType::RANDOM_DEVICE_ADDRESS;
}
+ std::map<uint8_t, GetAddressCallback> address_callbacks_;
};
BleAdvertiserInterfaceImpl* bt_le_advertiser_instance = nullptr;
diff --git a/system/main/shim/le_scanning_manager.cc b/system/main/shim/le_scanning_manager.cc
index 7bd81e30bc..c4b957129b 100644
--- a/system/main/shim/le_scanning_manager.cc
+++ b/system/main/shim/le_scanning_manager.cc
@@ -42,6 +42,7 @@
#include "storage/device.h"
#include "storage/le_device.h"
#include "storage/storage_module.h"
+#include "types/ble_address_with_type.h"
#include "types/bluetooth/uuid.h"
#include "types/raw_address.h"
@@ -92,10 +93,10 @@ class DefaultScanningCallback : public ::ScanningCallbacks {
extern ::ScanningCallbacks* bluetooth::shim::default_scanning_callback;
extern void btm_ble_process_adv_pkt_cont_for_inquiry(
- uint16_t event_type, uint8_t address_type, const RawAddress& raw_address,
- uint8_t primary_phy, uint8_t secondary_phy, uint8_t advertising_sid,
- int8_t tx_power, int8_t rssi, uint16_t periodic_adv_int,
- std::vector<uint8_t> advertising_data);
+ uint16_t event_type, tBLE_ADDR_TYPE address_type,
+ const RawAddress& raw_address, uint8_t primary_phy, uint8_t secondary_phy,
+ uint8_t advertising_sid, int8_t tx_power, int8_t rssi,
+ uint16_t periodic_adv_int, std::vector<uint8_t> advertising_data);
extern void btif_dm_update_ble_remote_properties(const RawAddress& bd_addr,
BD_NAME bd_name,
@@ -492,6 +493,7 @@ bool BleScannerInterfaceImpl::parse_filter_command(
apcf_command.data.begin(), apcf_command.data.end());
advertising_packet_content_filter_command.data_mask.assign(
apcf_command.data_mask.begin(), apcf_command.data_mask.end());
+ advertising_packet_content_filter_command.irk = apcf_command.irk;
return true;
}
diff --git a/system/main/test/main_shim_test.cc b/system/main/test/main_shim_test.cc
index 602a559ac7..039254ecc8 100644
--- a/system/main/test/main_shim_test.cc
+++ b/system/main/test/main_shim_test.cc
@@ -118,7 +118,7 @@ void mock_connection_le_on_connected(
const tBLE_BD_ADDR& address_with_type, uint16_t handle, tHCI_ROLE role,
uint16_t conn_interval, uint16_t conn_latency, uint16_t conn_timeout,
const RawAddress& local_rpa, const RawAddress& peer_rpa,
- uint8_t peer_addr_type) {
+ tBLE_ADDR_TYPE peer_addr_type) {
mock_function_count_map[__func__]++;
}
void mock_connection_le_on_failed(const tBLE_BD_ADDR& address_with_type,
diff --git a/system/osi/src/config.cc b/system/osi/src/config.cc
index bdc695cd65..9ebe076e8e 100644
--- a/system/osi/src/config.cc
+++ b/system/osi/src/config.cc
@@ -495,8 +495,8 @@ static bool config_parse(FILE* fp, config_t* config) {
CHECK(config != nullptr);
int line_num = 0;
- char line[1024];
- char section[1024];
+ char line[4096];
+ char section[4096];
strcpy(section, CONFIG_DEFAULT_SECTION);
while (fgets(line, sizeof(line), fp)) {
@@ -513,7 +513,7 @@ static bool config_parse(FILE* fp, config_t* config) {
<< line_num;
return false;
}
- strncpy(section, line_ptr + 1, len - 2); // NOLINT (len < 1024)
+ strncpy(section, line_ptr + 1, len - 2); // NOLINT (len < 4096)
section[len - 2] = '\0';
} else {
char* split = strchr(line_ptr, '=');
diff --git a/system/stack/Android.bp b/system/stack/Android.bp
index 744a342ce1..8ab335ba74 100644
--- a/system/stack/Android.bp
+++ b/system/stack/Android.bp
@@ -293,6 +293,7 @@ cc_test {
srcs: [
":TestCommonMockFunctions",
":TestMockHci",
+ ":TestMockStackMetrics",
"rfcomm/port_api.cc",
"rfcomm/port_rfc.cc",
"rfcomm/port_utils.cc",
diff --git a/system/stack/a2dp/a2dp_vendor.cc b/system/stack/a2dp/a2dp_vendor.cc
index b1bd5f65e7..d6bc28ad59 100644
--- a/system/stack/a2dp/a2dp_vendor.cc
+++ b/system/stack/a2dp/a2dp_vendor.cc
@@ -22,6 +22,8 @@
#include "a2dp_vendor.h"
+#include <dlfcn.h>
+
#include "a2dp_vendor_aptx.h"
#include "a2dp_vendor_aptx_hd.h"
#include "a2dp_vendor_ldac.h"
@@ -664,3 +666,23 @@ std::string A2DP_VendorCodecInfoString(const uint8_t* p_codec_info) {
return "Unsupported codec vendor_id: " + loghex(vendor_id) +
" codec_id: " + loghex(codec_id);
}
+
+void* A2DP_VendorCodecLoadExternalLib(const std::vector<std::string>& lib_paths,
+ const std::string& friendly_name) {
+ std::string lib_path_error_list = "";
+ for (auto lib_path : lib_paths) {
+ void* lib_handle = dlopen(lib_path.c_str(), RTLD_NOW);
+ if (lib_handle != NULL) {
+ LOG(INFO) << __func__ << "Library found: " << friendly_name << " with ["
+ << lib_path << "]."
+ << " (Tested libs: " << lib_path_error_list << ")";
+ return lib_handle;
+ }
+ lib_path_error_list += "[ Err: ";
+ lib_path_error_list += dlerror();
+ lib_path_error_list += " ], ";
+ }
+ LOG(ERROR) << __func__ << "Failed to open library: " << friendly_name
+ << ". (Tested libs: " << lib_path_error_list << ")";
+ return nullptr;
+}
diff --git a/system/stack/a2dp/a2dp_vendor_aptx_encoder.cc b/system/stack/a2dp/a2dp_vendor_aptx_encoder.cc
index 32929c2f09..4305d6cd01 100644
--- a/system/stack/a2dp/a2dp_vendor_aptx_encoder.cc
+++ b/system/stack/a2dp/a2dp_vendor_aptx_encoder.cc
@@ -38,7 +38,8 @@
//
// The aptX encoder shared library, and the functions to use
//
-static const char* APTX_ENCODER_LIB_NAME = "libaptX_encoder.so";
+static const std::string APTX_ENCODER_LIB_NAME = "libaptX_encoder.so";
+
static void* aptx_encoder_lib_handle = NULL;
static const char* APTX_ENCODER_INIT_NAME = "aptxbtenc_init";
@@ -111,14 +112,22 @@ static size_t aptx_encode_16bit(tAPTX_FRAMING_PARAMS* framing_params,
size_t* data_out_index, uint16_t* data16_in,
uint8_t* data_out);
+static const std::vector<std::string> APTX_ENCODER_LIB_PATHS = {
+ APTX_ENCODER_LIB_NAME,
+#ifdef __LP64__
+ "/system_ext/lib64/" + APTX_ENCODER_LIB_NAME,
+#else
+ "/system_ext/lib/" + APTX_ENCODER_LIB_NAME,
+#endif
+};
+
bool A2DP_VendorLoadEncoderAptx(void) {
if (aptx_encoder_lib_handle != NULL) return true; // Already loaded
// Open the encoder library
- aptx_encoder_lib_handle = dlopen(APTX_ENCODER_LIB_NAME, RTLD_NOW);
- if (aptx_encoder_lib_handle == NULL) {
- LOG_ERROR("%s: cannot open aptX encoder library %s: %s", __func__,
- APTX_ENCODER_LIB_NAME, dlerror());
+ aptx_encoder_lib_handle =
+ A2DP_VendorCodecLoadExternalLib(APTX_ENCODER_LIB_PATHS, "aptX encoder");
+ if (!aptx_encoder_lib_handle) {
return false;
}
diff --git a/system/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc b/system/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc
index 3396b12345..562ae74ab2 100644
--- a/system/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc
+++ b/system/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc
@@ -38,7 +38,7 @@
//
// The aptX-HD encoder shared library, and the functions to use
//
-static const char* APTX_HD_ENCODER_LIB_NAME = "libaptXHD_encoder.so";
+static const std::string APTX_HD_ENCODER_LIB_NAME = "libaptXHD_encoder.so";
static void* aptx_hd_encoder_lib_handle = NULL;
static const char* APTX_HD_ENCODER_INIT_NAME = "aptxhdbtenc_init";
@@ -112,14 +112,22 @@ static size_t aptx_hd_encode_24bit(tAPTX_HD_FRAMING_PARAMS* framing_params,
size_t* data_out_index, uint32_t* data32_in,
uint8_t* data_out);
+static const std::vector<std::string> APTX_HD_ENCODER_LIB_PATHS = {
+ APTX_HD_ENCODER_LIB_NAME,
+#ifdef __LP64__
+ "/system_ext/lib64/" + APTX_HD_ENCODER_LIB_NAME,
+#else
+ "/system_ext/lib/" + APTX_HD_ENCODER_LIB_NAME,
+#endif
+};
+
bool A2DP_VendorLoadEncoderAptxHd(void) {
if (aptx_hd_encoder_lib_handle != NULL) return true; // Already loaded
// Open the encoder library
- aptx_hd_encoder_lib_handle = dlopen(APTX_HD_ENCODER_LIB_NAME, RTLD_NOW);
- if (aptx_hd_encoder_lib_handle == NULL) {
- LOG_ERROR("%s: cannot open aptX-HD encoder library %s: %s", __func__,
- APTX_HD_ENCODER_LIB_NAME, dlerror());
+ aptx_hd_encoder_lib_handle = A2DP_VendorCodecLoadExternalLib(
+ APTX_HD_ENCODER_LIB_PATHS, "aptX-HD encoder");
+ if (!aptx_hd_encoder_lib_handle) {
return false;
}
diff --git a/system/stack/a2dp/a2dp_vendor_ldac_abr.cc b/system/stack/a2dp/a2dp_vendor_ldac_abr.cc
index 635c6eea0e..3f91f3d68c 100644
--- a/system/stack/a2dp/a2dp_vendor_ldac_abr.cc
+++ b/system/stack/a2dp/a2dp_vendor_ldac_abr.cc
@@ -23,6 +23,7 @@
#include <stdio.h>
#include <string.h>
+#include "a2dp_vendor.h"
#include "osi/include/log.h"
//
@@ -32,7 +33,7 @@
//
// The LDAC ABR shared library, and the functions to use
//
-static const char* LDAC_ABR_LIB_NAME = "libldacBT_abr.so";
+static const std::string LDAC_ABR_LIB_NAME = "libldacBT_abr.so";
static void* ldac_abr_lib_handle = NULL;
static const char* LDAC_ABR_GET_HANDLE_NAME = "ldac_ABR_get_handle";
@@ -62,15 +63,22 @@ static tLDAC_ABR_INIT ldac_abr_init_func;
static tLDAC_ABR_SET_THRESHOLDS ldac_abr_set_thresholds_func;
static tLDAC_ABR_PROC ldac_abr_proc_func;
+static const std::vector<std::string> LDAC_ABR_LIB_PATHS = {
+ LDAC_ABR_LIB_NAME,
+#ifdef __LP64__
+ "/system/lib64/" + LDAC_ABR_LIB_NAME,
+#else
+ "/system/lib/" + LDAC_ABR_LIB_NAME,
+#endif
+};
+
bool A2DP_VendorLoadLdacAbr(void) {
if (ldac_abr_lib_handle != NULL) return true; // Already loaded
// Open the LDAC ABR library
- ldac_abr_lib_handle = dlopen(LDAC_ABR_LIB_NAME, RTLD_NOW);
- if (ldac_abr_lib_handle == NULL) {
- LOG_ERROR("%s: cannot open LDAC ABR library %s: %s", __func__,
- LDAC_ABR_LIB_NAME, dlerror());
- A2DP_VendorUnloadLdacAbr();
+ ldac_abr_lib_handle =
+ A2DP_VendorCodecLoadExternalLib(LDAC_ABR_LIB_PATHS, "LDAC ABR");
+ if (!ldac_abr_lib_handle) {
return false;
}
diff --git a/system/stack/a2dp/a2dp_vendor_ldac_encoder.cc b/system/stack/a2dp/a2dp_vendor_ldac_encoder.cc
index 2f87c52522..942b010609 100644
--- a/system/stack/a2dp/a2dp_vendor_ldac_encoder.cc
+++ b/system/stack/a2dp/a2dp_vendor_ldac_encoder.cc
@@ -44,7 +44,7 @@
//
// The LDAC encoder shared library, and the functions to use
//
-static const char* LDAC_ENCODER_LIB_NAME = "libldacBT_enc.so";
+static const std::string LDAC_ENCODER_LIB_NAME = "libldacBT_enc.so";
static void* ldac_encoder_lib_handle = NULL;
static const char* LDAC_GET_HANDLE_NAME = "ldacBT_get_handle";
@@ -194,6 +194,15 @@ static void* load_func(const char* func_name) {
return func_ptr;
}
+static const std::vector<std::string> LDAC_ENCODER_LIB_PATHS = {
+ LDAC_ENCODER_LIB_NAME,
+#ifdef __LP64__
+ "/system/lib64/" + LDAC_ENCODER_LIB_NAME,
+#else
+ "/system/lib/" + LDAC_ENCODER_LIB_NAME,
+#endif
+};
+
bool A2DP_VendorLoadEncoderLdac(void) {
if (ldac_encoder_lib_handle != NULL) return true; // Already loaded
@@ -201,10 +210,9 @@ bool A2DP_VendorLoadEncoderLdac(void) {
memset(&a2dp_ldac_encoder_cb, 0, sizeof(a2dp_ldac_encoder_cb));
// Open the encoder library
- ldac_encoder_lib_handle = dlopen(LDAC_ENCODER_LIB_NAME, RTLD_NOW);
- if (ldac_encoder_lib_handle == NULL) {
- LOG_ERROR("%s: cannot open LDAC encoder library %s: %s", __func__,
- LDAC_ENCODER_LIB_NAME, dlerror());
+ ldac_encoder_lib_handle =
+ A2DP_VendorCodecLoadExternalLib(LDAC_ENCODER_LIB_PATHS, "LDAC encoder");
+ if (!ldac_encoder_lib_handle) {
return false;
}
diff --git a/system/stack/acl/btm_ble_connection_establishment.cc b/system/stack/acl/btm_ble_connection_establishment.cc
index fefd71a14c..f68dd73306 100644
--- a/system/stack/acl/btm_ble_connection_establishment.cc
+++ b/system/stack/acl/btm_ble_connection_establishment.cc
@@ -88,7 +88,7 @@ bool maybe_resolve_address(RawAddress* bda, tBLE_ADDR_TYPE* bda_type) {
if (!btm_ble_init_pseudo_addr(match_rec, *bda)) {
/* assign the original address to be the current report address */
*bda = match_rec->ble.pseudo_addr;
- *bda_type = match_rec->ble.ble_addr_type;
+ *bda_type = match_rec->ble.AddressType();
} else {
*bda = match_rec->bd_addr;
}
diff --git a/system/stack/btm/btm_ble.cc b/system/stack/btm/btm_ble.cc
index b0976d0256..5e1ab22e7b 100644
--- a/system/stack/btm/btm_ble.cc
+++ b/system/stack/btm/btm_ble.cc
@@ -89,12 +89,12 @@ void BTM_SecAddBleDevice(const RawAddress& bd_addr, tBT_DEVICE_TYPE dev_type,
memset(p_dev_rec->sec_bd_name, 0, sizeof(tBTM_BD_NAME));
p_dev_rec->device_type |= dev_type;
- p_dev_rec->ble.ble_addr_type = addr_type;
+ p_dev_rec->ble.SetAddressType(addr_type);
/* sync up with the Inq Data base*/
tBTM_INQ_INFO* p_info = BTM_InqDbRead(bd_addr);
if (p_info) {
- p_info->results.ble_addr_type = p_dev_rec->ble.ble_addr_type;
+ p_info->results.ble_addr_type = p_dev_rec->ble.AddressType();
p_info->results.device_type = p_dev_rec->device_type;
BTM_TRACE_DEBUG("InqDb device_type =0x%x addr_type=0x%x",
p_info->results.device_type, p_info->results.ble_addr_type);
@@ -364,7 +364,7 @@ void BTM_BleSecureConnectionOobDataReply(const RawAddress& bd_addr,
oob.peer_oob_data.present = true;
memcpy(&oob.peer_oob_data.randomizer, p_r, OCTET16_LEN);
memcpy(&oob.peer_oob_data.commitment, p_c, OCTET16_LEN);
- oob.peer_oob_data.addr_rcvd_from.type = p_dev_rec->ble.ble_addr_type;
+ oob.peer_oob_data.addr_rcvd_from.type = p_dev_rec->ble.AddressType();
oob.peer_oob_data.addr_rcvd_from.bda = bd_addr;
SMP_SecureConnectionOobDataReply((uint8_t*)&oob);
@@ -481,16 +481,16 @@ void BTM_ReadDevInfo(const RawAddress& remote_bda, tBT_DEVICE_TYPE* p_dev_type,
/* new inquiry result, overwrite device type in security device record */
if (p_inq_info) {
p_dev_rec->device_type = p_inq_info->results.device_type;
- p_dev_rec->ble.ble_addr_type = p_inq_info->results.ble_addr_type;
+ p_dev_rec->ble.SetAddressType(p_inq_info->results.ble_addr_type);
}
if (p_dev_rec->bd_addr == remote_bda &&
p_dev_rec->ble.pseudo_addr == remote_bda) {
*p_dev_type = p_dev_rec->device_type;
- *p_addr_type = p_dev_rec->ble.ble_addr_type;
+ *p_addr_type = p_dev_rec->ble.AddressType();
} else if (p_dev_rec->ble.pseudo_addr == remote_bda) {
*p_dev_type = BT_DEVICE_TYPE_BLE;
- *p_addr_type = p_dev_rec->ble.ble_addr_type;
+ *p_addr_type = p_dev_rec->ble.AddressType();
} else /* matching static adddress only */ {
if (p_dev_rec->device_type != BT_DEVICE_TYPE_UNKNOWN) {
*p_dev_type = p_dev_rec->device_type;
@@ -1713,7 +1713,7 @@ void btm_ble_connected(const RawAddress& bda, uint16_t handle, uint8_t enc_mode,
p_dev_rec->timestamp = btm_cb.dev_rec_count++;
}
- p_dev_rec->ble.ble_addr_type = addr_type;
+ p_dev_rec->ble.SetAddressType(addr_type);
p_dev_rec->ble.pseudo_addr = bda;
p_dev_rec->ble_hci_handle = handle;
p_dev_rec->device_type |= BT_DEVICE_TYPE_BLE;
@@ -1721,7 +1721,7 @@ void btm_ble_connected(const RawAddress& bda, uint16_t handle, uint8_t enc_mode,
if (!addr_matched) {
p_dev_rec->ble.active_addr_type = tBTM_SEC_BLE::BTM_BLE_ADDR_PSEUDO;
- if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_RANDOM) {
+ if (p_dev_rec->ble.AddressType() == BLE_ADDR_RANDOM) {
p_dev_rec->ble.cur_rand_addr = bda;
}
}
@@ -2097,7 +2097,7 @@ bool btm_ble_get_acl_remote_addr(uint16_t hci_handle, RawAddress& conn_addr,
switch (p_dev_rec->ble.active_addr_type) {
case tBTM_SEC_BLE::BTM_BLE_ADDR_PSEUDO:
conn_addr = p_dev_rec->bd_addr;
- *p_addr_type = p_dev_rec->ble.ble_addr_type;
+ *p_addr_type = p_dev_rec->ble.AddressType();
break;
case tBTM_SEC_BLE::BTM_BLE_ADDR_RRA:
diff --git a/system/stack/btm/btm_ble_addr.cc b/system/stack/btm/btm_ble_addr.cc
index c2b472acf7..93a4011558 100644
--- a/system/stack/btm/btm_ble_addr.cc
+++ b/system/stack/btm/btm_ble_addr.cc
@@ -34,6 +34,7 @@
#include "stack/crypto_toolbox/crypto_toolbox.h"
#include "stack/include/acl_api.h"
#include "stack/include/bt_octets.h"
+#include "types/ble_address_with_type.h"
#include "types/raw_address.h"
extern tBTM_CB btm_cb;
@@ -226,7 +227,8 @@ static tBTM_SEC_DEV_REC* btm_find_dev_by_identity_addr(
*
******************************************************************************/
bool btm_identity_addr_to_random_pseudo(RawAddress* bd_addr,
- uint8_t* p_addr_type, bool refresh) {
+ tBLE_ADDR_TYPE* p_addr_type,
+ bool refresh) {
tBTM_SEC_DEV_REC* p_dev_rec =
btm_find_dev_by_identity_addr(*bd_addr, *p_addr_type);
if (p_dev_rec == nullptr) {
@@ -245,7 +247,7 @@ bool btm_identity_addr_to_random_pseudo(RawAddress* bd_addr,
*bd_addr = p_dev_rec->ble.pseudo_addr;
}
- *p_addr_type = p_dev_rec->ble.ble_addr_type;
+ *p_addr_type = p_dev_rec->ble.AddressType();
return true;
}
@@ -264,7 +266,7 @@ bool btm_identity_addr_to_random_pseudo_from_address_with_type(
*
******************************************************************************/
bool btm_random_pseudo_to_identity_addr(RawAddress* random_pseudo,
- uint8_t* p_identity_addr_type) {
+ tBLE_ADDR_TYPE* p_identity_addr_type) {
tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(*random_pseudo);
if (p_dev_rec != NULL) {
diff --git a/system/stack/btm/btm_ble_bgconn.cc b/system/stack/btm/btm_ble_bgconn.cc
index f725351191..249f9ed7f4 100644
--- a/system/stack/btm/btm_ble_bgconn.cc
+++ b/system/stack/btm/btm_ble_bgconn.cc
@@ -97,7 +97,7 @@ const tBLE_BD_ADDR convert_to_address_with_type(
if (p_dev_rec->ble.identity_address_with_type.bda.IsEmpty()) {
return {
- .type = p_dev_rec->ble.ble_addr_type,
+ .type = p_dev_rec->ble.AddressType(),
.bda = bd_addr,
};
} else {
@@ -203,7 +203,7 @@ bool BTM_BackgroundConnectAddressKnown(const RawAddress& address) {
}
// Public address, Random Static, or Random Non-Resolvable Address known
- if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_PUBLIC ||
+ if (p_dev_rec->ble.AddressType() == BLE_ADDR_PUBLIC ||
!BTM_BLE_IS_RESOLVE_BDA(address)) {
return true;
}
diff --git a/system/stack/btm/btm_ble_gap.cc b/system/stack/btm/btm_ble_gap.cc
index a5683c3fee..e72177bce3 100644
--- a/system/stack/btm/btm_ble_gap.cc
+++ b/system/stack/btm/btm_ble_gap.cc
@@ -55,6 +55,7 @@
#include "stack/include/gap_api.h"
#include "stack/include/hci_error_code.h"
#include "stack/include/inq_hci_link_interface.h"
+#include "types/ble_address_with_type.h"
#include "types/raw_address.h"
extern tBTM_CB btm_cb;
@@ -63,7 +64,7 @@ extern void btm_inq_remote_name_timer_timeout(void* data);
extern bool btm_ble_init_pseudo_addr(tBTM_SEC_DEV_REC* p_dev_rec,
const RawAddress& new_pseudo_addr);
extern bool btm_identity_addr_to_random_pseudo(RawAddress* bd_addr,
- uint8_t* p_addr_type,
+ tBLE_ADDR_TYPE* p_addr_type,
bool refresh);
extern void btm_ble_batchscan_init(void);
extern void btm_ble_adv_filter_init(void);
@@ -243,7 +244,7 @@ static void btm_ble_start_sync_timeout(void* data);
* Local functions
******************************************************************************/
static void btm_ble_update_adv_flag(uint8_t flag);
-void btm_ble_process_adv_pkt_cont(uint16_t evt_type, uint8_t addr_type,
+void btm_ble_process_adv_pkt_cont(uint16_t evt_type, tBLE_ADDR_TYPE addr_type,
const RawAddress& bda, uint8_t primary_phy,
uint8_t secondary_phy,
uint8_t advertising_sid, int8_t tx_power,
@@ -909,7 +910,7 @@ static void sync_queue_cleanup(remove_sync_node_t* p_param) {
void btm_ble_start_sync_request(uint8_t sid, RawAddress addr, uint16_t skip,
uint16_t timeout) {
- uint8_t address_type = BLE_ADDR_RANDOM;
+ tBLE_ADDR_TYPE address_type = BLE_ADDR_RANDOM;
tINQ_DB_ENT* p_i = btm_inq_db_find(addr);
if (p_i) {
address_type = p_i->inq_info.results.ble_addr_type; // Random
@@ -1939,7 +1940,8 @@ static void btm_send_hci_scan_enable(uint8_t enable,
}
void btm_send_hci_set_scan_params(uint8_t scan_type, uint16_t scan_int,
- uint16_t scan_win, uint8_t addr_type_own,
+ uint16_t scan_win,
+ tBLE_ADDR_TYPE addr_type_own,
uint8_t scan_filter_policy) {
if (controller_get_interface()->supports_ble_extended_advertising()) {
scanning_phy_cfg phy_cfg;
@@ -2476,7 +2478,7 @@ void btm_clear_all_pending_le_entry(void) {
}
}
-void btm_ble_process_adv_addr(RawAddress& bda, uint8_t* addr_type) {
+void btm_ble_process_adv_addr(RawAddress& bda, tBLE_ADDR_TYPE* addr_type) {
/* map address to security record */
bool match = btm_identity_addr_to_random_pseudo(&bda, addr_type, false);
@@ -2493,7 +2495,7 @@ void btm_ble_process_adv_addr(RawAddress& bda, uint8_t* addr_type) {
} else {
// Assign the original address to be the current report address
bda = match_rec->ble.pseudo_addr;
- *addr_type = match_rec->ble.ble_addr_type;
+ *addr_type = match_rec->ble.AddressType();
}
}
}
@@ -2656,7 +2658,7 @@ void btm_ble_process_adv_pkt(uint8_t data_len, const uint8_t* data) {
* This function is called after random address resolution is done, and proceed
* to process adv packet.
*/
-void btm_ble_process_adv_pkt_cont(uint16_t evt_type, uint8_t addr_type,
+void btm_ble_process_adv_pkt_cont(uint16_t evt_type, tBLE_ADDR_TYPE addr_type,
const RawAddress& bda, uint8_t primary_phy,
uint8_t secondary_phy,
uint8_t advertising_sid, int8_t tx_power,
@@ -2804,7 +2806,7 @@ void btm_ble_process_adv_pkt_cont(uint16_t evt_type, uint8_t addr_type,
* from gd scanning module to handle inquiry result callback.
*/
void btm_ble_process_adv_pkt_cont_for_inquiry(
- uint16_t evt_type, uint8_t addr_type, const RawAddress& bda,
+ uint16_t evt_type, tBLE_ADDR_TYPE addr_type, const RawAddress& bda,
uint8_t primary_phy, uint8_t secondary_phy, uint8_t advertising_sid,
int8_t tx_power, int8_t rssi, uint16_t periodic_adv_int,
std::vector<uint8_t> advertising_data) {
diff --git a/system/stack/btm/btm_ble_int.h b/system/stack/btm/btm_ble_int.h
index dfb9f2277b..d92b9537aa 100644
--- a/system/stack/btm/btm_ble_int.h
+++ b/system/stack/btm/btm_ble_int.h
@@ -32,6 +32,7 @@
#include "btm_int_types.h"
#include "smp_api.h"
#include "stack/include/hci_error_code.h"
+#include "types/ble_address_with_type.h"
#include "types/raw_address.h"
extern void btm_ble_process_periodic_adv_sync_est_evt(uint8_t len,
@@ -111,8 +112,8 @@ extern uint64_t btm_get_next_private_addrress_interval_ms();
/* privacy function */
/* BLE address mapping with CS feature */
-extern bool btm_random_pseudo_to_identity_addr(RawAddress* random_pseudo,
- uint8_t* p_identity_addr_type);
+extern bool btm_random_pseudo_to_identity_addr(
+ RawAddress* random_pseudo, tBLE_ADDR_TYPE* p_identity_addr_type);
extern void btm_ble_refresh_peer_resolvable_private_addr(
const RawAddress& pseudo_bda, const RawAddress& rra,
tBTM_SEC_BLE::tADDRESS_TYPE type);
diff --git a/system/stack/btm/btm_ble_privacy.cc b/system/stack/btm/btm_ble_privacy.cc
index 76dbc4b10e..78e981c41b 100644
--- a/system/stack/btm/btm_ble_privacy.cc
+++ b/system/stack/btm/btm_ble_privacy.cc
@@ -585,7 +585,7 @@ bool btm_ble_resolving_list_load_dev(tBTM_SEC_DEV_REC* p_dev_rec) {
if (p_dev_rec->ble.identity_address_with_type.bda.IsEmpty()) {
p_dev_rec->ble.identity_address_with_type.bda = p_dev_rec->bd_addr;
p_dev_rec->ble.identity_address_with_type.type =
- p_dev_rec->ble.ble_addr_type;
+ p_dev_rec->ble.AddressType();
}
BTM_TRACE_DEBUG(
@@ -686,7 +686,7 @@ void btm_ble_resolving_list_load_dev(tBTM_SEC_DEV_REC& dev_rec) {
if (dev_rec.ble.identity_address_with_type.bda.IsEmpty()) {
dev_rec.ble.identity_address_with_type = {
.bda = dev_rec.bd_addr,
- .type = dev_rec.ble.ble_addr_type,
+ .type = dev_rec.ble.AddressType(),
};
}
diff --git a/system/stack/btm/btm_dev.cc b/system/stack/btm/btm_dev.cc
index 18f05a29c7..d887e93c2d 100644
--- a/system/stack/btm/btm_dev.cc
+++ b/system/stack/btm/btm_dev.cc
@@ -237,7 +237,7 @@ tBTM_SEC_DEV_REC* btm_sec_alloc_dev(const RawAddress& bd_addr) {
memcpy(p_dev_rec->dev_class, p_inq_info->results.dev_class, DEV_CLASS_LEN);
p_dev_rec->device_type = p_inq_info->results.device_type;
- p_dev_rec->ble.ble_addr_type = p_inq_info->results.ble_addr_type;
+ p_dev_rec->ble.SetAddressType(p_inq_info->results.ble_addr_type);
} else if (bd_addr == btm_cb.connecting_bda)
memcpy(p_dev_rec->dev_class, btm_cb.connecting_dc, DEV_CLASS_LEN);
@@ -405,7 +405,7 @@ void btm_consolidate_dev(tBTM_SEC_DEV_REC* p_target_rec) {
/* an RPA device entry is a duplicate of the target record */
if (btm_ble_addr_resolvable(p_dev_rec->bd_addr, p_target_rec)) {
if (p_target_rec->ble.pseudo_addr == p_dev_rec->bd_addr) {
- p_target_rec->ble.ble_addr_type = p_dev_rec->ble.ble_addr_type;
+ p_target_rec->ble.SetAddressType(p_dev_rec->ble.AddressType());
p_target_rec->device_type |= p_dev_rec->device_type;
/* remove the combined record */
diff --git a/system/stack/btm/security_device_record.h b/system/stack/btm/security_device_record.h
index 5b076ae2ed..360c7fb793 100644
--- a/system/stack/btm/security_device_record.h
+++ b/system/stack/btm/security_device_record.h
@@ -95,7 +95,14 @@ typedef struct {
typedef struct {
RawAddress pseudo_addr; /* LE pseudo address of the device if different from
device address */
- tBLE_ADDR_TYPE ble_addr_type; /* LE device type: public or random address */
+ private:
+ tBLE_ADDR_TYPE ble_addr_type_; /* LE device type: public or random address */
+
+ public:
+ tBLE_ADDR_TYPE AddressType() const { return ble_addr_type_; }
+ void SetAddressType(tBLE_ADDR_TYPE ble_addr_type) {
+ if (is_ble_addr_type_known(ble_addr_type)) ble_addr_type_ = ble_addr_type;
+ }
tBLE_BD_ADDR identity_address_with_type;
diff --git a/system/stack/gatt/gatt_main.cc b/system/stack/gatt/gatt_main.cc
index 2ce057db87..c4e1039a95 100644
--- a/system/stack/gatt/gatt_main.cc
+++ b/system/stack/gatt/gatt_main.cc
@@ -189,7 +189,7 @@ void gatt_find_in_device_record(const RawAddress& bd_addr,
if (p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) {
if (p_dev_rec->ble.identity_address_with_type.bda.IsEmpty()) {
- *address_with_type = {.type = p_dev_rec->ble.ble_addr_type,
+ *address_with_type = {.type = p_dev_rec->ble.AddressType(),
.bda = bd_addr};
return;
}
diff --git a/system/stack/include/a2dp_vendor.h b/system/stack/include/a2dp_vendor.h
index 39e1086ce9..6f4d16512b 100644
--- a/system/stack/include/a2dp_vendor.h
+++ b/system/stack/include/a2dp_vendor.h
@@ -25,6 +25,8 @@
#include <stddef.h>
#include <stdint.h>
+#include <vector>
+
#include "a2dp_codec_api.h"
#include "stack/include/bt_hdr.h"
@@ -211,4 +213,12 @@ bool A2DP_VendorInitCodecConfig(btav_a2dp_codec_index_t codec_index,
// Returns a string describing the codec information.
std::string A2DP_VendorCodecInfoString(const uint8_t* p_codec_info);
+// Try to dlopen external codec library
+// Will iterate over |lib_paths| to return the first successfully dlopen library
+// |friendly_name| is only use for logging purpose
+// Return pointer to the handle if the library is successfully dlopen,
+// nullptr otherwise
+void* A2DP_VendorCodecLoadExternalLib(const std::vector<std::string>& lib_paths,
+ const std::string& friendly_name);
+
#endif // A2DP_VENDOR_H
diff --git a/system/stack/include/ble_hci_link_interface.h b/system/stack/include/ble_hci_link_interface.h
index 19766fd2de..d4f6d35169 100644
--- a/system/stack/include/ble_hci_link_interface.h
+++ b/system/stack/include/ble_hci_link_interface.h
@@ -20,6 +20,7 @@
#include <cstdint>
#include "osi/include/osi.h" // UNUSED_ATTR
+#include "types/ble_address_with_type.h"
#include "types/raw_address.h"
// This header contains functions for HCI-ble to invoke
@@ -36,7 +37,7 @@ extern void btm_ble_test_command_complete(uint8_t* p);
extern void btm_ble_rand_enc_complete(uint8_t* p, uint16_t op_code,
tBTM_RAND_ENC_CB* p_enc_cplt_cback);
extern bool btm_identity_addr_to_random_pseudo(RawAddress* bd_addr,
- uint8_t* p_addr_type,
+ tBLE_ADDR_TYPE* p_addr_type,
bool refresh);
extern bool btm_identity_addr_to_random_pseudo_from_address_with_type(
tBLE_BD_ADDR* address_with_type, bool refresh);
diff --git a/system/stack/include/rfcdefs.h b/system/stack/include/rfcdefs.h
index ca9b3ce520..f5c952b034 100644
--- a/system/stack/include/rfcdefs.h
+++ b/system/stack/include/rfcdefs.h
@@ -35,11 +35,12 @@
/*
* Define used by RFCOMM TS frame types
*/
-#define RFCOMM_SABME 0x2F
-#define RFCOMM_UA 0x63
-#define RFCOMM_DM 0x0F
-#define RFCOMM_DISC 0x43
-#define RFCOMM_UIH 0xEF
+#define RFCOMM_SABME 0x2F // Start Asynchronous Balanced Mode (startup command)
+#define RFCOMM_UA 0x63 // Unnumbered Acknowledgement (response when connected)
+#define RFCOMM_DM \
+ 0x0F // Disconnected Mode (response to a command when disconnected)
+#define RFCOMM_DISC 0x43 // Disconnect (disconnect command)
+#define RFCOMM_UIH 0xEF // Unnumbered Information with Header check
/*
* Defenitions for the TS control frames
diff --git a/system/stack/include/stack_metrics_logging.h b/system/stack/include/stack_metrics_logging.h
index 1705f307ee..56921ddbdf 100644
--- a/system/stack/include/stack_metrics_logging.h
+++ b/system/stack/include/stack_metrics_logging.h
@@ -49,3 +49,6 @@ void log_manufacturer_info(const RawAddress& address,
const std::string& model,
const std::string& hardware_version,
const std::string& software_version);
+
+void log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum key,
+ int64_t value);
diff --git a/system/stack/metrics/stack_metrics_logging.cc b/system/stack/metrics/stack_metrics_logging.cc
index bd801ca03b..50f029f803 100644
--- a/system/stack/metrics/stack_metrics_logging.cc
+++ b/system/stack/metrics/stack_metrics_logging.cc
@@ -67,3 +67,8 @@ void log_manufacturer_info(const RawAddress& address,
address, source_type, source_name, manufacturer, model, hardware_version,
software_version);
}
+
+void log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum key,
+ int64_t value) {
+ bluetooth::shim::CountCounterMetrics(key, value);
+}
diff --git a/system/stack/rfcomm/port_api.cc b/system/stack/rfcomm/port_api.cc
index 862b731624..f49129d197 100644
--- a/system/stack/rfcomm/port_api.cc
+++ b/system/stack/rfcomm/port_api.cc
@@ -711,11 +711,18 @@ int PORT_ReadData(uint16_t handle, char* p_data, uint16_t max_len,
return (PORT_NOT_OPENED);
}
+ if (p_port->state == PORT_STATE_OPENING) {
+ LOG_WARN("Trying to read a port in PORT_STATE_OPENING state");
+ }
+
if (p_port->line_status) {
return (PORT_LINE_ERR);
}
- if (fixed_queue_is_empty(p_port->rx.queue)) return (PORT_SUCCESS);
+ if (fixed_queue_is_empty(p_port->rx.queue)) {
+ LOG_WARN("Read on empty input queue");
+ return (PORT_SUCCESS);
+ }
count = 0;
@@ -1024,6 +1031,10 @@ int PORT_WriteData(uint16_t handle, const char* p_data, uint16_t max_len,
return (PORT_NOT_OPENED);
}
+ if (p_port->state == PORT_STATE_OPENING) {
+ LOG_WARN("Write data received but port is in OPENING state");
+ }
+
if (!max_len || !p_port->peer_mtu) {
RFCOMM_TRACE_ERROR("PORT_WriteData() peer_mtu:%d", p_port->peer_mtu);
return (PORT_UNKNOWN_ERROR);
diff --git a/system/stack/rfcomm/port_rfc.cc b/system/stack/rfcomm/port_rfc.cc
index 647e6af357..111284a120 100644
--- a/system/stack/rfcomm/port_rfc.cc
+++ b/system/stack/rfcomm/port_rfc.cc
@@ -24,6 +24,7 @@
******************************************************************************/
#include <base/logging.h>
+#include <frameworks/proto_logging/stats/enums/bluetooth/enums.pb.h>
#include <cstdint>
#include <string>
@@ -35,6 +36,7 @@
#include "osi/include/osi.h" // UNUSED_ATTR
#include "stack/include/bt_hdr.h"
#include "stack/include/sdpdefs.h"
+#include "stack/include/stack_metrics_logging.h"
#include "stack/rfcomm/port_int.h"
#include "stack/rfcomm/rfc_int.h"
@@ -165,8 +167,12 @@ void port_start_close(tPORT* p_port) {
if ((p_mcb == NULL) || (p_port->rfc.state == RFC_STATE_CLOSED)) {
/* Call management callback function before calling port_release_port() to
* clear tPort */
- if (p_port->p_mgmt_callback)
+ if (p_port->p_mgmt_callback) {
p_port->p_mgmt_callback(PORT_CLOSED, p_port->handle);
+ log_counter_metrics(
+ android::bluetooth::CodePathCounterKeyEnum::RFCOMM_PORT_START_CLOSE,
+ 1);
+ }
port_release_port(p_port);
} else {
@@ -217,8 +223,10 @@ void PORT_StartCnf(tRFC_MCB* p_mcb, uint16_t result) {
if (p_port->p_mgmt_callback) {
p_port->p_mgmt_callback(PORT_START_FAILED, p_port->handle);
+ log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::
+ RFCOMM_PORT_START_CNF_FAILED,
+ 1);
}
-
port_release_port(p_port);
}
}
@@ -449,8 +457,12 @@ void PORT_DlcEstablishInd(tRFC_MCB* p_mcb, uint8_t dlci, uint16_t mtu) {
if (p_port->p_callback && (p_port->ev_mask & PORT_EV_CONNECTED))
(p_port->p_callback)(PORT_EV_CONNECTED, p_port->handle);
- if (p_port->p_mgmt_callback)
+ if (p_port->p_mgmt_callback) {
p_port->p_mgmt_callback(PORT_SUCCESS, p_port->handle);
+ log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::
+ RFCOMM_CONNECTION_SUCCESS_IND,
+ 1);
+ }
p_port->state = PORT_STATE_OPENED;
}
@@ -477,6 +489,9 @@ void PORT_DlcEstablishCnf(tRFC_MCB* p_mcb, uint8_t dlci, uint16_t mtu,
if (result != RFCOMM_SUCCESS) {
p_port->error = PORT_START_FAILED;
port_rfc_closed(p_port, PORT_START_FAILED);
+ log_counter_metrics(
+ android::bluetooth::CodePathCounterKeyEnum::RFCOMM_PORT_START_FAILED,
+ 1);
return;
}
@@ -489,9 +504,12 @@ void PORT_DlcEstablishCnf(tRFC_MCB* p_mcb, uint8_t dlci, uint16_t mtu,
if (p_port->p_callback && (p_port->ev_mask & PORT_EV_CONNECTED))
(p_port->p_callback)(PORT_EV_CONNECTED, p_port->handle);
- if (p_port->p_mgmt_callback)
+ if (p_port->p_mgmt_callback) {
p_port->p_mgmt_callback(PORT_SUCCESS, p_port->handle);
-
+ log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::
+ RFCOMM_CONNECTION_SUCCESS_CNF,
+ 1);
+ }
p_port->state = PORT_STATE_OPENED;
/* RPN is required only if we want to tell DTE how the port should be opened
@@ -561,6 +579,8 @@ void PORT_PortNegCnf(tRFC_MCB* p_mcb, uint8_t dlci,
RFCOMM_DlcReleaseReq(p_mcb, p_port->dlci);
port_rfc_closed(p_port, PORT_PORT_NEG_FAILED);
+ log_counter_metrics(
+ android::bluetooth::CodePathCounterKeyEnum::RFCOMM_PORT_NEG_FAILED, 1);
return;
}
@@ -698,6 +718,8 @@ void PORT_DlcReleaseInd(tRFC_MCB* p_mcb, uint8_t dlci) {
tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
if (!p_port) return;
port_rfc_closed(p_port, PORT_CLOSED);
+ log_counter_metrics(
+ android::bluetooth::CodePathCounterKeyEnum::RFCOMM_PORT_CLOSED, 1);
}
/*******************************************************************************
@@ -718,6 +740,9 @@ void PORT_CloseInd(tRFC_MCB* p_mcb) {
for (i = 0; i < MAX_RFC_PORTS; i++, p_port++) {
if (p_port->rfc.p_mcb == p_mcb) {
port_rfc_closed(p_port, PORT_PEER_CONNECTION_FAILED);
+ log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::
+ RFCOMM_PORT_PEER_CONNECTION_FAILED,
+ 1);
}
}
rfc_release_multiplexer_channel(p_mcb);
@@ -741,6 +766,9 @@ void Port_TimeOutCloseMux(tRFC_MCB* p_mcb) {
for (i = 0; i < MAX_RFC_PORTS; i++, p_port++) {
if (p_port->rfc.p_mcb == p_mcb) {
port_rfc_closed(p_port, PORT_PEER_TIMEOUT);
+ log_counter_metrics(
+ android::bluetooth::CodePathCounterKeyEnum::RFCOMM_PORT_PEER_TIMEOUT,
+ 1);
}
}
}
diff --git a/system/stack/rfcomm/rfc_event.h b/system/stack/rfcomm/rfc_event.h
index 98d24000d3..c950a4fcf2 100644
--- a/system/stack/rfcomm/rfc_event.h
+++ b/system/stack/rfcomm/rfc_event.h
@@ -21,47 +21,122 @@
/*
* Events that can be received by multiplexer as well as port state machines
*/
-typedef uint8_t tRFC_EVENT;
-#define RFC_EVENT_SABME 0
-#define RFC_EVENT_UA 1
-#define RFC_EVENT_DM 2
-#define RFC_EVENT_DISC 3
-#define RFC_EVENT_UIH 4
-#define RFC_EVENT_TIMEOUT 5
-#define RFC_EVENT_BAD_FRAME 50
+enum tRFC_EVENT : uint16_t {
+ /*
+ * Events that can be received by multiplexer as well as port state machines
+ */
+ RFC_EVENT_SABME = 0,
+ RFC_EVENT_UA = 1,
+ RFC_EVENT_DM = 2,
+ RFC_EVENT_DISC = 3,
+ RFC_EVENT_UIH = 4,
+ RFC_EVENT_TIMEOUT = 5,
+ RFC_EVENT_BAD_FRAME = 50,
+};
+
/*
* Multiplexer events
*/
-typedef uint8_t tRFC_MX_EVENT;
-#define RFC_MX_EVENT_SABME RFC_EVENT_SABME
-#define RFC_MX_EVENT_UA RFC_EVENT_UA
-#define RFC_MX_EVENT_DM RFC_EVENT_DM
-#define RFC_MX_EVENT_DISC RFC_EVENT_DISC
-#define RFC_MX_EVENT_UIH RFC_EVENT_UIH
-#define RFC_MX_EVENT_TIMEOUT RFC_EVENT_TIMEOUT
-#define RFC_MX_EVENT_START_REQ 6
-#define RFC_MX_EVENT_START_RSP 7
-#define RFC_MX_EVENT_CLOSE_REQ 8
-#define RFC_MX_EVENT_CONN_CNF 9
-#define RFC_MX_EVENT_CONN_IND 10
-#define RFC_MX_EVENT_CONF_CNF 11
-#define RFC_MX_EVENT_CONF_IND 12
-#define RFC_MX_EVENT_QOS_VIOLATION_IND 13
-#define RFC_MX_EVENT_DISC_IND 14
+enum tRFC_MX_EVENT : uint16_t {
+ /*
+ * Multiplexer events
+ */
+ RFC_MX_EVENT_SABME = RFC_EVENT_SABME,
+ RFC_MX_EVENT_UA = RFC_EVENT_UA,
+ RFC_MX_EVENT_DM = RFC_EVENT_DM,
+ RFC_MX_EVENT_DISC = RFC_EVENT_DISC,
+ RFC_MX_EVENT_UIH = RFC_EVENT_UIH,
+ RFC_MX_EVENT_TIMEOUT = RFC_EVENT_TIMEOUT,
+ RFC_MX_EVENT_START_REQ = 6,
+ RFC_MX_EVENT_START_RSP = 7,
+ RFC_MX_EVENT_CLOSE_REQ = 8,
+ RFC_MX_EVENT_CONN_CNF = 9,
+ RFC_MX_EVENT_CONN_IND = 10,
+ RFC_MX_EVENT_CONF_CNF = 11,
+ RFC_MX_EVENT_CONF_IND = 12,
+ RFC_MX_EVENT_QOS_VIOLATION_IND = 13,
+ RFC_MX_EVENT_DISC_IND = 14,
+};
/*
* Port events
*/
-typedef uint8_t tRFC_PORT_EVENT;
-#define RFC_PORT_EVENT_SABME RFC_EVENT_SABME
-#define RFC_PORT_EVENT_UA RFC_EVENT_UA
-#define RFC_PORT_EVENT_DM RFC_EVENT_DM
-#define RFC_PORT_EVENT_DISC RFC_EVENT_DISC
-#define RFC_PORT_EVENT_UIH RFC_EVENT_UIH
-#define RFC_PORT_EVENT_TIMEOUT RFC_EVENT_TIMEOUT
-#define RFC_PORT_EVENT_OPEN 9
-#define RFC_PORT_EVENT_ESTABLISH_RSP 11
-#define RFC_PORT_EVENT_CLOSE 12
-#define RFC_PORT_EVENT_CLEAR 13
-#define RFC_PORT_EVENT_DATA 14
-#define RFC_PORT_EVENT_SEC_COMPLETE 15
+enum tRFC_PORT_EVENT : uint16_t {
+ /*
+ * Port events
+ */
+ RFC_PORT_EVENT_SABME = RFC_EVENT_SABME,
+ RFC_PORT_EVENT_UA = RFC_EVENT_UA,
+ RFC_PORT_EVENT_DM = RFC_EVENT_DM,
+ RFC_PORT_EVENT_DISC = RFC_EVENT_DISC,
+ RFC_PORT_EVENT_UIH = RFC_EVENT_UIH,
+ RFC_PORT_EVENT_TIMEOUT = RFC_EVENT_TIMEOUT,
+ RFC_PORT_EVENT_OPEN = 9,
+ RFC_PORT_EVENT_ESTABLISH_RSP = 11,
+ RFC_PORT_EVENT_CLOSE = 12,
+ RFC_PORT_EVENT_CLEAR = 13,
+ RFC_PORT_EVENT_DATA = 14,
+ RFC_PORT_EVENT_SEC_COMPLETE = 15,
+};
+
+#define CASE_RETURN_TEXT(code) \
+ case code: \
+ return #code
+
+// Common events for both port and mux
+inline std::string rfcomm_event_text(const tRFC_EVENT& event) {
+ switch (event) {
+ CASE_RETURN_TEXT(RFC_EVENT_SABME);
+ CASE_RETURN_TEXT(RFC_EVENT_UA);
+ CASE_RETURN_TEXT(RFC_EVENT_DM);
+ CASE_RETURN_TEXT(RFC_EVENT_DISC);
+ CASE_RETURN_TEXT(RFC_EVENT_UIH);
+ CASE_RETURN_TEXT(RFC_EVENT_TIMEOUT);
+ CASE_RETURN_TEXT(RFC_EVENT_BAD_FRAME);
+ default:
+ return std::string("UNKNOWN[") + std::to_string(event) + std::string("]");
+ }
+}
+
+inline std::string rfcomm_mx_event_text(const tRFC_MX_EVENT& event) {
+ switch (event) {
+ CASE_RETURN_TEXT(RFC_MX_EVENT_SABME);
+ CASE_RETURN_TEXT(RFC_MX_EVENT_UA);
+ CASE_RETURN_TEXT(RFC_MX_EVENT_DM);
+ CASE_RETURN_TEXT(RFC_MX_EVENT_DISC);
+ CASE_RETURN_TEXT(RFC_MX_EVENT_UIH);
+ CASE_RETURN_TEXT(RFC_MX_EVENT_TIMEOUT);
+ CASE_RETURN_TEXT(RFC_MX_EVENT_START_REQ);
+ CASE_RETURN_TEXT(RFC_MX_EVENT_START_RSP);
+ CASE_RETURN_TEXT(RFC_MX_EVENT_CLOSE_REQ);
+ CASE_RETURN_TEXT(RFC_MX_EVENT_CONN_CNF);
+ CASE_RETURN_TEXT(RFC_MX_EVENT_CONN_IND);
+ CASE_RETURN_TEXT(RFC_MX_EVENT_CONF_CNF);
+ CASE_RETURN_TEXT(RFC_MX_EVENT_CONF_IND);
+ CASE_RETURN_TEXT(RFC_MX_EVENT_QOS_VIOLATION_IND);
+ CASE_RETURN_TEXT(RFC_MX_EVENT_DISC_IND);
+ default:
+ return std::string("UNKNOWN[") + std::to_string(event) + std::string("]");
+ }
+}
+
+inline std::string rfcomm_port_event_text(const tRFC_PORT_EVENT& event) {
+ switch (event) {
+ CASE_RETURN_TEXT(RFC_PORT_EVENT_SABME);
+ CASE_RETURN_TEXT(RFC_PORT_EVENT_UA);
+ CASE_RETURN_TEXT(RFC_PORT_EVENT_DM);
+ CASE_RETURN_TEXT(RFC_PORT_EVENT_DISC);
+ CASE_RETURN_TEXT(RFC_PORT_EVENT_UIH);
+ CASE_RETURN_TEXT(RFC_PORT_EVENT_TIMEOUT);
+ CASE_RETURN_TEXT(RFC_PORT_EVENT_OPEN);
+ CASE_RETURN_TEXT(RFC_PORT_EVENT_ESTABLISH_RSP);
+ CASE_RETURN_TEXT(RFC_PORT_EVENT_CLOSE);
+ CASE_RETURN_TEXT(RFC_PORT_EVENT_CLEAR);
+ CASE_RETURN_TEXT(RFC_PORT_EVENT_DATA);
+ CASE_RETURN_TEXT(RFC_PORT_EVENT_SEC_COMPLETE);
+ default:
+ return std::string("UNKNOWN[") + std::to_string(event) + std::string("]");
+ }
+}
+
+#undef CASE_RETURN_TEXT
diff --git a/system/stack/rfcomm/rfc_int.h b/system/stack/rfcomm/rfc_int.h
index 9b9c96b5a8..61706a2946 100644
--- a/system/stack/rfcomm/rfc_int.h
+++ b/system/stack/rfcomm/rfc_int.h
@@ -34,6 +34,7 @@
#include "stack/include/l2c_api.h"
#include "stack/rfcomm/port_int.h"
#include "stack/rfcomm/rfc_event.h"
+#include "stack/rfcomm/rfc_state.h"
#include "types/raw_address.h"
/*
@@ -146,50 +147,6 @@ typedef struct {
#define LINE_STATUS_FRAME 0x08 /* Receive Framing error */
#define LINE_STATUS_FAILED 0x10 /* Connection Failed */
-/*
- * Define states and events for the RFC multiplexer state machine
-*/
-typedef enum : uint16_t {
- RFC_MX_STATE_IDLE = 0,
- RFC_MX_STATE_WAIT_CONN_CNF = 1,
- RFC_MX_STATE_CONFIGURE = 2,
- RFC_MX_STATE_SABME_WAIT_UA = 3,
- RFC_MX_STATE_WAIT_SABME = 4,
- RFC_MX_STATE_CONNECTED = 5,
- RFC_MX_STATE_DISC_WAIT_UA = 6,
-} tRFC_MX_STATE;
-
-inline std::string rfcomm_mx_state_text(tRFC_MX_STATE state) {
- switch (state) {
- case RFC_MX_STATE_IDLE:
- return std::string("idle");
- case RFC_MX_STATE_WAIT_CONN_CNF:
- return std::string("wait_config");
- case RFC_MX_STATE_CONFIGURE:
- return std::string("configure");
- case RFC_MX_STATE_SABME_WAIT_UA:
- return std::string("sabme_wait_ua");
- case RFC_MX_STATE_WAIT_SABME:
- return std::string("wait_sabme");
- case RFC_MX_STATE_CONNECTED:
- return std::string("connected");
- case RFC_MX_STATE_DISC_WAIT_UA:
- return std::string("disconnect_wait_ua");
- default:
- return std::string("UNKNOWN");
- }
-}
-
-/*
- * Define port states
- */
-#define RFC_STATE_CLOSED 0
-#define RFC_STATE_SABME_WAIT_UA 1
-#define RFC_STATE_ORIG_WAIT_SEC_CHECK 2
-#define RFC_STATE_TERM_WAIT_SEC_CHECK 3
-#define RFC_STATE_OPENED 4
-#define RFC_STATE_DISC_WAIT_UA 5
-
/* seconds to wait for reply with Poll bit */
#define RFC_T1_TIMEOUT 20
/* seconds to wait for reply with Poll bit other than MX */
diff --git a/system/stack/rfcomm/rfc_l2cap_if.cc b/system/stack/rfcomm/rfc_l2cap_if.cc
index bf6fd6eafe..d5a80d26a3 100644
--- a/system/stack/rfcomm/rfc_l2cap_if.cc
+++ b/system/stack/rfcomm/rfc_l2cap_if.cc
@@ -22,12 +22,15 @@
*
******************************************************************************/
+#include <base/logging.h>
+
#include <cstddef>
#include <cstdint>
#include "bt_target.h"
#include "common/time_util.h"
#include "osi/include/allocator.h"
+#include "osi/include/log.h"
#include "osi/include/osi.h" // UNUSED_ATTR
#include "stack/include/bt_hdr.h"
#include "stack/include/bt_types.h"
@@ -36,8 +39,6 @@
#include "stack/rfcomm/rfc_int.h"
#include "types/raw_address.h"
-#include <base/logging.h>
-
/*
* Define Callback functions to be called by L2CAP
*/
@@ -177,6 +178,11 @@ void RFCOMM_ConnectCnf(uint16_t lcid, uint16_t result) {
*
******************************************************************************/
void RFCOMM_ConfigInd(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg) {
+ if (p_cfg == nullptr) {
+ LOG_ERROR("Received l2cap configuration info with nullptr");
+ return;
+ }
+
tRFC_MCB* p_mcb = rfc_find_lcid_mcb(lcid);
if (!p_mcb) {
diff --git a/system/stack/rfcomm/rfc_state.h b/system/stack/rfcomm/rfc_state.h
new file mode 100644
index 0000000000..b725a3503a
--- /dev/null
+++ b/system/stack/rfcomm/rfc_state.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+/*
+ * Define states and events for the RFC multiplexer state machine
+ */
+typedef enum : uint16_t {
+ RFC_MX_STATE_IDLE = 0,
+ RFC_MX_STATE_WAIT_CONN_CNF = 1,
+ RFC_MX_STATE_CONFIGURE = 2,
+ RFC_MX_STATE_SABME_WAIT_UA = 3,
+ RFC_MX_STATE_WAIT_SABME = 4,
+ RFC_MX_STATE_CONNECTED = 5,
+ RFC_MX_STATE_DISC_WAIT_UA = 6,
+} tRFC_MX_STATE;
+
+/*
+ * Define port states
+ */
+typedef enum : uint8_t {
+ RFC_STATE_CLOSED = 0,
+ RFC_STATE_SABME_WAIT_UA = 1,
+ RFC_STATE_ORIG_WAIT_SEC_CHECK = 2,
+ RFC_STATE_TERM_WAIT_SEC_CHECK = 3,
+ RFC_STATE_OPENED = 4,
+ RFC_STATE_DISC_WAIT_UA = 5,
+} tRFC_PORT_STATE;
+
+#define CASE_RETURN_TEXT(code) \
+ case code: \
+ return #code
+
+inline std::string rfcomm_mx_state_text(const tRFC_MX_STATE& state) {
+ switch (state) {
+ CASE_RETURN_TEXT(RFC_MX_STATE_IDLE);
+ CASE_RETURN_TEXT(RFC_MX_STATE_WAIT_CONN_CNF);
+ CASE_RETURN_TEXT(RFC_MX_STATE_CONFIGURE);
+ CASE_RETURN_TEXT(RFC_MX_STATE_SABME_WAIT_UA);
+ CASE_RETURN_TEXT(RFC_MX_STATE_WAIT_SABME);
+ CASE_RETURN_TEXT(RFC_MX_STATE_CONNECTED);
+ CASE_RETURN_TEXT(RFC_MX_STATE_DISC_WAIT_UA);
+ default:
+ return std::string("UNKNOWN[") + std::to_string(state) + std::string("]");
+ }
+}
+
+inline std::string rfcomm_port_state_text(const tRFC_PORT_STATE& state) {
+ switch (state) {
+ CASE_RETURN_TEXT(RFC_STATE_CLOSED);
+ CASE_RETURN_TEXT(RFC_STATE_SABME_WAIT_UA);
+ CASE_RETURN_TEXT(RFC_STATE_ORIG_WAIT_SEC_CHECK);
+ CASE_RETURN_TEXT(RFC_STATE_TERM_WAIT_SEC_CHECK);
+ CASE_RETURN_TEXT(RFC_STATE_OPENED);
+ CASE_RETURN_TEXT(RFC_STATE_DISC_WAIT_UA);
+ default:
+ return std::string("UNKNOWN[") + std::to_string(state) + std::string("]");
+ }
+}
+
+#undef CASE_RETURN_TEXT
diff --git a/system/stack/rfcomm/rfc_utils.cc b/system/stack/rfcomm/rfc_utils.cc
index e1eb71b90f..ae3708def4 100644
--- a/system/stack/rfcomm/rfc_utils.cc
+++ b/system/stack/rfcomm/rfc_utils.cc
@@ -320,6 +320,7 @@ void rfcomm_mcb_timer_timeout(void* data) {
void rfc_sec_check_complete(UNUSED_ATTR const RawAddress* bd_addr,
UNUSED_ATTR tBT_TRANSPORT transport,
void* p_ref_data, tBTM_STATUS res) {
+ CHECK(p_ref_data != nullptr);
tPORT* p_port = (tPORT*)p_ref_data;
/* Verify that PORT is still waiting for Security to complete */
diff --git a/system/test/mock/mock_main_shim_acl_api.cc b/system/test/mock/mock_main_shim_acl_api.cc
index 04709d7866..55ffd4cbe9 100644
--- a/system/test/mock/mock_main_shim_acl_api.cc
+++ b/system/test/mock/mock_main_shim_acl_api.cc
@@ -69,7 +69,7 @@ void bluetooth::shim::ACL_IgnoreAllLeConnections() {
}
void bluetooth::shim::ACL_ReadConnectionAddress(const RawAddress& pseudo_addr,
RawAddress& conn_addr,
- uint8_t* p_addr_type) {
+ tBLE_ADDR_TYPE* p_addr_type) {
mock_function_count_map[__func__]++;
}
diff --git a/system/test/mock/mock_main_shim_btm_api.cc b/system/test/mock/mock_main_shim_btm_api.cc
index 975374d009..d799c2027b 100644
--- a/system/test/mock/mock_main_shim_btm_api.cc
+++ b/system/test/mock/mock_main_shim_btm_api.cc
@@ -383,10 +383,6 @@ void bluetooth::shim::BTM_RemoteOobDataReply(tBTM_STATUS res,
const Octet16& r) {
mock_function_count_map[__func__]++;
}
-void bluetooth::shim::BTM_RemoveEirService(uint32_t* p_eir_uuid,
- uint16_t uuid16) {
- mock_function_count_map[__func__]++;
-}
void bluetooth::shim::BTM_SecAddBleDevice(const RawAddress& bd_addr,
tBT_DEVICE_TYPE dev_type,
tBLE_ADDR_TYPE addr_type) {
diff --git a/system/test/mock/mock_main_shim_l2cap_api.cc b/system/test/mock/mock_main_shim_l2cap_api.cc
index e2ed0048dc..0cf413c3c7 100644
--- a/system/test/mock/mock_main_shim_l2cap_api.cc
+++ b/system/test/mock/mock_main_shim_l2cap_api.cc
@@ -257,14 +257,14 @@ bool bluetooth::shim::L2CA_IsLeLink(uint16_t acl_handle) {
}
void bluetooth::shim::L2CA_ReadConnectionAddr(const RawAddress& pseudo_addr,
RawAddress& conn_addr,
- uint8_t* p_addr_type) {
+ tBLE_ADDR_TYPE* p_addr_type) {
mock_function_count_map[__func__]++;
test::mock::main_shim_l2cap_api::L2CA_ReadConnectionAddr(
pseudo_addr, conn_addr, p_addr_type);
}
bool bluetooth::shim::L2CA_ReadRemoteConnectionAddr(
const RawAddress& pseudo_addr, RawAddress& conn_addr,
- uint8_t* p_addr_type) {
+ tBLE_ADDR_TYPE* p_addr_type) {
mock_function_count_map[__func__]++;
return test::mock::main_shim_l2cap_api::L2CA_ReadRemoteConnectionAddr(
pseudo_addr, conn_addr, p_addr_type);
diff --git a/system/test/mock/mock_main_shim_l2cap_api.h b/system/test/mock/mock_main_shim_l2cap_api.h
index 1d8d37c74a..3916c05b6e 100644
--- a/system/test/mock/mock_main_shim_l2cap_api.h
+++ b/system/test/mock/mock_main_shim_l2cap_api.h
@@ -54,6 +54,7 @@ extern std::map<std::string, int> mock_function_count_map;
#include "stack/include/btm_api.h"
#include "stack/include/gatt_api.h"
#include "stack/include/sco_hci_link_interface.h"
+#include "types/ble_address_with_type.h"
#include "types/raw_address.h"
// Mocked compile conditionals, if any
@@ -418,11 +419,11 @@ extern struct L2CA_IsLeLink L2CA_IsLeLink;
// p_addr_type Returns: void
struct L2CA_ReadConnectionAddr {
std::function<void(const RawAddress& pseudo_addr, RawAddress& conn_addr,
- uint8_t* p_addr_type)>
+ tBLE_ADDR_TYPE* p_addr_type)>
body{[](const RawAddress& pseudo_addr, RawAddress& conn_addr,
- uint8_t* p_addr_type) {}};
+ tBLE_ADDR_TYPE* p_addr_type) {}};
void operator()(const RawAddress& pseudo_addr, RawAddress& conn_addr,
- uint8_t* p_addr_type) {
+ tBLE_ADDR_TYPE* p_addr_type) {
body(pseudo_addr, conn_addr, p_addr_type);
};
};
@@ -432,11 +433,11 @@ extern struct L2CA_ReadConnectionAddr L2CA_ReadConnectionAddr;
// p_addr_type Returns: bool
struct L2CA_ReadRemoteConnectionAddr {
std::function<bool(const RawAddress& pseudo_addr, RawAddress& conn_addr,
- uint8_t* p_addr_type)>
+ tBLE_ADDR_TYPE* p_addr_type)>
body{[](const RawAddress& pseudo_addr, RawAddress& conn_addr,
- uint8_t* p_addr_type) { return false; }};
+ tBLE_ADDR_TYPE* p_addr_type) { return false; }};
bool operator()(const RawAddress& pseudo_addr, RawAddress& conn_addr,
- uint8_t* p_addr_type) {
+ tBLE_ADDR_TYPE* p_addr_type) {
return body(pseudo_addr, conn_addr, p_addr_type);
};
};
diff --git a/system/test/mock/mock_osi_mutex.cc b/system/test/mock/mock_osi_mutex.cc
new file mode 100644
index 0000000000..0f9bc8599d
--- /dev/null
+++ b/system/test/mock/mock_osi_mutex.cc
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Generated mock file from original source file
+ * Functions generated:2
+ *
+ * mockcify.pl ver 0.3.0
+ */
+
+#include <cstdint>
+#include <functional>
+#include <map>
+#include <string>
+
+extern std::map<std::string, int> mock_function_count_map;
+
+// Mock include file to share data between tests and mock
+#include "test/mock/mock_osi_mutex.h"
+
+// Mocked internal structures, if any
+
+namespace test {
+namespace mock {
+namespace osi_mutex {
+
+// Function state capture and return values, if needed
+struct mutex_global_lock mutex_global_lock;
+struct mutex_global_unlock mutex_global_unlock;
+
+} // namespace osi_mutex
+} // namespace mock
+} // namespace test
+
+// Mocked function return values, if any
+namespace test {
+namespace mock {
+namespace osi_mutex {} // namespace osi_mutex
+} // namespace mock
+} // namespace test
+
+// Mocked functions, if any
+void mutex_global_lock(void) {
+ mock_function_count_map[__func__]++;
+ test::mock::osi_mutex::mutex_global_lock();
+}
+void mutex_global_unlock(void) {
+ mock_function_count_map[__func__]++;
+ test::mock::osi_mutex::mutex_global_unlock();
+}
+// Mocked functions complete
+// END mockcify generation
diff --git a/system/test/mock/mock_osi_mutex.h b/system/test/mock/mock_osi_mutex.h
new file mode 100644
index 0000000000..8870c878fb
--- /dev/null
+++ b/system/test/mock/mock_osi_mutex.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+/*
+ * Generated mock file from original source file
+ * Functions generated:2
+ *
+ * mockcify.pl ver 0.3.0
+ */
+
+#include <cstdint>
+#include <functional>
+#include <map>
+#include <string>
+
+extern std::map<std::string, int> mock_function_count_map;
+
+// Original included files, if any
+// NOTE: Since this is a mock file with mock definitions some number of
+// include files may not be required. The include-what-you-use
+// still applies, but crafting proper inclusion is out of scope
+// for this effort. This compilation unit may compile as-is, or
+// may need attention to prune from (or add to ) the inclusion set.
+#include <mutex>
+
+#include "osi/include/mutex.h"
+
+// Mocked compile conditionals, if any
+
+namespace test {
+namespace mock {
+namespace osi_mutex {
+
+// Shared state between mocked functions and tests
+// Name: mutex_global_lock
+// Params: void
+// Return: void
+struct mutex_global_lock {
+ std::function<void(void)> body{[](void) {}};
+ void operator()(void) { body(); };
+};
+extern struct mutex_global_lock mutex_global_lock;
+
+// Name: mutex_global_unlock
+// Params: void
+// Return: void
+struct mutex_global_unlock {
+ std::function<void(void)> body{[](void) {}};
+ void operator()(void) { body(); };
+};
+extern struct mutex_global_unlock mutex_global_unlock;
+
+} // namespace osi_mutex
+} // namespace mock
+} // namespace test
+
+// END mockcify generation \ No newline at end of file
diff --git a/system/test/mock/mock_stack_acl_ble.cc b/system/test/mock/mock_stack_acl_ble.cc
index b9b7794e87..33b3c99805 100644
--- a/system/test/mock/mock_stack_acl_ble.cc
+++ b/system/test/mock/mock_stack_acl_ble.cc
@@ -63,7 +63,7 @@ void acl_ble_enhanced_connection_complete_from_shim(
const tBLE_BD_ADDR& address_with_type, uint16_t handle, tHCI_ROLE role,
uint16_t conn_interval, uint16_t conn_latency, uint16_t conn_timeout,
const RawAddress& local_rpa, const RawAddress& peer_rpa,
- uint8_t peer_addr_type) {
+ tBLE_ADDR_TYPE peer_addr_type) {
mock_function_count_map[__func__]++;
}
diff --git a/system/test/mock/mock_stack_btm_ble_addr.cc b/system/test/mock/mock_stack_btm_ble_addr.cc
index 157ebe8fb7..80507b99cd 100644
--- a/system/test/mock/mock_stack_btm_ble_addr.cc
+++ b/system/test/mock/mock_stack_btm_ble_addr.cc
@@ -35,6 +35,7 @@ extern std::map<std::string, int> mock_function_count_map;
// Mock include file to share data between tests and mock
#include "test/mock/mock_stack_btm_ble_addr.h"
+#include "types/ble_address_with_type.h"
#include "types/raw_address.h"
// Mocked compile conditionals, if any
@@ -100,7 +101,8 @@ tBTM_SEC_DEV_REC* btm_ble_resolve_random_addr(const RawAddress& random_bda) {
random_bda);
}
bool btm_identity_addr_to_random_pseudo(RawAddress* bd_addr,
- uint8_t* p_addr_type, bool refresh) {
+ tBLE_ADDR_TYPE* p_addr_type,
+ bool refresh) {
mock_function_count_map[__func__]++;
return test::mock::stack_btm_ble_addr::btm_identity_addr_to_random_pseudo(
bd_addr, p_addr_type, refresh);
@@ -113,7 +115,7 @@ bool btm_identity_addr_to_random_pseudo_from_address_with_type(
address_with_type, refresh);
}
bool btm_random_pseudo_to_identity_addr(RawAddress* random_pseudo,
- uint8_t* p_identity_addr_type) {
+ tBLE_ADDR_TYPE* p_identity_addr_type) {
mock_function_count_map[__func__]++;
return test::mock::stack_btm_ble_addr::btm_random_pseudo_to_identity_addr(
random_pseudo, p_identity_addr_type);
diff --git a/system/test/mock/mock_stack_btm_ble_addr.h b/system/test/mock/mock_stack_btm_ble_addr.h
index e620953385..6f9a93737a 100644
--- a/system/test/mock/mock_stack_btm_ble_addr.h
+++ b/system/test/mock/mock_stack_btm_ble_addr.h
@@ -118,11 +118,13 @@ extern struct btm_ble_resolve_random_addr btm_ble_resolve_random_addr;
// Params: RawAddress* bd_addr, uint8_t* p_addr_type, bool refresh
// Returns: bool
struct btm_identity_addr_to_random_pseudo {
- std::function<bool(RawAddress* bd_addr, uint8_t* p_addr_type, bool refresh)>
- body{[](RawAddress* bd_addr, uint8_t* p_addr_type, bool refresh) {
+ std::function<bool(RawAddress* bd_addr, tBLE_ADDR_TYPE* p_addr_type,
+ bool refresh)>
+ body{[](RawAddress* bd_addr, tBLE_ADDR_TYPE* p_addr_type, bool refresh) {
return false;
}};
- bool operator()(RawAddress* bd_addr, uint8_t* p_addr_type, bool refresh) {
+ bool operator()(RawAddress* bd_addr, tBLE_ADDR_TYPE* p_addr_type,
+ bool refresh) {
return body(bd_addr, p_addr_type, refresh);
};
};
diff --git a/system/test/mock/mock_stack_btm_ble_gap.cc b/system/test/mock/mock_stack_btm_ble_gap.cc
index ef913db823..c3c8d0942d 100644
--- a/system/test/mock/mock_stack_btm_ble_gap.cc
+++ b/system/test/mock/mock_stack_btm_ble_gap.cc
@@ -26,10 +26,12 @@ extern std::map<std::string, int> mock_function_count_map;
#include <base/bind.h>
#include <base/strings/string_number_conversions.h>
+
#include <cstdint>
#include <list>
#include <memory>
#include <vector>
+
#include "common/time_util.h"
#include "device/include/controller.h"
#include "main/shim/acl_api.h"
@@ -47,6 +49,7 @@ extern std::map<std::string, int> mock_function_count_map;
#include "stack/include/gap_api.h"
#include "stack/include/hci_error_code.h"
#include "stack/include/inq_hci_link_interface.h"
+#include "types/ble_address_with_type.h"
#include "types/raw_address.h"
#ifndef UNUSED_ATTR
@@ -155,13 +158,13 @@ void btm_ble_increment_link_topology_mask(uint8_t link_role) {
mock_function_count_map[__func__]++;
}
void btm_ble_init(void) { mock_function_count_map[__func__]++; }
-void btm_ble_process_adv_addr(RawAddress& bda, uint8_t* addr_type) {
+void btm_ble_process_adv_addr(RawAddress& bda, tBLE_ADDR_TYPE* addr_type) {
mock_function_count_map[__func__]++;
}
void btm_ble_process_adv_pkt(uint8_t data_len, const uint8_t* data) {
mock_function_count_map[__func__]++;
}
-void btm_ble_process_adv_pkt_cont(uint16_t evt_type, uint8_t addr_type,
+void btm_ble_process_adv_pkt_cont(uint16_t evt_type, tBLE_ADDR_TYPE addr_type,
const RawAddress& bda, uint8_t primary_phy,
uint8_t secondary_phy,
uint8_t advertising_sid, int8_t tx_power,
@@ -171,7 +174,7 @@ void btm_ble_process_adv_pkt_cont(uint16_t evt_type, uint8_t addr_type,
mock_function_count_map[__func__]++;
}
void btm_ble_process_adv_pkt_cont_for_inquiry(
- uint16_t evt_type, uint8_t addr_type, const RawAddress& bda,
+ uint16_t evt_type, tBLE_ADDR_TYPE addr_type, const RawAddress& bda,
uint8_t primary_phy, uint8_t secondary_phy, uint8_t advertising_sid,
int8_t tx_power, int8_t rssi, uint16_t periodic_adv_int,
std::vector<uint8_t> advertising_data) {
@@ -220,7 +223,8 @@ void btm_clear_all_pending_le_entry(void) {
mock_function_count_map[__func__]++;
}
void btm_send_hci_set_scan_params(uint8_t scan_type, uint16_t scan_int,
- uint16_t scan_win, uint8_t addr_type_own,
+ uint16_t scan_win,
+ tBLE_ADDR_TYPE addr_type_own,
uint8_t scan_filter_policy) {
mock_function_count_map[__func__]++;
}
@@ -254,4 +258,4 @@ void btm_ble_periodic_adv_sync_tx_rcvd(uint8_t* p, uint16_t param_len) {
}
void btm_ble_biginfo_adv_report_rcvd(uint8_t* p, uint16_t param_len) {
mock_function_count_map[__func__]++;
-} \ No newline at end of file
+}
diff --git a/system/test/mock/mock_stack_btm_inq.cc b/system/test/mock/mock_stack_btm_inq.cc
index c068026118..356fe6d765 100644
--- a/system/test/mock/mock_stack_btm_inq.cc
+++ b/system/test/mock/mock_stack_btm_inq.cc
@@ -144,9 +144,6 @@ void BTM_AddEirService(uint32_t* p_eir_uuid, uint16_t uuid16) {
void BTM_CancelInquiry(void) { mock_function_count_map[__func__]++; }
void BTM_EnableInterlacedInquiryScan() { mock_function_count_map[__func__]++; }
void BTM_EnableInterlacedPageScan() { mock_function_count_map[__func__]++; }
-void BTM_RemoveEirService(uint32_t* p_eir_uuid, uint16_t uuid16) {
- mock_function_count_map[__func__]++;
-}
void btm_clr_inq_db(const RawAddress* p_bda) {
mock_function_count_map[__func__]++;
}
diff --git a/system/test/mock/mock_stack_metrics_logging.cc b/system/test/mock/mock_stack_metrics_logging.cc
index 3485c351a6..befaade97c 100644
--- a/system/test/mock/mock_stack_metrics_logging.cc
+++ b/system/test/mock/mock_stack_metrics_logging.cc
@@ -60,6 +60,7 @@ struct log_link_layer_connection_event log_link_layer_connection_event;
struct log_smp_pairing_event log_smp_pairing_event;
struct log_sdp_attribute log_sdp_attribute;
struct log_manufacturer_info log_manufacturer_info;
+struct log_counter_metrics log_counter_metrics;
} // namespace stack_metrics_logging
} // namespace mock
@@ -112,4 +113,10 @@ void log_manufacturer_info(const RawAddress& address,
software_version);
}
+void log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum key,
+ int64_t value) {
+ mock_function_count_map[__func__]++;
+ test::mock::stack_metrics_logging::log_counter_metrics(key, value);
+}
+
// END mockcify generation
diff --git a/system/test/mock/mock_stack_metrics_logging.h b/system/test/mock/mock_stack_metrics_logging.h
index f923859c3a..354ee37c90 100644
--- a/system/test/mock/mock_stack_metrics_logging.h
+++ b/system/test/mock/mock_stack_metrics_logging.h
@@ -159,6 +159,18 @@ struct log_manufacturer_info {
};
extern struct log_manufacturer_info log_manufacturer_info;
+// Name: log_counter_metrics
+struct log_counter_metrics {
+ std::function<void(android::bluetooth::CodePathCounterKeyEnum key,
+ int64_t value)>
+ body{
+ [](android::bluetooth::CodePathCounterKeyEnum key, int64_t value) {}};
+ void operator()(android::bluetooth::CodePathCounterKeyEnum key,
+ int64_t value) {
+ body(key, value);
+ };
+};
+extern struct log_counter_metrics log_counter_metrics;
} // namespace stack_metrics_logging
} // namespace mock
} // namespace test
diff --git a/system/types/Android.bp b/system/types/Android.bp
index 7beb94028d..059c8e501e 100644
--- a/system/types/Android.bp
+++ b/system/types/Android.bp
@@ -48,11 +48,15 @@ cc_test {
name: "net_test_types",
test_suites: ["device-tests"],
defaults: ["fluoride_defaults"],
+ include_dirs: [
+ "packages/modules/Bluetooth/system",
+ ],
host_supported: true,
srcs: [
+ "test/ble_address_with_type_unittest.cc",
+ "test/bluetooth/uuid_unittest.cc",
"test/class_of_device_unittest.cc",
"test/raw_address_unittest.cc",
- "test/bluetooth/uuid_unittest.cc",
],
shared_libs: [
"android.hardware.bluetooth@1.0",
diff --git a/system/types/ble_address_with_type.h b/system/types/ble_address_with_type.h
index 850abb900c..ecd62a85fb 100644
--- a/system/types/ble_address_with_type.h
+++ b/system/types/ble_address_with_type.h
@@ -45,8 +45,38 @@ inline std::string AddressTypeText(tBLE_ADDR_TYPE type) {
}
#endif // __cplusplus
+inline bool is_ble_addr_type_valid(uint8_t raw_type) { return raw_type < 4; }
+
+inline bool is_ble_addr_type_known(tBLE_ADDR_TYPE type) {
+ switch (type) {
+ case BLE_ADDR_PUBLIC:
+ case BLE_ADDR_PUBLIC_ID:
+ case BLE_ADDR_RANDOM:
+ case BLE_ADDR_RANDOM_ID:
+ return true;
+ default:
+ return false;
+ }
+}
+
+inline tBLE_ADDR_TYPE to_ble_addr_type(uint8_t raw_type) {
+ return (tBLE_ADDR_TYPE)raw_type;
+}
+inline uint8_t from_ble_addr_type(tBLE_ADDR_TYPE type) { return (uint8_t)type; }
+
/* BLE ADDR type ID bit */
#define BLE_ADDR_TYPE_ID_BIT 0x02
+inline bool is_identity_type(const tBLE_ADDR_TYPE& type) {
+ return type & BLE_ADDR_TYPE_ID_BIT;
+}
+
+#define STREAM_TO_BLE_ADDR_TYPE(type, p) \
+ { \
+ (type) = (tBLE_ADDR_TYPE)(*(p)); \
+ (p) += sizeof(tBLE_ADDR_TYPE); \
+ }
+#define BLE_ADDR_TYPE_TO_STREAM(p, type) \
+ { *(p)++ = (tBLE_ADDR_TYPE)(type); }
#ifdef __cplusplus
constexpr uint8_t kBleAddressPublicDevice = BLE_ADDR_PUBLIC;
diff --git a/system/types/test/ble_address_with_type_unittest.cc b/system/types/test/ble_address_with_type_unittest.cc
new file mode 100644
index 0000000000..5332d99e28
--- /dev/null
+++ b/system/types/test/ble_address_with_type_unittest.cc
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "types/ble_address_with_type.h"
+
+#include <gtest/gtest.h>
+
+TEST(BleAddressWithTypeTest, to_ble_addr_type) {
+ for (unsigned i = 0; i < 0xff + 1; i++) {
+ switch (to_ble_addr_type((uint8_t)i)) {
+ case BLE_ADDR_PUBLIC:
+ ASSERT_TRUE(i == 0);
+ break;
+ case BLE_ADDR_RANDOM:
+ ASSERT_TRUE(i == 1);
+ break;
+ case BLE_ADDR_PUBLIC_ID:
+ ASSERT_TRUE(i == 2);
+ break;
+ case BLE_ADDR_RANDOM_ID:
+ ASSERT_TRUE(i == 3);
+ break;
+ case BLE_ADDR_ANONYMOUS:
+ ASSERT_TRUE(i == 0xff);
+ break;
+ default:
+ ASSERT_TRUE(i > 3 && i != 0xff);
+ break;
+ }
+ }
+}
+
+TEST(BleAddressWithTypeTest, from_ble_addr_type) {
+ struct type_table_t {
+ tBLE_ADDR_TYPE type;
+ uint8_t value;
+ } type_table[] = {
+ {BLE_ADDR_PUBLIC, 0}, {BLE_ADDR_RANDOM, 1},
+ {BLE_ADDR_PUBLIC_ID, 2}, {BLE_ADDR_RANDOM_ID, 3},
+ {BLE_ADDR_ANONYMOUS, 0xff},
+ };
+
+ for (unsigned i = 0; i < sizeof(type_table) / sizeof(type_table[0]); i++) {
+ ASSERT_TRUE(from_ble_addr_type(type_table[i].type) == type_table[i].value);
+ }
+}
+
+TEST(BleAddressWithTypeTest, STREAM_TO_BLE_ADDR_TYPE) {
+ uint8_t buf[256] = {0x00, 0x01, 0x02, 0x03};
+ buf[10] = 0x01;
+ buf[20] = 0x02;
+ buf[30] = 0x03;
+ buf[127] = 0xff;
+ buf[255] = 0xff;
+
+ uint8_t* p = buf;
+ for (unsigned i = 0; i < sizeof(buf); i++) {
+ tBLE_ADDR_TYPE type;
+ STREAM_TO_BLE_ADDR_TYPE(type, p);
+ switch (i) {
+ case 0:
+ ASSERT_TRUE(type == BLE_ADDR_PUBLIC);
+ break;
+ case 1:
+ case 10:
+ ASSERT_TRUE(type == BLE_ADDR_RANDOM);
+ break;
+ case 2:
+ case 20:
+ ASSERT_TRUE(type == BLE_ADDR_PUBLIC_ID);
+ break;
+ case 3:
+ case 30:
+ ASSERT_TRUE(type == BLE_ADDR_RANDOM_ID);
+ break;
+ case 127:
+ case 255:
+ ASSERT_TRUE(type == BLE_ADDR_ANONYMOUS);
+ break;
+ default:
+ ASSERT_TRUE(type == BLE_ADDR_PUBLIC);
+ break;
+ }
+ }
+}
+
+TEST(BleAddressWithTypeTest, BLE_ADDR_TYPE_TO_STREAM) {
+ uint8_t buf[256] = {0};
+ uint8_t* p = buf;
+
+ BLE_ADDR_TYPE_TO_STREAM(p, BLE_ADDR_PUBLIC);
+ BLE_ADDR_TYPE_TO_STREAM(p, BLE_ADDR_RANDOM);
+ BLE_ADDR_TYPE_TO_STREAM(p, BLE_ADDR_PUBLIC_ID);
+ BLE_ADDR_TYPE_TO_STREAM(p, BLE_ADDR_RANDOM_ID);
+ BLE_ADDR_TYPE_TO_STREAM(p, BLE_ADDR_ANONYMOUS);
+
+ const uint8_t exp[] = {0x0, 0x1, 0x2, 0x3, 0xff};
+ ASSERT_EQ(*exp, *buf);
+ ASSERT_EQ(5, p - buf);
+}
diff --git a/tools/rootcanal/model/controller/link_layer_controller.cc b/tools/rootcanal/model/controller/link_layer_controller.cc
index e3cf441147..871a595dd2 100644
--- a/tools/rootcanal/model/controller/link_layer_controller.cc
+++ b/tools/rootcanal/model/controller/link_layer_controller.cc
@@ -38,8 +38,6 @@ namespace rootcanal {
constexpr uint16_t kNumCommandPackets = 0x01;
constexpr milliseconds kNoDelayMs(0);
-constexpr milliseconds kShortDelayMs(5);
-constexpr milliseconds kLongDelayMs(200);
// TODO: Model Rssi?
static uint8_t GetRssi() {
@@ -923,7 +921,7 @@ void LinkLayerController::IncomingIoCapabilityRequestPacket(
if (pairing_started) {
PairingType pairing_type = security_manager_.GetSimplePairingType();
if (pairing_type != PairingType::INVALID) {
- ScheduleTask(kShortDelayMs, [this, peer, pairing_type]() {
+ ScheduleTask(kNoDelayMs, [this, peer, pairing_type]() {
AuthenticateRemoteStage1(peer, pairing_type);
});
} else {
@@ -965,7 +963,7 @@ void LinkLayerController::IncomingIoCapabilityResponsePacket(
PairingType pairing_type = security_manager_.GetSimplePairingType();
if (pairing_type != PairingType::INVALID) {
- ScheduleTask(kShortDelayMs, [this, peer, pairing_type]() {
+ ScheduleTask(kNoDelayMs, [this, peer, pairing_type]() {
AuthenticateRemoteStage1(peer, pairing_type);
});
} else {
@@ -1878,7 +1876,7 @@ void LinkLayerController::IncomingPasskeyFailedPacket(
ASSERT(failed.IsValid());
auto current_peer = incoming.GetSourceAddress();
security_manager_.AuthenticationRequestFinished();
- ScheduleTask(kShortDelayMs, [this, current_peer]() {
+ ScheduleTask(kNoDelayMs, [this, current_peer]() {
if (properties_.IsUnmasked(EventCode::SIMPLE_PAIRING_COMPLETE)) {
send_event_(bluetooth::hci::SimplePairingCompleteBuilder::Create(
ErrorCode::AUTHENTICATION_FAILURE, current_peer));
@@ -1927,7 +1925,7 @@ void LinkLayerController::IncomingPinRequestPacket(
SaveKeyAndAuthenticate('L', peer); // Legacy
} else {
security_manager_.AuthenticationRequestFinished();
- ScheduleTask(kShortDelayMs, [this, peer]() {
+ ScheduleTask(kNoDelayMs, [this, peer]() {
if (properties_.IsUnmasked(EventCode::SIMPLE_PAIRING_COMPLETE)) {
send_event_(bluetooth::hci::SimplePairingCompleteBuilder::Create(
ErrorCode::AUTHENTICATION_FAILURE, peer));
@@ -1937,7 +1935,7 @@ void LinkLayerController::IncomingPinRequestPacket(
}
} else {
LOG_INFO("PIN pairing %s", properties_.GetAddress().ToString().c_str());
- ScheduleTask(kShortDelayMs, [this, peer]() {
+ ScheduleTask(kNoDelayMs, [this, peer]() {
security_manager_.SetPinRequested(peer);
if (properties_.IsUnmasked(EventCode::PIN_CODE_REQUEST)) {
send_event_(bluetooth::hci::PinCodeRequestBuilder::Create(peer));
@@ -1980,7 +1978,7 @@ void LinkLayerController::IncomingPinResponsePacket(
SaveKeyAndAuthenticate('L', peer); // Legacy
} else {
security_manager_.AuthenticationRequestFinished();
- ScheduleTask(kShortDelayMs, [this, peer]() {
+ ScheduleTask(kNoDelayMs, [this, peer]() {
if (properties_.IsUnmasked(EventCode::SIMPLE_PAIRING_COMPLETE)) {
send_event_(bluetooth::hci::SimplePairingCompleteBuilder::Create(
ErrorCode::AUTHENTICATION_FAILURE, peer));
@@ -1990,7 +1988,7 @@ void LinkLayerController::IncomingPinResponsePacket(
}
} else {
LOG_INFO("PIN pairing %s", properties_.GetAddress().ToString().c_str());
- ScheduleTask(kShortDelayMs, [this, peer]() {
+ ScheduleTask(kNoDelayMs, [this, peer]() {
security_manager_.SetPinRequested(peer);
if (properties_.IsUnmasked(EventCode::PIN_CODE_REQUEST)) {
send_event_(bluetooth::hci::PinCodeRequestBuilder::Create(peer));
@@ -2055,7 +2053,7 @@ void LinkLayerController::IncomingPageResponsePacket(
}
if (awaiting_authentication) {
- ScheduleTask(kShortDelayMs, [this, peer, handle]() {
+ ScheduleTask(kNoDelayMs, [this, peer, handle]() {
HandleAuthenticationRequest(peer, handle);
});
}
@@ -2230,8 +2228,7 @@ ErrorCode LinkLayerController::LinkKeyRequestReply(
security_manager_.WriteKey(peer, key);
security_manager_.AuthenticationRequestFinished();
- ScheduleTask(kShortDelayMs,
- [this, peer]() { AuthenticateRemoteStage2(peer); });
+ ScheduleTask(kNoDelayMs, [this, peer]() { AuthenticateRemoteStage2(peer); });
return ErrorCode::SUCCESS;
}
@@ -2251,11 +2248,11 @@ ErrorCode LinkLayerController::LinkKeyRequestNegativeReply(
security_manager_.AuthenticationRequest(address, handle, false);
}
- ScheduleTask(kShortDelayMs,
+ ScheduleTask(kNoDelayMs,
[this, address]() { StartSimplePairing(address); });
} else {
LOG_INFO("PIN pairing %s", properties_.GetAddress().ToString().c_str());
- ScheduleTask(kShortDelayMs, [this, address]() {
+ ScheduleTask(kNoDelayMs, [this, address]() {
security_manager_.SetPinRequested(address);
if (properties_.IsUnmasked(EventCode::PIN_CODE_REQUEST)) {
send_event_(bluetooth::hci::PinCodeRequestBuilder::Create(address));
@@ -2274,7 +2271,7 @@ ErrorCode LinkLayerController::IoCapabilityRequestReply(
PairingType pairing_type = security_manager_.GetSimplePairingType();
if (pairing_type != PairingType::INVALID) {
- ScheduleTask(kShortDelayMs, [this, peer, pairing_type]() {
+ ScheduleTask(kNoDelayMs, [this, peer, pairing_type]() {
AuthenticateRemoteStage1(peer, pairing_type);
});
SendLinkLayerPacket(model::packets::IoCapabilityResponseBuilder::Create(
@@ -2331,21 +2328,21 @@ void LinkLayerController::SaveKeyAndAuthenticate(uint8_t key_type,
if (key_type == 'L') {
// Legacy
- ScheduleTask(kShortDelayMs, [this, peer, key_vec]() {
+ ScheduleTask(kNoDelayMs, [this, peer, key_vec]() {
if (properties_.IsUnmasked(EventCode::LINK_KEY_NOTIFICATION)) {
send_event_(bluetooth::hci::LinkKeyNotificationBuilder::Create(
peer, key_vec, bluetooth::hci::KeyType::AUTHENTICATED_P192));
}
});
} else {
- ScheduleTask(kShortDelayMs, [this, peer]() {
+ ScheduleTask(kNoDelayMs, [this, peer]() {
if (properties_.IsUnmasked(EventCode::SIMPLE_PAIRING_COMPLETE)) {
send_event_(bluetooth::hci::SimplePairingCompleteBuilder::Create(
ErrorCode::SUCCESS, peer));
}
});
- ScheduleTask(kShortDelayMs, [this, peer, key_vec]() {
+ ScheduleTask(kNoDelayMs, [this, peer, key_vec]() {
if (properties_.IsUnmasked(EventCode::LINK_KEY_NOTIFICATION)) {
send_event_(bluetooth::hci::LinkKeyNotificationBuilder::Create(
peer, key_vec, bluetooth::hci::KeyType::AUTHENTICATED_P256));
@@ -2353,8 +2350,7 @@ void LinkLayerController::SaveKeyAndAuthenticate(uint8_t key_type,
});
}
- ScheduleTask(kShortDelayMs,
- [this, peer]() { AuthenticateRemoteStage2(peer); });
+ ScheduleTask(kNoDelayMs, [this, peer]() { AuthenticateRemoteStage2(peer); });
}
ErrorCode LinkLayerController::PinCodeRequestReply(const Address& peer,
@@ -2365,7 +2361,7 @@ ErrorCode LinkLayerController::PinCodeRequestReply(const Address& peer,
LOG_INFO("%s: %s != %s", properties_.GetAddress().ToString().c_str(),
peer.ToString().c_str(), current_peer.ToString().c_str());
security_manager_.AuthenticationRequestFinished();
- ScheduleTask(kShortDelayMs, [this, current_peer]() {
+ ScheduleTask(kNoDelayMs, [this, current_peer]() {
if (properties_.IsUnmasked(EventCode::SIMPLE_PAIRING_COMPLETE)) {
send_event_(bluetooth::hci::SimplePairingCompleteBuilder::Create(
ErrorCode::AUTHENTICATION_FAILURE, current_peer));
@@ -2384,7 +2380,7 @@ ErrorCode LinkLayerController::PinCodeRequestReply(const Address& peer,
SaveKeyAndAuthenticate('L', peer); // Legacy
} else {
security_manager_.AuthenticationRequestFinished();
- ScheduleTask(kShortDelayMs, [this, peer]() {
+ ScheduleTask(kNoDelayMs, [this, peer]() {
if (properties_.IsUnmasked(EventCode::SIMPLE_PAIRING_COMPLETE)) {
send_event_(bluetooth::hci::SimplePairingCompleteBuilder::Create(
ErrorCode::AUTHENTICATION_FAILURE, peer));
@@ -2402,7 +2398,7 @@ ErrorCode LinkLayerController::PinCodeRequestNegativeReply(
const Address& peer) {
auto current_peer = security_manager_.GetAuthenticationAddress();
security_manager_.AuthenticationRequestFinished();
- ScheduleTask(kShortDelayMs, [this, current_peer]() {
+ ScheduleTask(kNoDelayMs, [this, current_peer]() {
if (properties_.IsUnmasked(EventCode::SIMPLE_PAIRING_COMPLETE)) {
send_event_(bluetooth::hci::SimplePairingCompleteBuilder::Create(
ErrorCode::AUTHENTICATION_FAILURE, current_peer));
@@ -2431,7 +2427,7 @@ ErrorCode LinkLayerController::UserConfirmationRequestNegativeReply(
const Address& peer) {
auto current_peer = security_manager_.GetAuthenticationAddress();
security_manager_.AuthenticationRequestFinished();
- ScheduleTask(kShortDelayMs, [this, current_peer]() {
+ ScheduleTask(kNoDelayMs, [this, current_peer]() {
if (properties_.IsUnmasked(EventCode::SIMPLE_PAIRING_COMPLETE)) {
send_event_(bluetooth::hci::SimplePairingCompleteBuilder::Create(
ErrorCode::AUTHENTICATION_FAILURE, current_peer));
@@ -2459,7 +2455,7 @@ ErrorCode LinkLayerController::UserPasskeyRequestNegativeReply(
const Address& peer) {
auto current_peer = security_manager_.GetAuthenticationAddress();
security_manager_.AuthenticationRequestFinished();
- ScheduleTask(kShortDelayMs, [this, current_peer]() {
+ ScheduleTask(kNoDelayMs, [this, current_peer]() {
if (properties_.IsUnmasked(EventCode::SIMPLE_PAIRING_COMPLETE)) {
send_event_(bluetooth::hci::SimplePairingCompleteBuilder::Create(
ErrorCode::AUTHENTICATION_FAILURE, current_peer));
@@ -2487,7 +2483,7 @@ ErrorCode LinkLayerController::RemoteOobDataRequestNegativeReply(
const Address& peer) {
auto current_peer = security_manager_.GetAuthenticationAddress();
security_manager_.AuthenticationRequestFinished();
- ScheduleTask(kShortDelayMs, [this, current_peer]() {
+ ScheduleTask(kNoDelayMs, [this, current_peer]() {
if (properties_.IsUnmasked(EventCode::SIMPLE_PAIRING_COMPLETE)) {
send_event_(bluetooth::hci::SimplePairingCompleteBuilder::Create(
ErrorCode::AUTHENTICATION_FAILURE, current_peer));
@@ -2544,7 +2540,7 @@ ErrorCode LinkLayerController::AuthenticationRequested(uint16_t handle) {
AddressWithType remote = connections_.GetAddress(handle);
- ScheduleTask(kShortDelayMs, [this, remote, handle]() {
+ ScheduleTask(kNoDelayMs, [this, remote, handle]() {
HandleAuthenticationRequest(remote.GetAddress(), handle);
});
@@ -2591,7 +2587,7 @@ ErrorCode LinkLayerController::SetConnectionEncryption(
return ErrorCode::PIN_OR_KEY_MISSING;
}
- ScheduleTask(kShortDelayMs, [this, remote, handle, encryption_enable]() {
+ ScheduleTask(kNoDelayMs, [this, remote, handle, encryption_enable]() {
HandleSetConnectionEncryption(remote.GetAddress(), handle,
encryption_enable);
});
@@ -2603,7 +2599,7 @@ ErrorCode LinkLayerController::AcceptConnectionRequest(const Address& bd_addr,
if (connections_.HasPendingConnection(bd_addr)) {
LOG_INFO("Accepting connection request from %s",
bd_addr.ToString().c_str());
- ScheduleTask(kLongDelayMs, [this, bd_addr, try_role_switch]() {
+ ScheduleTask(kNoDelayMs, [this, bd_addr, try_role_switch]() {
LOG_INFO("Accepted connection from %s", bd_addr.ToString().c_str());
MakePeripheralConnection(bd_addr, try_role_switch);
});
@@ -2638,7 +2634,7 @@ ErrorCode LinkLayerController::AcceptConnectionRequest(const Address& bd_addr,
link_parameters.extended));
// Schedule HCI Connection Complete event.
- ScheduleTask(kShortDelayMs, [this, status, sco_handle, bd_addr]() {
+ ScheduleTask(kNoDelayMs, [this, status, sco_handle, bd_addr]() {
send_event_(bluetooth::hci::ConnectionCompleteBuilder::Create(
ErrorCode(status), sco_handle, bd_addr, bluetooth::hci::LinkType::SCO,
bluetooth::hci::Enable::DISABLED));
@@ -2678,7 +2674,7 @@ ErrorCode LinkLayerController::RejectConnectionRequest(const Address& addr,
return ErrorCode::UNKNOWN_CONNECTION;
}
- ScheduleTask(kLongDelayMs, [this, addr, reason]() {
+ ScheduleTask(kNoDelayMs, [this, addr, reason]() {
RejectPeripheralConnection(addr, reason);
});
@@ -2723,7 +2719,7 @@ ErrorCode LinkLayerController::CreateConnectionCancel(const Address& addr) {
void LinkLayerController::SendDisconnectionCompleteEvent(uint16_t handle,
uint8_t reason) {
if (properties_.IsUnmasked(EventCode::DISCONNECTION_COMPLETE)) {
- ScheduleTask(kShortDelayMs, [this, handle, reason]() {
+ ScheduleTask(kNoDelayMs, [this, handle, reason]() {
send_event_(bluetooth::hci::DisconnectionCompleteBuilder::Create(
ErrorCode::SUCCESS, handle, ErrorCode(reason)));
});
@@ -2784,7 +2780,7 @@ ErrorCode LinkLayerController::ChangeConnectionPacketType(uint16_t handle,
return ErrorCode::UNKNOWN_CONNECTION;
}
- ScheduleTask(kShortDelayMs, [this, handle, types]() {
+ ScheduleTask(kNoDelayMs, [this, handle, types]() {
if (properties_.IsUnmasked(EventCode::CONNECTION_PACKET_TYPE_CHANGED)) {
send_event_(bluetooth::hci::ConnectionPacketTypeChangedBuilder::Create(
ErrorCode::SUCCESS, handle, types));
@@ -3156,8 +3152,8 @@ ErrorCode LinkLayerController::LeRemoteConnectionParameterRequestReply(
return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
}
- ScheduleTask(kShortDelayMs, [this, connection_handle, interval_min,
- interval_max, latency, timeout]() {
+ ScheduleTask(kNoDelayMs, [this, connection_handle, interval_min, interval_max,
+ latency, timeout]() {
LeConnectionUpdateComplete(connection_handle, interval_min, interval_max,
latency, timeout);
});
@@ -3423,7 +3419,7 @@ ErrorCode LinkLayerController::LeEnableEncryption(uint16_t handle,
return ErrorCode::UNKNOWN_CONNECTION;
}
- ScheduleTask(kShortDelayMs, [this, handle, rand, ediv, ltk]() {
+ ScheduleTask(kNoDelayMs, [this, handle, rand, ediv, ltk]() {
HandleLeEnableEncryption(handle, rand, ediv, ltk);
});
return ErrorCode::SUCCESS;
@@ -3823,8 +3819,8 @@ ErrorCode LinkLayerController::AcceptSynchronousConnection(
link_parameters.extended));
// Schedule HCI Synchronous Connection Complete event.
- ScheduleTask(kShortDelayMs, [this, status, sco_handle, bd_addr,
- link_parameters]() {
+ ScheduleTask(kNoDelayMs, [this, status, sco_handle, bd_addr,
+ link_parameters]() {
send_event_(bluetooth::hci::SynchronousConnectionCompleteBuilder::Create(
ErrorCode(status), sco_handle, bd_addr,
link_parameters.extended ? bluetooth::hci::ScoLinkType::ESCO
@@ -3858,7 +3854,7 @@ ErrorCode LinkLayerController::RejectSynchronousConnection(Address bd_addr,
properties_.GetAddress(), bd_addr, reason, 0, 0, 0, 0, 0, 0));
// Schedule HCI Synchronous Connection Complete event.
- ScheduleTask(kShortDelayMs, [this, reason, bd_addr]() {
+ ScheduleTask(kNoDelayMs, [this, reason, bd_addr]() {
send_event_(bluetooth::hci::SynchronousConnectionCompleteBuilder::Create(
ErrorCode(reason), 0, bd_addr, bluetooth::hci::ScoLinkType::ESCO, 0, 0,
0, 0, bluetooth::hci::ScoAirMode::TRANSPARENT));