diff options
322 files changed, 10347 insertions, 9011 deletions
@@ -3,7 +3,6 @@ # Project owners girardier@google.com #{LAST_RESORT_SUGGESTION} muhammadfalam@google.com #{LAST_RESORT_SUGGESTION} -sattiraju@google.com #{LAST_RESORT_SUGGESTION} siyuanh@google.com #{LAST_RESORT_SUGGESTION} sungsoo@google.com #{LAST_RESORT_SUGGESTION} diff --git a/android/BluetoothLegacyMigration/OWNERS b/android/BluetoothLegacyMigration/OWNERS index fad553d703..66467c7b3e 100644 --- a/android/BluetoothLegacyMigration/OWNERS +++ b/android/BluetoothLegacyMigration/OWNERS @@ -1,6 +1,5 @@ # Reviewers for /android/BluetoothLegacyMigration eruffieux@google.com -sattiraju@google.com siyuanh@google.com wescande@google.com diff --git a/android/apishim/OWNERS b/android/apishim/OWNERS index 231e3b66ef..a70b577d30 100644 --- a/android/apishim/OWNERS +++ b/android/apishim/OWNERS @@ -4,6 +4,5 @@ cmanton@google.com eruffieux@google.com jpawlowski@google.com mylesgw@google.com -sattiraju@google.com siyuanh@google.com wescande@google.com
\ No newline at end of file diff --git a/android/app/OWNERS b/android/app/OWNERS index aaf3dca876..ee993c40ff 100644 --- a/android/app/OWNERS +++ b/android/app/OWNERS @@ -1,12 +1,10 @@ # Reviewers for /android/app -aritrasen@google.com cmanton@google.com eruffieux@google.com hallstrom@google.com jpawlowski@google.com mylesgw@google.com -sattiraju@google.com siyuanh@google.com wescande@google.com yuyangh@google.com diff --git a/android/app/jni/com_android_bluetooth_avrcp_controller.cpp b/android/app/jni/com_android_bluetooth_avrcp_controller.cpp index dcb9fe6d87..57a80bb87d 100644 --- a/android/app/jni/com_android_bluetooth_avrcp_controller.cpp +++ b/android/app/jni/com_android_bluetooth_avrcp_controller.cpp @@ -125,7 +125,7 @@ static void btavrcp_playerapplicationsetting_callback( /*2 bytes for id and num */ arraylen += 2 + app_attrs[i].num_val; } - log::verbose(" arraylen {}", arraylen); + log::verbose("arraylen {}", arraylen); ScopedLocalRef<jbyteArray> playerattribs( sCallbackEnv.get(), sCallbackEnv->NewByteArray(arraylen)); @@ -174,7 +174,7 @@ static void btavrcp_playerapplicationsetting_changed_callback( ScopedLocalRef<jbyteArray> playerattribs( sCallbackEnv.get(), sCallbackEnv->NewByteArray(arraylen)); if (!playerattribs.get()) { - log::error("Fail to new jbyteArray playerattribs "); + log::error("Fail to new jbyteArray playerattribs"); return; } /* @@ -268,7 +268,7 @@ static void btavrcp_track_changed_callback(const RawAddress& bd_addr, ScopedLocalRef<jintArray> attribIds(sCallbackEnv.get(), sCallbackEnv->NewIntArray(num_attr)); if (!attribIds.get()) { - log::error(" failed to set new array for attribIds"); + log::error("failed to set new array for attribIds"); return; } sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), @@ -279,7 +279,7 @@ static void btavrcp_track_changed_callback(const RawAddress& bd_addr, sCallbackEnv.get(), sCallbackEnv->NewObjectArray((jint)num_attr, strclazz, 0)); if (!stringArray.get()) { - log::error(" failed to get String array"); + log::error("failed to get String array"); return; } diff --git a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp index f6982c297b..98bc4d4f4f 100644 --- a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp +++ b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp @@ -307,9 +307,8 @@ static void device_found_callback(int num_properties, return; } - log::verbose( - "Properties: {}, Address: {}", num_properties, - ADDRESS_TO_LOGGABLE_STR(*(RawAddress*)properties[addr_index].val)); + log::verbose("Properties: {}, Address: {}", num_properties, + *(RawAddress*)properties[addr_index].val); remote_device_properties_callback(BT_STATUS_SUCCESS, (RawAddress*)properties[addr_index].val, @@ -463,7 +462,7 @@ static void discovery_state_changed_callback(bt_discovery_state_t state) { CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid()) return; - log::verbose("DiscoveryState:{} ", state); + log::verbose("DiscoveryState:{}", state); sCallbackEnv->CallVoidMethod( sJniCallbacksObj, method_discoveryStateChangeCallback, (jint)state); @@ -509,8 +508,8 @@ static void pin_request_callback(RawAddress* bd_addr, bt_bdname_t* bdname, addr.get(), devname.get(), cod, min_16_digits); } -static void ssp_request_callback(RawAddress* bd_addr, bt_bdname_t* bdname, - uint32_t cod, bt_ssp_variant_t pairing_variant, +static void ssp_request_callback(RawAddress* bd_addr, + bt_ssp_variant_t pairing_variant, uint32_t pass_key) { if (!bd_addr) { log::error("Address is null"); @@ -536,19 +535,8 @@ static void ssp_request_callback(RawAddress* bd_addr, bt_bdname_t* bdname, sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), (jbyte*)bd_addr); - ScopedLocalRef<jbyteArray> devname( - sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(bt_bdname_t))); - if (!devname.get()) { - log::error("Error while allocating"); - return; - } - - sCallbackEnv->SetByteArrayRegion(devname.get(), 0, sizeof(bt_bdname_t), - (jbyte*)bdname); - sCallbackEnv->CallVoidMethod(sJniCallbacksObj, method_sspRequestCallback, - addr.get(), devname.get(), cod, - (jint)pairing_variant, pass_key); + addr.get(), (jint)pairing_variant, pass_key); } static jobject createClassicOobDataObject(JNIEnv* env, bt_oob_data_t oob_data) { @@ -745,8 +733,7 @@ static void switch_buffer_size_callback(bool is_low_latency_buffer_size) { CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid()) return; - log::verbose("SwitchBufferSizeCallback: {}", - is_low_latency_buffer_size ? "true" : "false"); + log::verbose("SwitchBufferSizeCallback: {}", is_low_latency_buffer_size); sCallbackEnv->CallVoidMethod( sJniCallbacksObj, method_switchBufferSizeCallback, @@ -763,8 +750,7 @@ static void switch_codec_callback(bool is_low_latency_buffer_size) { CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid()) return; - log::verbose("SwitchCodecCallback: {}", - is_low_latency_buffer_size ? "true" : "false"); + log::verbose("SwitchCodecCallback: {}", is_low_latency_buffer_size); sCallbackEnv->CallVoidMethod(sJniCallbacksObj, method_switchCodecCallback, (jboolean)is_low_latency_buffer_size); @@ -824,7 +810,7 @@ static void dut_mode_recv_callback(uint16_t /* opcode */, uint8_t* /* buf */, static void le_test_mode_recv_callback(bt_status_t status, uint16_t packet_count) { - log::verbose("status:{} packet_count:{} ", bt_status_text(status), + log::verbose("status:{} packet_count:{}", bt_status_text(status), packet_count); } @@ -2276,7 +2262,7 @@ int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env) { &method_devicePropertyChangedCallback}, {"deviceFoundCallback", "([B)V", &method_deviceFoundCallback}, {"pinRequestCallback", "([B[BIZ)V", &method_pinRequestCallback}, - {"sspRequestCallback", "([B[BIII)V", &method_sspRequestCallback}, + {"sspRequestCallback", "([BII)V", &method_sspRequestCallback}, {"bondStateChangeCallback", "(I[BII)V", &method_bondStateChangeCallback}, {"addressConsolidateCallback", "([B[B)V", &method_addressConsolidateCallback}, diff --git a/android/app/jni/com_android_bluetooth_hearing_aid.cpp b/android/app/jni/com_android_bluetooth_hearing_aid.cpp index 2dc16ed90d..2179f52b16 100644 --- a/android/app/jni/com_android_bluetooth_hearing_aid.cpp +++ b/android/app/jni/com_android_bluetooth_hearing_aid.cpp @@ -62,7 +62,7 @@ class HearingAidCallbacksImpl : public HearingAidCallbacks { void OnDeviceAvailable(uint8_t capabilities, uint64_t hi_sync_id, const RawAddress& bd_addr) override { - log::info("capabilities={} hi_sync_id={}", +capabilities, hi_sync_id); + log::info("capabilities={} hi_sync_id={}", capabilities, hi_sync_id); std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex); CallbackEnv sCallbackEnv(__func__); diff --git a/android/app/jni/com_android_bluetooth_hfp.cpp b/android/app/jni/com_android_bluetooth_hfp.cpp index fa1ead2083..2407ef7273 100644 --- a/android/app/jni/com_android_bluetooth_hfp.cpp +++ b/android/app/jni/com_android_bluetooth_hfp.cpp @@ -80,7 +80,7 @@ class JniHeadsetCallbacks : bluetooth::headset::Callbacks { void ConnectionStateCallback( bluetooth::headset::bthf_connection_state_t state, RawAddress* bd_addr) override { - log::info("{} for {}", state, ADDRESS_TO_LOGGABLE_CSTR(*bd_addr)); + log::info("{} for {}", state, *bd_addr); std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex); CallbackEnv sCallbackEnv(__func__); @@ -95,7 +95,7 @@ class JniHeadsetCallbacks : bluetooth::headset::Callbacks { void AudioStateCallback(bluetooth::headset::bthf_audio_state_t state, RawAddress* bd_addr) override { - log::info("{} for {}", state, ADDRESS_TO_LOGGABLE_CSTR(*bd_addr)); + log::info("{} for {}", state, *bd_addr); std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex); CallbackEnv sCallbackEnv(__func__); @@ -503,7 +503,7 @@ static jboolean connectHfpNative(JNIEnv* env, jobject /* object */, jniThrowIOException(env, EINVAL); return JNI_FALSE; } - log::info("device {}", ADDRESS_TO_LOGGABLE_CSTR(*((RawAddress*)addr))); + log::info("device {}", *((RawAddress*)addr)); bt_status_t status = sBluetoothHfpInterface->Connect((RawAddress*)addr); if (status != BT_STATUS_SUCCESS) { log::error("Failed HF connection, status: {}", bt_status_text(status)); @@ -525,7 +525,7 @@ static jboolean disconnectHfpNative(JNIEnv* env, jobject /* object */, jniThrowIOException(env, EINVAL); return JNI_FALSE; } - log::info("device {}", ADDRESS_TO_LOGGABLE_CSTR(*((RawAddress*)addr))); + log::info("device {}", *((RawAddress*)addr)); bt_status_t status = sBluetoothHfpInterface->Disconnect((RawAddress*)addr); if (status != BT_STATUS_SUCCESS) { log::error("Failed HF disconnection, status: {}", bt_status_text(status)); @@ -547,7 +547,7 @@ static jboolean connectAudioNative(JNIEnv* env, jobject /* object */, jniThrowIOException(env, EINVAL); return JNI_FALSE; } - log::info("device {}", ADDRESS_TO_LOGGABLE_CSTR(*((RawAddress*)addr))); + log::info("device {}", *((RawAddress*)addr)); bt_status_t status = sBluetoothHfpInterface->ConnectAudio((RawAddress*)addr, 0); if (status != BT_STATUS_SUCCESS) { @@ -571,7 +571,7 @@ static jboolean disconnectAudioNative(JNIEnv* env, jobject /* object */, jniThrowIOException(env, EINVAL); return JNI_FALSE; } - log::info("device {}", ADDRESS_TO_LOGGABLE_CSTR(*((RawAddress*)addr))); + log::info("device {}", *((RawAddress*)addr)); bt_status_t status = sBluetoothHfpInterface->DisconnectAudio((RawAddress*)addr); if (status != BT_STATUS_SUCCESS) { diff --git a/android/app/jni/com_android_bluetooth_hfpclient.cpp b/android/app/jni/com_android_bluetooth_hfpclient.cpp index f51255bf6e..02388603f0 100644 --- a/android/app/jni/com_android_bluetooth_hfpclient.cpp +++ b/android/app/jni/com_android_bluetooth_hfpclient.cpp @@ -201,7 +201,7 @@ static void callsetup_cb(const RawAddress* bd_addr, ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr)); if (!addr.get()) return; - log::debug("callsetup_cb bdaddr {}", ADDRESS_TO_LOGGABLE_STR(*bd_addr)); + log::debug("callsetup_cb bdaddr {}", *bd_addr); sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCallSetup, (jint)callsetup, addr.get()); diff --git a/android/app/src/com/android/bluetooth/bass_client/BaseData.java b/android/app/src/com/android/bluetooth/bass_client/BaseData.java index a2d75b257f..f98dda279c 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BaseData.java +++ b/android/app/src/com/android/bluetooth/bass_client/BaseData.java @@ -67,9 +67,9 @@ class BaseData { public static class BaseInformation { public byte[] presentationDelay = new byte[3]; public byte[] codecId = new byte[5]; - public byte codecConfigLength; + public int codecConfigLength; public byte[] codecConfigInfo; - public byte metaDataLength; + public int metaDataLength; public byte[] metaData; public byte numSubGroups; public byte[] bisIndices; @@ -126,12 +126,12 @@ class BaseData { log("codecConfigLength: " + codecConfigLength); log("subGroupId: " + subGroupId); } - if (codecConfigLength != (byte) 0) { + if (codecConfigLength != 0) { log("codecConfigInfo: " + Arrays.toString(codecConfigInfo)); } if (level == 2) { log("metaDataLength: " + metaDataLength); - if (metaDataLength != (byte) 0) { + if (metaDataLength != 0) { log("metaData: " + Arrays.toString(metaData)); } if (level == 1 || level == 2) { @@ -250,18 +250,16 @@ class BaseData { 0, METADATA_CODEC_LENGTH); offset += METADATA_CODEC_LENGTH; } - node.codecConfigLength = serviceData[offset++]; + node.codecConfigLength = serviceData[offset++] & 0xff; if (node.codecConfigLength != 0) { - node.codecConfigInfo = new byte[(int) node.codecConfigLength]; - System.arraycopy(serviceData, offset, node.codecConfigInfo, - 0, (int) node.codecConfigLength); + node.codecConfigInfo = new byte[node.codecConfigLength]; + System.arraycopy(serviceData, offset, node.codecConfigInfo, 0, node.codecConfigLength); offset += node.codecConfigLength; } - node.metaDataLength = serviceData[offset++]; + node.metaDataLength = serviceData[offset++] & 0xff; if (node.metaDataLength != 0) { - node.metaData = new byte[(int) node.metaDataLength]; - System.arraycopy(serviceData, offset, - node.metaData, 0, (int) node.metaDataLength); + node.metaData = new byte[node.metaDataLength]; + System.arraycopy(serviceData, offset, node.metaData, 0, node.metaDataLength); offset += node.metaDataLength; } return new Pair<BaseInformation, Integer>(node, offset); @@ -273,11 +271,10 @@ class BaseData { BaseInformation node = new BaseInformation(); node.level = METADATA_LEVEL3; node.index = serviceData[offset++]; - node.codecConfigLength = serviceData[offset++]; + node.codecConfigLength = serviceData[offset++] & 0xff; if (node.codecConfigLength != 0) { - node.codecConfigInfo = new byte[(int) node.codecConfigLength]; - System.arraycopy(serviceData, offset, - node.codecConfigInfo, 0, (int) node.codecConfigLength); + node.codecConfigInfo = new byte[node.codecConfigLength]; + System.arraycopy(serviceData, offset, node.codecConfigInfo, 0, node.codecConfigLength); offset += node.codecConfigLength; } return new Pair<BaseInformation, Integer>(node, offset); diff --git a/android/app/src/com/android/bluetooth/bass_client/BassClientService.java b/android/app/src/com/android/bluetooth/bass_client/BassClientService.java index 947d96d01a..e84be4f8b0 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassClientService.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassClientService.java @@ -1505,12 +1505,10 @@ public class BassClientService extends ProfileService { BluetoothLeBroadcastMetadata sourceMetadata, boolean isGroupOp) { log( - "addSource: device: " - + sink - + " sourceMetadata" - + sourceMetadata - + " isGroupOp: " - + isGroupOp); + "addSource: " + + ("device: " + sink) + + (", sourceMetadata: " + sourceMetadata) + + (", isGroupOp: " + isGroupOp)); List<BluetoothDevice> devices = getTargetDeviceList(sink, isGroupOp); // Don't coordinate it as a group if there's no group or there is one device only @@ -1570,12 +1568,12 @@ public class BassClientService extends ProfileService { if (sourceId != BassConstants.INVALID_SOURCE_ID) { sEventLogger.logd( TAG, - "Switch Broadcast Source: device: " - + device - + ", old SourceId: " - + sourceId - + ", new SourceMetadata: " - + sourceMetadata); + "Switch Broadcast Source: " + + ("device: " + device) + + (", old SourceId: " + sourceId) + + (", new broadcastId: " + sourceMetadata.getBroadcastId()) + + (", new broadcastName: " + + sourceMetadata.getBroadcastName())); // new source will be added once the existing source got removed if (isGroupOp) { @@ -1629,12 +1627,11 @@ public class BassClientService extends ProfileService { sEventLogger.logd( TAG, - "Add Broadcast Source: device: " - + device - + ", sourceMetadata: " - + sourceMetadata - + ", isGroupOp: " - + isGroupOp); + "Add Broadcast Source: " + + ("device: " + device) + + (", broadcastId: " + sourceMetadata.getBroadcastId()) + + (", broadcastName: " + sourceMetadata.getBroadcastName()) + + (", isGroupOp: " + isGroupOp)); Message message = stateMachine.obtainMessage(BassClientStateMachine.ADD_BCAST_SOURCE); message.obj = sourceMetadata; @@ -1642,10 +1639,10 @@ public class BassClientService extends ProfileService { if (code != null && code.length != 0) { sEventLogger.logd( TAG, - "Set Broadcast Code (Add Source context): device: " - + device - + ", broadcastId: " - + sourceMetadata.getBroadcastId()); + "Set Broadcast Code (Add Source context): " + + ("device: " + device) + + (", broadcastId: " + sourceMetadata.getBroadcastId()) + + (", broadcastName: " + sourceMetadata.getBroadcastName())); message = stateMachine.obtainMessage(BassClientStateMachine.SET_BCAST_CODE); message.obj = sourceMetadata; @@ -1664,7 +1661,11 @@ public class BassClientService extends ProfileService { */ public void modifySource( BluetoothDevice sink, int sourceId, BluetoothLeBroadcastMetadata updatedMetadata) { - log("modifySource: device: " + sink + " sourceId " + sourceId); + log( + "modifySource: " + + ("device: " + sink) + + ("sourceId: " + sourceId) + + (", updatedMetadata: " + updatedMetadata)); Map<BluetoothDevice, Integer> devices = getGroupManagedDeviceSources(sink, sourceId).second; if (updatedMetadata == null) { @@ -1695,12 +1696,11 @@ public class BassClientService extends ProfileService { sEventLogger.logd( TAG, - "Modify Broadcast Source: device: " - + device - + ", sourceId: " - + sourceId - + ", updatedMetadata: " - + updatedMetadata); + "Modify Broadcast Source: " + + ("device: " + device) + + ("sourceId: " + sourceId) + + (", updatedBroadcastId: " + updatedMetadata.getBroadcastId()) + + (", updatedBroadcastName: " + updatedMetadata.getBroadcastName())); Message message = stateMachine.obtainMessage(BassClientStateMachine.UPDATE_BCAST_SOURCE); @@ -1711,10 +1711,12 @@ public class BassClientService extends ProfileService { if (code != null && code.length != 0) { sEventLogger.logd( TAG, - "Set Broadcast Code (Modify Source context), device: " - + device - + ", sourceId: " - + sourceId); + "Set Broadcast Code (Modify Source context): " + + ("device: " + device) + + ("sourceId: " + sourceId) + + (", updatedBroadcastId: " + updatedMetadata.getBroadcastId()) + + (", updatedBroadcastName: " + + updatedMetadata.getBroadcastName())); message = stateMachine.obtainMessage(BassClientStateMachine.SET_BCAST_CODE); message.obj = updatedMetadata; message.arg1 = BassClientStateMachine.ARGTYPE_METADATA; @@ -1731,7 +1733,7 @@ public class BassClientService extends ProfileService { * @param sourceId source ID as delivered in onSourceAdded */ public void removeSource(BluetoothDevice sink, int sourceId) { - log("removeSource: device = " + sink + ", sourceId " + sourceId); + log("removeSource: device: " + sink + ", sourceId: " + sourceId); Map<BluetoothDevice, Integer> devices = getGroupManagedDeviceSources(sink, sourceId).second; for (Map.Entry<BluetoothDevice, Integer> deviceSourceIdPair : devices.entrySet()) { @@ -1768,10 +1770,11 @@ public class BassClientService extends ProfileService { if (metaData != null && stateMachine.isSyncedToTheSource(sourceId)) { sEventLogger.logd( TAG, - "Remove Broadcast Source(Force lost PA sync): device: " - + device - + ", sourceId: " - + sourceId); + "Remove Broadcast Source(Force lost PA sync): " + + ("device: " + device) + + (", sourceId: " + sourceId) + + (", broadcastId: " + metaData.getBroadcastId()) + + (", broadcastName: " + metaData.getBroadcastName())); log("Force source to lost PA sync"); Message message = stateMachine.obtainMessage( @@ -2159,13 +2162,11 @@ public class BassClientService extends ProfileService { sEventLogger.logd( TAG, - "Modify Broadcast Source (resume): device: " - + sink - + ", sourceId: " - + sourceId - + ", updatedMetadata: " - + metadata); - + "Modify Broadcast Source (resume): " + + ("device: " + sink) + + ("sourceId: " + sourceId) + + (", updatedBroadcastId: " + metadata.getBroadcastId()) + + (", updatedBroadcastName: " + metadata.getBroadcastName())); Message message = stateMachine.obtainMessage(BassClientStateMachine.UPDATE_BCAST_SOURCE); message.arg1 = sourceId; diff --git a/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java b/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java index 7353839f9f..b9e59aded8 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java @@ -826,7 +826,7 @@ public class BassClientStateMachine extends StateMachine { offset += BassConstants.BCAST_RCVR_STATE_BIS_SYNC_SIZE; bisSyncState.add((long) Utils.byteArrayToInt(bisSyncIndex)); - byte metaDataLength = receiverState[offset++]; + int metaDataLength = receiverState[offset++] & 0xFF; if (metaDataLength > 0) { log("metadata of length: " + metaDataLength + "is available"); byte[] metaData = new byte[metaDataLength]; diff --git a/android/app/src/com/android/bluetooth/bass_client/PublicBroadcastData.java b/android/app/src/com/android/bluetooth/bass_client/PublicBroadcastData.java index 5db0ffaa84..bff99cb25e 100644 --- a/android/app/src/com/android/bluetooth/bass_client/PublicBroadcastData.java +++ b/android/app/src/com/android/bluetooth/bass_client/PublicBroadcastData.java @@ -35,7 +35,7 @@ class PublicBroadcastData { private final PublicBroadcastInfo mPublicBroadcastInfo; public static class PublicBroadcastInfo { - public byte metaDataLength; + public int metaDataLength; public byte[] metaData; public boolean isEncrypted; public int audioConfigQuality; @@ -53,7 +53,7 @@ class PublicBroadcastData { log("encrypted: " + isEncrypted); log("audio config quality: " + audioConfigQuality); log("metaDataLength: " + metaDataLength); - if (metaDataLength != (byte) 0) { + if (metaDataLength != 0) { log("metaData: " + Arrays.toString(metaData)); } log("**END: Public Broadcast Information****"); @@ -90,16 +90,20 @@ class PublicBroadcastData { } // Parse Public broadcast announcement metadata - publicBroadcastInfo.metaDataLength = serviceData[offset++]; + publicBroadcastInfo.metaDataLength = serviceData[offset++] & 0xff; if (serviceData.length != (publicBroadcastInfo.metaDataLength + PUBLIC_BROADCAST_SERVICE_DATA_LEN_MIN)) { Log.w(TAG, "Invalid meta data length for PublicBroadcastData construction"); return null; } if (publicBroadcastInfo.metaDataLength != 0) { - publicBroadcastInfo.metaData = new byte[(int) publicBroadcastInfo.metaDataLength]; - System.arraycopy(serviceData, offset, - publicBroadcastInfo.metaData, 0, (int) publicBroadcastInfo.metaDataLength); + publicBroadcastInfo.metaData = new byte[publicBroadcastInfo.metaDataLength]; + System.arraycopy( + serviceData, + offset, + publicBroadcastInfo.metaData, + 0, + publicBroadcastInfo.metaDataLength); offset += publicBroadcastInfo.metaDataLength; } publicBroadcastInfo.print(); diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java b/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java index c7697ba845..ba67584be2 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java @@ -674,40 +674,56 @@ class AdapterProperties { Flags.identityAddressNullIfUnknown() ? Utils.getBrEdrAddress(device, mService) : mService.getIdentityAddress(address); - debugLog("cleanupPrevBondRecordsFor: " + device); + int deviceType = mRemoteDevices.getDeviceProperties(device).getDeviceType(); + debugLog("cleanupPrevBondRecordsFor: " + device + ", device type: " + deviceType); if (identityAddress == null) { return; } + if (Flags.cleanupLeOnlyDeviceType() && deviceType != BluetoothDevice.DEVICE_TYPE_LE) { + return; + } + for (BluetoothDevice existingDevice : mBondedDevices) { String existingAddress = existingDevice.getAddress(); String existingIdentityAddress = Flags.identityAddressNullIfUnknown() ? Utils.getBrEdrAddress(existingDevice, mService) : mService.getIdentityAddress(existingAddress); - - if (!identityAddress.equals(existingIdentityAddress) || address.equals( - existingAddress)) { - continue; + int existingDeviceType = + mRemoteDevices.getDeviceProperties(existingDevice).getDeviceType(); + + boolean removeExisting = false; + if (identityAddress.equals(existingIdentityAddress) + && !address.equals(existingAddress)) { + if (Flags.cleanupLeOnlyDeviceType()) { + // Existing device record should be removed only if the device type is LE-only + removeExisting = (existingDeviceType == BluetoothDevice.DEVICE_TYPE_LE); + } else { + removeExisting = true; + } } - // Found an existing device with same identity address but different pseudo address - if (mService.getNative().removeBond(Utils.getBytesFromAddress(existingAddress))) { - mBondedDevices.remove(existingDevice); - infoLog( - "Removing old bond record: " - + existingDevice - + " for the device: " - + device); - } else { - Log.e( - TAG, - "Unexpected error while removing old bond record:" - + existingDevice - + " for the device: " - + device); + if (removeExisting) { + // Found an existing LE-only device with the same identity address but different + // pseudo address + if (mService.getNative().removeBond(Utils.getBytesFromAddress(existingAddress))) { + mBondedDevices.remove(existingDevice); + infoLog( + "Removing old bond record: " + + existingDevice + + " for the device: " + + device); + } else { + Log.e( + TAG, + "Unexpected error while removing old bond record:" + + existingDevice + + " for the device: " + + device); + } + break; } - break; } } diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java index 2f3ea75ba0..5e970a92b7 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java @@ -318,6 +318,8 @@ public class AdapterService extends Service { private volatile boolean mTestModeEnabled = false; + private MetricsLogger mMetricsLogger; + /** Handlers for incoming service calls */ private AdapterServiceBinder mBinder; @@ -636,6 +638,7 @@ public class AdapterService extends Service { private void init() { Log.d(TAG, "init()"); Config.init(this); + initMetricsLogger(); mDeviceConfigListener.start(); if (!Flags.fastBindToApp()) { @@ -806,6 +809,23 @@ public class AdapterService extends Service { return mSilenceDeviceManager; } + private boolean initMetricsLogger() { + if (mMetricsLogger != null) { + return false; + } + mMetricsLogger = MetricsLogger.getInstance(); + return mMetricsLogger.init(this); + } + + private boolean closeMetricsLogger() { + if (mMetricsLogger == null) { + return false; + } + boolean result = mMetricsLogger.close(); + mMetricsLogger = null; + return result; + } + /** * Log L2CAP CoC Server Connection Metrics * @@ -858,6 +878,10 @@ public class AdapterService extends Service { socketAcceptanceLatencyMillis); } + public void setMetricsLogger(MetricsLogger metricsLogger) { + mMetricsLogger = metricsLogger; + } + /** * Log L2CAP CoC Client Connection Metrics * @@ -1317,6 +1341,8 @@ public class AdapterService extends Service { return; } + closeMetricsLogger(); + clearAdapterService(this); mCleaningUp = true; diff --git a/android/app/src/com/android/bluetooth/btservice/BondStateMachine.java b/android/app/src/com/android/bluetooth/btservice/BondStateMachine.java index a47dbe61d6..0fd7317580 100644 --- a/android/app/src/com/android/bluetooth/btservice/BondStateMachine.java +++ b/android/app/src/com/android/bluetooth/btservice/BondStateMachine.java @@ -52,7 +52,6 @@ import com.android.internal.util.State; import com.android.internal.util.StateMachine; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashSet; import java.util.Objects; import java.util.Optional; @@ -593,15 +592,12 @@ final class BondStateMachine extends StateMachine { } @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) - void sspRequestCallback(byte[] address, byte[] name, int cod, int pairingVariant, int passkey) { - //TODO(BT): Get wakelock and update name and cod + void sspRequestCallback(byte[] address, int pairingVariant, int passkey) { BluetoothDevice bdDevice = mRemoteDevices.getDevice(address); if (bdDevice == null) { mRemoteDevices.addDeviceProperties(address); } infoLog("sspRequestCallback: " + Utils.getRedactedAddressStringFromByte(address) - + " name: " + Arrays.toString(name) - + " cod: " + cod + " pairingVariant " + pairingVariant + " passkey: " + (Build.isDebuggable() ? passkey : "******")); int variant; diff --git a/android/app/src/com/android/bluetooth/btservice/DeviceBloomfilterGenerator.java b/android/app/src/com/android/bluetooth/btservice/DeviceBloomfilterGenerator.java index 356e02c36f..02b2c4bef8 100644 --- a/android/app/src/com/android/bluetooth/btservice/DeviceBloomfilterGenerator.java +++ b/android/app/src/com/android/bluetooth/btservice/DeviceBloomfilterGenerator.java @@ -25,393 +25,349 @@ import java.io.IOException; public class DeviceBloomfilterGenerator { public static final String BLOOM_FILTER_DEFAULT = - "0107000002EDC51BBFCA820B1E810DC" - + "797476C0A668983A4BBA3310080A6D0" - + "8C2BA2D711B50171FD8F495BEF01D33" - + "89FCFA606BAB443B474A8044F2328D5" - + "D2CBAE984DEBD265BCB0137CCE65FAC" - + "113CDB7F48A6603389EB044D580C0F8" - + "ECF916875116794C842344B5BB0DA3A" - + "29E82A72B08662CD7D2113AF027B426" - + "829676607D7FCE7BA33FCA3E14802F6" - + "7862DD1EE9A85B71EEF88E3666CCEB0" - + "17E70B518E6762AE42111A35CB6F44B" - + "B234A5F86A62A93D9EC61A9BC830939" - + "A2C6636C5FF27E05E3D54D07D1638A6" - + "E322F9EF68953B43976BE6F4BAE39B3" - + "828A0CD5EA6FE440005D64DABD0BBB0" - + "081EE00947331AB6E9907C01E8C1336" - + "64486D2A92A16902264405E4F7D6A67" - + "0E10470F37120C373D5C3CE098A57AC" - + "CC403CD74D8506E5C39BC4BE33EF070" - + "B4B3CA185A0D54077B011CD6DE32B92" - + "DE29ED749EC4D6C0B1AE006D72097D9" - + "876F2771317120BB09D46F0CE45A919" - + "ACCB6C5931A43F71149ED998AE303C3" - + "8136E0400B10B247A555839B5001CAF" - + "542854F74DA4413684952571A967ACA" - + "780C650F696774D380BA646CC4E7E6D" - + "E20D6F99135B1EAEDF6C9E05A6C90FB" - + "5585739A04BD52EBBE98D4FC848E299" - + "DB90E8EE63979CBF9422A93772ECCA1" - + "FE3254FBDF841C18C54B8D03EDAE5DA" - + "83801E1DAF19C3FF35B1638FEE6BA4C" - + "3AB905A4A19C37BF1F3699D0DFC18EA" - + "BDEB6F8D0B84304116EB91BF466A1C8" - + "7B2607C7D4F888BE389C3B2BF50ADC6" - + "F2B96E4BEFBBA441DC12241E8AA4D0E" - + "A968D22CEE01642FDBCF6B77641AF12" - + "EE348EE019239C84337A5E1F8ABE7F1" - + "F2BA41C0CB71BA63F07BC47EB930365" - + "7668C7BA920FE12C94847AC58A85ABD" - + "C4DC7AF58587E7707EED6201D2E03BF" - + "D90A31A4CA1428754CFAAE708983E3F" - + "C517F88071E270D08874649CBC90BB3" - + "D550A84723572ECA915CD95A62D12D4" - + "4964AC04A01769C252BFD2117E06D22" - + "422F4205F0BB0BF255A525F9ACED902" - + "E9C729352A1954C91F55525096A5DBF" - + "88F0C894507DF05E410D141DA54A55E" - + "D9905D4B2BEEB315AFE23CC37D4D705" - + "4BAEE2C231D8802518B0300FA47BCE1" - + "8D76DB17869EF18246BD30B716AB6CC" - + "DED6DE295F2D7EC9063ED7D4B769288" - + "9FC44283F0D4452B9CD25D84AEFBE5B" - + "3C352A6AE98DFEA9FD1B3797966E4AB" - + "DE5591628428245C231D89CCCAC63A4" - + "5497104611C07DBDC2250BFBC342226" - + "D2CC77960ED16EE28D132DBD4291575" - + "C92BEEFD9AB141A28BBD44E109F8915" - + "C9E3B6085590020A53197CD19FA4117" - + "38A7561F4F27F1965921B7BC7114AFA" - + "55BFDF726E428D1F3D6C5BB68421363" - + "8505B15F44F2A022474A56805D3401A" - + "507B44F5AEB77CA4725010E163D7096" - + "1953977102915870EFD152B9B213CE9" - + "E7FF4F441FDD509A78A9C31F41D9407" - + "48D765CFCB289082EB798681491138A" - + "99049DC89A6465CE7C2347F0E539AC0" - + "CFA4564B0FD886D964E6FDA5157EA71" - + "C8EA8CD69A27299E98A5AC308D012EE" - + "5ABECCCC580E800E42B2D0A2B00C0AF" - + "F8F9C219E800F4B3CE8C2BB6FA33477" - + "E68B74AB6EFC897AE9ABB7D023C00DC" - + "71EBA3B57F3AE55964F4D901DA2866A" - + "30FCB7ABE9A2B1E551955293FD7D7B4" - + "C7017A59BEE0ECCFB8718F1D3D1F51A" - + "C9068AAFFF8136A49B43E855CEA015C" - + "15510EA5916576E3FBA182A3DE04374" - + "03A1C0145E6F542659BFBE99C73B8AD" - + "0182399C3BFDE19E44023381838F620" - + "3A24E4D2AF668D9EDB1946366B5AEA8" - + "B6E8A8BF530AC32F00947B025CB9DEE" - + "6A91E010A3C1BD63AA0D24780E928D0" - + "3A5637F604F3C05AA0F86486FBFEE3E" - + "8F4978EAE88B37265FE29EDEED98B85" - + "49E399A640205F05A230EA95FACED77" - + "25A283FFDC2974076A4DA98A634A8C1" - + "FD58534CF2782440A0DD9B67C65989C" - + "99144223A29A10E845D169BA4ADB844" - + "4AB6ECA1861FCB5526B81B360975D85" - + "A0AA6DC27291123FE7B8016D798D073" - + "EABED77B9D4CB1920600F7B378DD89A" - + "A1652D92CBF0EA1C0ABA2EF0F5E444F" - + "EF61A8A17188694AA9011D5E6391F22" - + "C4F3D848E6ADBC7A843044BB4D89E0E" - + "6C7B4C1F4D5999D10D5F6E958E14A11" - + "0A8486F48D8ABB05CE578BAB6859D6F" - + "316D09F2A555B572AC9438E0B2A1109" - + "C9AEAF9C08E220D58162D4858489DBF" - + "5A18313FAC1791DCD217A2F6241D781" - + "A5EAB3DD43253A75C12C2BD17AA0AAB" - + "ABE34D5C4BD3C6D7DA991D9841D64E0" - + "95A32E19E10EC12ADABFAEBD2D318BA" - + "73624D1C6F68A60A7C091050F6E768F" - + "04B57934A6EDABABB9590B9B60E46C3" - + "F0A21A3BDCF873C658DD86AEE256402" - + "F24207559509A32B9225B76C482B341" - + "78A56CF16E561F1BC81ED422092AE58" - + "23382021CCA7A29F2721F970BCEEAE0" - + "EB9129054FD0E72E06E14CD4C1BA9EB" - + "936118C0CAE981021884240007BB3A1" - + "028B54D28ABD2EC580CE6319528354F" - + "BD5B35A5C7A251BB35E748D918130BD" - + "33205E9F9344926865247F20CA12F82" - + "8709DB0FFF3B69BB769E42035A7230D" - + "59290DBB16CF85E484A8A93D077B92B" - + "44791B3F8ACD98794C4005AA852C68E" - + "00F0DE3F2148E38C4F2A7B0AC0FA013" - + "C931B2478B63C67F7C507DAC614BCEF" - + "18813FB17DAA19CDF13847D1726A427" - + "56C837504488844C454B2F49EC488EE" - + "100C2895E32C16A17127E20550F3607" - + "FCD43A6C384A5C2673870CD8E2B55AD" - + "3994030A8DAEC6D279CC688ED810887" - + "3DA68DA066F57D2DE4A27536922B8E0" - + "FAC93E2925A07D226614B65BFDDD154" - + "7A72211A20A85CF8BF93D904D08E7A6" - + "C897BF886005DCB055E5D6DA8410604" - + "62C6F0A88391B8E833684A4349FDEF2" - + "D9398180671035888C9FC9D92024A6D" - + "97143EF15D7629D10F8EB94335B625E" - + "20EE79A3AAC3C3A3334FE7886A625E1" - + "5AB74D019C9E53AFB95297E28077846" - + "42AD102F437B9D26DBF435C4E699B9B" - + "EC422A8F69A8DB60338B32186275E67" - + "0A90C8636EF6E54BC292BE85C698BDF" - + "C879B0457046FEC28EA5FE2F4C4A12F" - + "5A176B768D29F0888E167A2DD52F889" - + "503FD43B0EFEB7D180FF65C01DC345E" - + "2C57248CA29478744E6315C9EA01FDC" - + "F28CB68C4065839FB545A2079FA8174" - + "5DF43C8EFFE5BB15287B26EFC6649EB" - + "148A52CB37733E995D950F86929D07C" - + "1F0C10F541142F9F2B8BD6F6E61297A" - + "FB900BD21EC99C2323E1F0F95EE7EDE" - + "DFCB6922A3E3FA8696C145801F6F526" - + "4B17734B75CAC18C4252A5F8A2A0B34" - + "1C4D401CFFA61A9D28B2135C61026CD" - + "A343875C793AB2E3D041748372789D2" - + "C362BB7FE48E136BA3D8C54E8105915" - + "740009BA55C53569EA3602FB49B738C" - + "B0B7EA34112854927AF7BDED517F721" - + "797DB06795AEB0EA14E2405CA956103" - + "A5F8A28FA4D43AC4705E49E0DAAD109" - + "F99405DC047BDD4BCA433896529F0EA" - + "C69C75E55701E01AF57D42015008AAC" - + "3B331D97F04A85A8E35DD868F2A4173" - + "D7DC18983ACBEFE14E4AA1E6DB4AB1A" - + "6B818F70F698B7E259FF31908E5C488" - + "C435710749C2E21CF64DFF34811F5C5" - + "9A01F382C9028FEEF14FF9093487155" - + "2A3C2A4C1D37ABAD6850199ABC29D75" - + "C19208B41C0D496BD59681B4F5374A3" - + "344FEA061C7D18E63902874CCEBD210" - + "9CDC6CF6DF39DBB1AD8C165A083C394" - + "0A56230E53D8EE882A7A229BE7085FF" - + "6BF3CA91C1A65598CEAF1002FF11E0E" - + "36EA3D63C67FBA0108DF4098487C697" - + "BBA81D7628DAACD209CA03C93B0FD9B" - + "A51AD36969BD084030FFADEC5334D70" - + "F536BAA5C5B874696E6D1814A0EDF8F" - + "65B41CEC8B963F99C0E4BE2D3082DBC" - + "4F9099275997134AEB3D8E848458C81" - + "E2F0334D13E98D5CA64B98096338F81" - + "CA8B410639AAE839E7AF7BF3B03499A" - + "F27CBE1CCE6450BF90AE14B8012F3EC" - + "D4C884C5D4ACF33BF555A082781B443" - + "E9E554D6E2375D609858DF6E3AE31C0" - + "C67E7AD87EB107E9C9519D1A2DBFBEE" - + "95A8468E7FB204B286683622C8ACE69" - + "71EA7C594200002F700028E9C34AA79" - + "AF3797B4671C01B22B95518FEF9A506" - + "6C95A5752EBAA99A220F7208CE5C459" - + "E685F12E3028982106AD4BD424D1A48" - + "63C888AA0CCFB13A35DB8FF8FE50E5F" - + "7C22B82330069F21D7BAE965CBC77AC" - + "F2606E442A2E560B82AC3DBB1D97226" - + "60CF185994F0CCAFA2B2DB4C5297816" - + "BF6B4486816AC8A3D63DA88AB0A4285" - + "D1206B4CCAC02C6DBF57455C3A17B4A" - + "A753B293AAFFEF1E90960C5F1425CCA" - + "F53A1DF0F26CE3173CD550EEC5C0404" - + "B44B8C0011FB62F2AF4DEED85F48FB8" - + "45AE42B08342E481F046C498C318FFB" - + "43CD7C8D53688961687191108FA0042" - + "043BAC117D80645CA8F123C5B010173" - + "4CB38FFD67A3887CEDA2A7D0D9EFE85" - + "3E6E16AEA29B95E8A9053F2BB2C97FB" - + "437F93E4D495568D1F108DFD2C6A11F" - + "0D3F7011A4FC9DDC0A0D77C107B349E" - + "34F20302AC1C384BD554F3D745D706A" - + "A2623C09A6FB3578B69C8A9C9423678" - + "A18ACCD604B145CB5444CBD1060A9B0" - + "E2C9AA3BF2B3A4369B4F23113218ECE" - + "B5BEC85C5028D04715E829DBED0CF96" - + "311AC77161A7ED39767895103EB6586" - + "134EB8E08C857B183D2A6BBF18E7E70" - + "006D982C024E9DD7002BD6FDFE34C2F" - + "268981305CD4E5BA5E7447EA1714B5A" - + "03CA1C3B2D090682670DC5A51C2C079" - + "191D2C6F79F3108664A1B3F2F16F0F4" - + "6288720C7B67E33EBA7ADB5847F50BB" - + "B5A8E402C4F0B1271BDAAB4CC6DBBDF" - + "1F092436569C8900F8B29155233FF36" - + "47282221E57787BC7FB45E58510D044" - + "1ED42AB7D52856C9F54FAACC104E6E0" - + "C5C2408FE091E9E27C1E67153AE48C8" - + "B24C42FA79E6C7C8045E6C0FEB11600" - + "6ABC9A182DD68D7BE04F290292CA8D8" - + "5E8B05A43A512C3FC49942187A892E1" - + "79E9360F8B9B11B5BEDADA6D416C192" - + "8A1C0D6D5FA1766BA829C8784152B68" - + "61EDEB5FAD3F40BD2091E77C2C044DE" - + "F8CE9BD55B8A2C11DF4E65C49860F29" - + "A4DF82997FDCA1ED71EC90F34466AA9" - + "865F21D7C2173E162D4CFB04330234A" - + "9195D20668F8523DAB73B7143710002" - + "7CF5DE51A33D789549CCD2369326E74" - + "962728F4D8D50BA6539044C1BB24FC5" - + "1C10EB575EC580459B191FD87198C9B" - + "99EDF5EB338C769AA12F6A0B9696686" - + "022B442F7D2D0842EA40E413888851B" - + "40105745C8E3D4C52FE78A9896397E1" - + "55BDB96132D8A36A8B06E7B53AB0984" - + "A5C0B76380D1C599F088476A005F493" - + "24F3E30ABA5CABC6AC7142DCAF1A758" - + "29AD9D95C4157F1124B10B7FB580C9A" - + "10A0931FFFB6AEB7CC408C62050553F" - + "8DDADD702B93CFF5A3EA63C2EDBE467" - + "DD375876403803428652DAACF8D469F" - + "FFD7DF42ADDBC65AC7A4C19F5019316" - + "D55E9700617C1A00C4C9763C1D6EF4B" - + "AE62BB100B8C888ADAB431C2941AE01" - + "01BF8830BC6AD9C2C08ED99AA881505" - + "8A52F31B132FAC3A440B5DD4BBFF4FF" - + "1043A2938E04C4BC922930AA8A298F4" - + "5A2A252F935BF1830D993BF0EEC2CE0" - + "41632D87E08E6E92D138803301785AE" - + "2C7BF8F035CBC4F660008F7C2CB0A2F" - + "B470A3B323AD23A5FC6EA915E2DC927" - + "B266F7BB08E1C5AB992B128B0D668F6" - + "658BF6B2D00F9D3573FC0A0F6156D9C" - + "259A1FFC9747F591EA25A9FC69F78A1" - + "9AF2D325CE63BDFDA51AB26C7DCCAE1" - + "D0C01EF504D70A4807DD682FE3AC8E9" - + "F4C609E6A2530152BF128112757B759" - + "21F3DB16EC4448F0122FAD7CDFF60A1" - + "686A8C39A1E37C1DF23B79280C1826E" - + "101E63ACF712BCD6812B4F86C87F91A" - + "3248B77417BBC345F388B836469F629" - + "7C996F14732E00E4083847842FA160A" - + "22C7A289ED5090E2F79C80D28B83243" - + "3FCBE5D5955582570D86BB5DAE95FAA" - + "B4B3BFF5833FD3201D8CAD6480B8035" - + "EA4D7A54D3AB7CA814B95C815EE9F59" - + "C3A8005394E6D4C826EDF64C5483AB2" - + "8A29C81F8957A82631AFCF5A2BC6AFA" - + "6975D46C7D9C98330ECCE773C18CC8E" - + "520FA12A6E96F1EDA40B761BDED47C8" - + "CDD63B481A2FE5506CE912848D3B979" - + "6BF2AAB5C7A901EF455DF897E18B230" - + "91E114A55CF920827ACEF7872A7532E" - + "49A1CFE1E23B4B9451749087C2BF2C1" - + "97B04664C61BB709C4434C63240B608" - + "86223746668D39ED82304CB8A4CCDB8" - + "15FB0BCF91752DD4A592A2BC96C1A8F" - + "5A4930688AC7748F827C28DEA1ABB56" - + "61CBBF38B59439644223C64D12C40A2" - + "7EF6C9A8986A0C9E78093D1837C53DB" - + "AD63CB1B33ABCE70853F584D1A7ED3A" - + "978B7FC26325D979E1DBA46FEA67AEE" - + "7D9C1750865FDED367829AE47D0ABD7" - + "BA8834925405BE324C242617036CE83" - + "CDF8BF06849C257C09B1F8FC03F0B60" - + "26B28D922AFB0B2FBA48DEDA3E8347F" - + "29260A9754D3781A8A5EDC70EB7DF01" - + "9056040C9CC7F220DE3FF9BE42CC80A" - + "65AFB0D2F54DEEB489D12816ECBB7C1" - + "C0803489C153B8578898BC206019CB4" - + "D16EECEC58C8AE11A05F9F80A4960F9" - + "3D4511710F8A53809CD19048B1A0E82" - + "E0BE98F84B2E54E18413DD60F162198" - + "965371D7BB3D20D20FDA59FFA603DE5" - + "4C25101958E2B9709F599926168025A" - + "0F4CB96112EAC400E1B98468C21F554" - + "085AF045788DE2C37821D2AEF66DBEF" - + "59D422D3052DA80FBA4D2A09F87ECF4" - + "9B78A81A00377FE29015C522F4A2DEC" - + "3598BC791B19F1550462E4B32C46DF3" - + "014163487CE36E87975FB9D567F083C" - + "0A6A82E489642B372471EA84AB70B29" - + "74F88712DE456246977F4A58803DEED" - + "2BB75B0C5CF877A431B90C6E940193C" - + "BBEF68C29FEB41177561ECA92CD9E02" - + "B9586869B8D6B48C2ACE45B03B49F98" - + "C48A29718CA09E796F0B99E97623796" - + "50FB7A4F0802AACC199A53A0638C6F7" - + "2A48805780C176DFC89E3494108C4CA" - + "94326BC794C1E921395DF13C767D094" - + "776A68BB5511C0F1F358C3748BC54E5" - + "3638D815821C555A8D1B7AF5F405723" - + "196A90AF060DB356CE599CBE7375B39" - + "13CA7CA69B6A93DC1EB418108DD4F8E" - + "681800426212DC7AC109081FCA8C8BB" - + "1AECC4CF89D163241C41852F808EE74" - + "C4A3AD7EAF7FA8C363F55C97D8B5876" - + "A84EE9C1EA49E47313DE304ACD8B0BA" - + "2F671789B22874A907302F047A0B5B4" - + "E5C89341AC6A97E8DF62136DC4394FF" - + "C1D15909731F40BBE7E58D9C30A09A2" - + "C09D3CDA4A80F9B35340424791E97F5" - + "20C87756BE726A981A50760445CF05A" - + "40828E55ABAA0E2B2D2C6BBD1D3E756" - + "62275EC490F1BAFE518553ACC7FE538" - + "211C405DA3A06422FE157E072EBF85C" - + "731ED32CB1514D00CFA13FBB1D6F050" - + "BBE1E9E7D881C9155108215DE6D890D" - + "BFB53CB71C844BB78613422DD0BA17B" - + "E42244CD2682AC5D0C526EC8707980A" - + "76443EBE139840031A10CCE7EC1C373" - + "3ED3A8433098E1BD19A38F3EC03AAD2" - + "80B06C06097672EBC15AB8A76B9F4AB" - + "9C831081E7935D62781936BB0D8AE70" - + "A3631EB130DADCB3AEF2A485694B786" - + "B205A282616B774AF1BE4E957F658CE" - + "6DDC20DA1BC603EADF8AB0143DE4223" - + "BC4710E51623811BA820ADC2C66404D" - + "F187D8AA7D63C56C52ED8C163CC53D0" - + "47799736C7A28933D6BB1FF28998C24" - + "5745C86A8B518D515606932FEDABD36" - + "5B5545EB320FC6AEE9B20BAC023D5D0" - + "A72C97427B0E139653AEAB53993EAE3" - + "49B093F2C38F7E7CBDD221DBEEBC79D" - + "1297A64156050FF4B5EB131EC10BBBE" - + "7FA5C2BA82BC8251AB6B99299466EEF" - + "FC46EF22A4259685A82713488A51132" - + "9BEFE0523DE6AA06EC24F0D7ACA08F6" - + "BD80A4EFEED259D49DC25AD21D9681F" - + "1D8C15BA80DBEF6E0FC277AB363CD76" - + "6097799A9BD41C7A0144B24361AE8AC" - + "89FB929030B394B6C8E3AD4615577EF" - + "A31A26E2964504194A70437A1A75C0F" - + "4C5437A11AFC329131BDD1ED24564C2" - + "FB75211E8CCB2117A3B837708EC4660" - + "C121840428ACD112C9343D204E6F6D1" - + "B18262AA8449E5CA7CC8699B3154990" - + "AD4AFD41366582094D111A0C65BB0FB" - + "073434A3E8EEB1AA53D42244F7078ED" - + "CCBFD611062C743093518D839A8AE9B" - + "CFCED4801B633519865DEA86FCB12FD" - + "ECA20B3259D0D7CDD790495A286202C" - + "5D2CCD4F795A111414B0E38B3842346" - + "2A2260B9BA85CB460C3789B3667A7A8" - + "044F75AD193228933FF8144B6430581" - + "FB68DAB997F4CC8D8A96E76BAB0220D" - + "00E3C2BACDE2AB57055D598A92B3F33" - + "43AD109504C8B812C1C30C3DB68DB68" - + "2E038A84405DCA46FA40801B907D971" - + "1D813A5C83127866A1481D943FC1741" - + "761501189B7204640A065082DBFF3D5" - + "99472B9A758CE739A3ADF4FE6132AC4" - + "A5010C4BD83974D4826529CE68BA1BF" - + "885E99EBC2415ADEBE628CC1C80CC75" - + "3B3830D2B46F12264C4E14EEA833C41" - + "BA06FD521D5AFA61DAB3DC261238084" - + "86136B70ABD9828E2DE72622252353A" - + "2F5A9D93AAEF1F7612F41F3525324A9" - + "5F3624EBBB85BF4BA20EB7647654D28" - + "2C38A0CB75554B014A8609C59FC992F" - + "AE9F1E747AA4D300AEC31742E21F3E8" - + "790DF80788D7E3ECFEDB4E692D57E25" - + "ADA106B42F5F50046B48576CBC7A4A8" - + "ACFA8920540ED0265ED0BDD119BA9A0" - + "6A26C2555958ED609907B1DEC507B08" - + "A562007FC1C5471EBAC039227C1B3BE" - + "205D211EE455B3E380E2F7236A06F53" - + "20B813B7A4AE138D57E7BA152967406" - + "C1C62A6EE1FDD5B13EC0128DCFF359A" - + "30D2A224AA2EA5443DBEFCAEBF2523"; + "0107000002ED430FB68A222B10850886C54" + + "FEC4A6E8D81843EA13122CCB2C1AE2B8AC7" + + "11B34170ED4F59597F3D6B1C9DC2A7D4D89" + + "243B434A8160E65281052C8ACB84DEAD3E1" + + "347081BCDAC3D2C121CDF0F1B8265B2C9EB" + + "15CD5C0C878E8B996875102710D0423C6B3" + + "BF09A1036E815A2F15C62CC2D2111B70252" + + "061B29622E4D7C9CA72333E8A3E41402F7F" + + "400FA0EC8EA1971B6EACA094204AB00F870" + + "851AF6272A612121A66CA6D0EBBB34BDB87" + + "AA006099C461A9AC8B88ABA0C603441FFA7" + + "50463C44CD2436B087E3AACBE3E8152B439" + + "347F6DC31F3AB0936B10DFEA69A40582CD2" + + "051B749D720818E521C5BA187E2374EA39F" + + "CC199484406D045A81681322C44D80D5D6B" + + "6B0410410F83521533355C9860100D32C46" + + "1031FDE98426855108E4AAB14F019A6B042" + + "905A0D511F34852090DE36B1ED82945748E" + + "C414833BBF042D5A095D9C54E317271D212" + + "BDC1DC6588D45891EA8C86D5625202F6134" + + "7A599CA630A138212E04093102A67A55000" + + "984031EB7163110E54DA6D13786F1752829" + + "20A4A7C0C642F29A3BCB3859B6D28D5E79A" + + "FC41D6E89131BAFAE5D6CBC85ACC009B510" + + "51218043134F8B698D4FF8C922B1B782ACF" + + "E63F3CCDFB42029F462DC4877E52D46A6DB" + + "41C0CC519CD40ACA47D3088A069DB550C3F" + + "F3FA460CEEF4BE583AA825E4819093BD943" + + "69954C8258EABDCB4F090B8674495E1AB9B" + + "F42234CD733102839730D80B1884BB29E08" + + "8CF776BC6E4AABB88503FC0264140AA9C8F" + + "F868C238EE016C0FDFAFEA526416D97C674" + + "8EA0583A8684B3684637CABA7F5B2BE11D8" + + "CB7182E3D02F807EB920345264443F3120F" + + "912D36847AE48A85AB0CD9C3261F1116370" + + "72E86301D06078CC90A7224C08E2A550CA0" + + "AE588800A1CD5039800F3EA7110887C65B8" + + "9B85FB3F9448C6722930F46104CD93E6A8C" + + "2C60368AC04F20569C696BFD011FE06D204" + + "00F610D90B60FF206AD2551A8CF902F9C62" + + "5013B1014C93B151258D287C7C08F1CAB45" + + "0D5B05245ED261C874A152D99475432ACE1" + + "210AF4038834C08D53CABEDA02317809250" + + "B30701E9DFFCE10166D4031C96F181D7B9B" + + "49356A91C4DEF6DF2C0F2D6FC9271E9514B" + + "04108199D44643FAE4454BCCE09C8826DF3" + + "4240B42A62E0DC5E215C1F679797E8639DA" + + "15847E0F28A50F820588CC48C4BA4043310" + + "4213801D9DC0258BBAC042126C8E017160A" + + "796CE89E53699D428053D4F2BE6FFDAB155" + + "AA899C54E308B8901D9C2B63B9796128217" + + "1920D987A41938B2746BF4C0661B750A1F7" + + "9C5134AC857BEDB747E56CDD31D8C4B9294" + + "39EF30707F00D4C9EA02241C256005D3C29" + + "BB03FC571AEBF38C43251110143D7092A91" + + "38162880940706D91D291B1136EBF7794F4" + + "417D5029B7898C3874219400038761CE0B2" + + "A9C824962CE0D4B013AE3D444C088B7F65C" + + "B5D2384ACE4BB8C267A887120E9282D9403" + + "6BDB5052EBED88A286F69C27698E90A58E3" + + "98E3026250BF0CCC3B5E8042CA9200A4B21" + + "E02E70D0C231EF00F2B10E042336E00B8B7" + + "F62BEEAB46BC9170683217D063800DC70FB" + + "66B57F1AE81065447283DB7822A313CBB87" + + "C9A221A1558D5293F77EFB4C1813A977AA1" + + "EDCB8035050C2E5E73AF8260BA7F5A33A85" + + "9B81FC04CA2051C19D1020599613217EB8B" + + "62A20808E6C5361C5147E434E624859F610" + + "CE7E08F05933F94389CA00E58033283C2BF" + + "6403A246EC2B5668F06DA3A065668D2BFCB" + + "1FC80565382916708F46B025805DAE62B1E" + + "150A3E33D66BA4F6F202E92C852A44A6F60" + + "2D70258BBF8468DDBE2E0E8D41D8AEFAD83" + + "2364DC68AD9279CB854DD389A051210B05A" + + "AB6CC85FA4E14E05EA81FE9C6936026A2CB" + + "98A7508881F1D9725CE3D45445E69D9B60C" + + "20B89490144A27A28818B8DDD068A84BD70" + + "555AFEE4A1861DCB1166E813F689745A590" + + "AC7DC27093800ECAB801AC35C9033EF1E36" + + "730D18B1929400F59D3218D0A23252D924B" + + "54AA1C0A934B7EF575ECCAF434D2931A049" + + "0AA50195566981B0201935048A6B1BC7894" + + "B5553A4989E0EF43A744F4D7988D3AD1D6A" + + "14AE34B91820486FC598AA0DCEE5A81AB69" + + "511FF792929B0A44BAC70AC0691A8318140" + + "9C0EECF9E9CE12009806AD0854408C974A0" + + "8273FB817BB4C0405A2F6284D6C141EBE24" + + "D62652275C12C3EC16261BAFEBE14C547BF" + + "0C682BA901C1860560A0D501380BED06102" + + "A599F0C9504B1A3E51206C9C6A68AE9A7C1" + + "91010F606EA484957934A7EFE9A0C8750B8" + + "B60646C154A31139ECD873E6D81DD66E724" + + "040AD402015115CB91689207A56D4A63341" + + "38E46EC16E7E1F8BC818F4210B2AE312438" + + "0023E8C1A7DEA311F970BCF0AE0E3113F07" + + "6FB0F32605614CD4C1BA9E01BEC3AC6CBC9" + + "C902B4840C4113D93B10E8B44C58A7CAA41" + + "8048639110835C9BCD23565C783D1B521E1" + + "88EC2C07091AB2D7E9F934C80A8672D7F20" + + "D216EC38ACDD28FF93BE9F27615C3414250" + + "30D7EA9019A024DB5AD84A880FD15A9998C" + + "679032F08C59035C44C05AE152C68E20D68" + + "9EE31D0F38C0D2A3B0251DA001C999B2638" + + "263005FF8517186E5CB4CB13433F137CAB3" + + "84C55D87D11327848D56C033C820A8C44C5" + + "54B214B6E6D42E122C2CD1E3047EA130036" + + "91411EB1879C34A86E200BD02657A38CF8F" + + "A355A52C0701133DAEC6D259CC708ECC042" + + "8B0DA3B1A84EF5C4C58EB47D93B23DA609A" + + "D81E3521A679086612B45B3F1E1540A5225" + + "1F209254F833815900D00E6A25C9BB74820" + + "43DC305C65DF58C41268060D6F0AC8791B8" + + "61332C4A624587D929021009D65003188AC" + + "87C1C8A02CA65171462E1D43229D10E9EDD" + + "40319623E24AE71B1B551132327CCE3A8E2" + + "234A95C360D433D9E433B997005F2A03580" + + "A42E9923D6B79982252753745E49908EE84" + + "E2AAD69FBDA207292505EEF31E7102BDCA0" + + "37FF4AD4BDA92F89254007FF4AAB9165704" + + "EDFD2CBA51E2F484E5AF501768D48969B0A" + + "A8C12CD39F37F889017D003F0A7EA5D9029" + + "D60905CC34042C5F14882A863874826131D" + + "9EC26EFCB2CA920840C1CFD9350492511F3" + + "A3E019EB248E5F44CF45CC6936CA5252DAD" + + "1C8E138327B33C891D130D06101D0701A0E" + + "B1B1C914271F030220B7FFC2BFAF39DB942" + + "1BE8942129E5D0DB7467E7DD75AC922E3EB" + + "F3C61200C1840C695274313254B60CA51CD" + + "6B42A470B288B34180CC138BEC4C211682E" + + "13D0700366CA94186567D3892E1D630FE16" + + "3278CD0E766ABFBC080326AAAFB25CE8117" + + "9D564C02DB8548435F94A3002734CB034D1" + + "031A8345D28D1C278C5B4E6537F721F97EA" + + "246948B906A1F26424CE8460418492268AA" + + "CD83AC4731D08E889AD140D98406DC0413D" + + "D4A8A113812330F0A0838C64D5CF054C08F" + + "6FD438A5028AAA1F350884E24AC428E30D1" + + "B68A2AE577D7DC1C7032ABAFB14A4E2166D" + + "38AB0A63198D805798B1E2C89F9A108E5B8" + + "3A8477790642C0E21CE64DFF35A11F76582" + + "019100F10A8BEEF14F45A934870452F761A" + + "6C1C9FDAA468500B13AE2A66D89CA6CF43D" + + "751D63C5B6A0E0E72258324CE8A151D7D10" + + "E625088765C2B16A0B8C82A7E5E29993224" + + "9C1712402C1940ED4260DF158E4120A0EB0" + + "1945004B549EB48D1608349D84EA510024B" + + "30E8E26E07D7342ED3E01000F43B8605060" + + "7ABA83B7228D809D201CA62CCAB0DF8DA56" + + "A5AE0409D0C4037FBA5AA5B7755095009E2" + + "BC5B9B4696E6DDA14A0F9BBFC55C44E68E8" + + "E0E41D0658A2C32C0CB8080059245197134" + + "C2B354EA4CD38C456AD0330C03698D58A74" + + "B88886318FC1CA8F40263882A83DADE17B7" + + "3104489FB0743298EE3640978DAE143801A" + + "F3AC66D804A5D43CD0336474B0B2713B04B" + + "8A910CD666057C20DA48EA4E7AC2180566E" + + "44D452B947ED185B1D1A81B73EE95AE469E" + + "2F924DA3061132024898F6D51487D550A18" + + "90AB6CE02841C20A018AE769AB4471C05A2" + + "298551CDEB1810E6D95245C19BE8D10340B" + + "3208C6D4C5F6285532C3520D8358AED57CC" + + "27A122A770C08AA8C4CB0B8A5D3ABFCB6D0" + + "F1F7D5AF25230019D21D7BF2B66578E686F" + + "8622C762D2A5E1E00651F3B18C6272E08B9" + + "87B906ECAAB2A7A1B5C5095812BF7D458A8" + + "4BA46A1DA1D686AF1A4241D1112BAE42906" + + "C6FBF47455E7817B48A35B1281AEBC631CD" + + "C90101F94042C2F728BD70F26CFA5730D3D" + + "44E85625A8A40BA000953860532C4F9ED85" + + "F181A84106C0708302E2B1B206D5184356B" + + "7223AB7D8D5368C1714A55D1A21F204621C" + + "399DB1FD90A40CA0E052C6721016C44A286" + + "AD4EA381F2C7A66591C927E853E7F7C4EA3" + + "DB95E0E985B3A530C83F923FF13E4968F86" + + "87191028F92CE213B1D0F7015E6F2BDDC08" + + "0F63E3022759E32FE5104A95CB4CBC418F3" + + "B565D616AB8743C29EF5BB550B7794A1C96" + + "A96588482405440B231AFEE4444F5970A9B" + + "AC96B2A31F2E3AE968B4E0590385C7C0B5B" + + "EC8DC44B8D05714C83BCB9D4C500351AC74" + + "941B7C11956789711B8EB522902604A8CA1" + + "179141F286BAE8F677580071B86C42C898D" + + "7B0A186DD5E28C6FF608013098D0F0BA1E5" + + "EC62E034CB1B072A3B374809A702651D942" + + "114244791B1D2E5FA9E300E62485A3A3E30" + + "E0F560C2720C7B66C33CB878DACE0075078" + + "15012A1A44D0B12159DAA84CDADB74D1708" + + "0416279C5B807CA091973237E3563107201" + + "F5E6839E17901C51410C0CD1CD622BDD368" + + "4AC9904BFACC534A7E0C1A0458DE01B61A3" + + "681EE3100AC484DB648429B6824D7CAA65E" + + "262DE81562001E91B5219C6097F21472913" + + "93EE8D85CDB11A220552C3F449B4288F189" + + "2C47BCD944F0F9B29209EDA926848AC5B26" + + "C8C1D6FFB217469A028D87C4077E60A1F14" + + "318897F09213411637D06046BCEA8632D54" + + "3882C33BD526DC49078D09A4CB42B9775C2" + + "1593177B2E14C62AA9CF5FA586F2393E102" + + "55CE104511638AC9D1B20040C0463DAB53B" + + "F24211001184B59E91DB35D2D441CCF1788" + + "106F35D7252DFDDED10F268690442133349" + + "E51CD0E841174EA2251B5A4ACAD98CCB799" + + "F4EDCBA1AE1EB89969486BB69E2A616AB50" + + "2D3D2502CE50C9C4178D0053D40355637D8" + + "E396E52EE08A5C9638479518DB841F2F8A2" + + "628F5666BF92B15943580B76380D1458FF0" + + "0805CB004D8B764F3C32A3ADD8BEF2C2004" + + "518E3A65C29CCDD9044957D3144B04B7E94" + + "20D12387AC31E2B34F6469E408C2705C5D2" + + "E09D4D5102FC159D5A14B616279B6523BF3" + + "658DC25B9034086309210FAD465EA3D04F0" + + "2A0FB66EA012C41977819006550A9FE0A97" + + "81A0856CD52161D4AD4AA8529D102B94098" + + "EB23431829448F0085948922BC4249C1E28" + + "CDA9AFB811130A5AA3920122152E40031ED" + + "6BBEF0BF844390938E1446FC92617029922" + + "D8F4183E236F9A90A2823CC93BF0CEC2CC0" + + "E1632545C8826894913A823104785E23F03" + + "88BB3D8AC4D660008F7CB4D6A2FB47161B2" + + "223F32857568BD12E0D5827B6C2C73B0860" + + "442A996812BB0D348D64599F6948087D521" + + "63FB0A0F40D7C9E3592BFDCD757F5813E31" + + "3AE469B10A39BC09305CE43AD6DA1B83AEC" + + "75DEBD0B140D25522D72648048549A7E1A8" + + "8E160C611C0A293C010351280D3F543259A" + + "3B7DB10EC4648F2123EA51CCFB4095784A0" + + "C3BB0D1605C3629150A049022A111643BCC" + + "3003C94994B068448FE9B27040DD2057B78" + + "551639838674F9930974A90F10702E02BE4" + + "9384E853FA120E2287B6887DD09060778C0" + + "892C3916633FEBB145411982CB0984C849B" + + "E94AAABC539EFD863CD1201D082D4402181" + + "37DD4D7A44C2C37EA854195CA15ECFB98CB" + + "2811539846B5C836EDFE48D2632F2782948" + + "90C953882F1B23DD5F2BCA622693494CC70" + + "9094330A5CE3478D8C008740DA172E60ED1" + + "DC8C03523BBC1456844D43DC51B2FE5564C" + + "C91300EC1FF304A53A6B5C0A341ED555968" + + "BFF1FB24081EB87A55F392013384EB5D62A" + + "75AAE6A21CCE0661B4A94B0441087C2B524" + + "811A47669101A8F0816064C02204B608176" + + "61F637487BBC592300F7804DCD1891F903C" + + "F42352BD8A7D3B2B98041E8196011044AA8" + + "D6489CA7825DCD1ABF5567E9BA28A5963D6" + + "0462BC40D16E80A2FCD6D1A8FAA24C9EF80" + + "97F1874453DEE373D94902A1FE608537C11" + + "71A7ED0383B3FF4271255A7D91D3826E696" + + "78FE6D9D1744861756D0E78A1AE051009C6" + + "9A98BAB05C10EF52CC26741F4228683EDB2" + + "FDA694D4247CA9B6B0F091E077C00F8A9D1" + + "3AF90A8534099ADE9603527B82449965ED1" + + "3D14C8BE9CB8D323F20D417240304867230" + + "CABFD9BE036C1097507B0CAFD2D6F3483B1" + + "AE98E429642C68034094803A0CF8940BC20" + + "6019CB7D87A6CECCCC82E01805A9F84A730" + + "0F8B4C531614DAFD380B2B1A068A5B0B82E" + + "4A6C8344A7C90E124039D68F1231C812137" + + "155FB3422CB8DEA7DFAE701D34782412131" + + "CE3A8501E119923349025B0F18792112EA8" + + "520E9A7C160C007194C81BD365B28F6AC36" + + "887D0C0D6059D949D532D10D2F080FFE052" + + "E01F95ECD51B78A80A983357F2B005E5238" + + "C80588758DF87A1758A161152440D30B655" + + "B30561CB503EE96E0507DFB4D527D583C1A" + + "C892A689716A242511EA04AA20321747286" + + "12C3D766D69303E8F888395EC4BD3530D4C" + + "F87FB421BB2848948590CB3EFE0E29E6F51" + + "5335618CC91CD8C20FB42EC6DECDAB08C3B" + + "CE47302A49FD044CE236BA428846B610C1B" + + "A77442796906F5A22002AAAC8BE5AD60060" + + "CC6B32A4B945B94CDCEFAC8902595268020" + + "B19326A878089E9811DDCB17C665F094677" + + "B60FF7415F4E77A188F7A8AC44652030DB1" + + "5571C45488F133AF3F604B207D3F5CAF044" + + "19016D60194BBB311A3B01E278A41B289BD" + + "B3E94481209D0E8A4828604228C6DA7AC10" + + "9001D8A8010A08ECC2C7BBB731243141822" + + "B100E67C8433A578B7F7888123B47C12706" + + "7E52FAC6E8C1EC59A47799DC044A8DBD09B" + + "2B671581A02865A9063025A44A0B464A4D2" + + "82611438D52AED601375CCB946F80500901" + + "730D4098F6E5859812BC9D28499BCDE4A00" + + "51130306428751C06E426EC77573CE27A98" + + "0930624C01CF11A40809C10ABA90A230B24" + + "6A3B1D3A1522326DEC5B1172AFCD70541AD" + + "4DBE51C215D4045A7212070BE167E0766EB" + + "C4C7BBE832CB940CD80CB0567B81E670400" + + "C858D7798A9081C11C866D5E68894996B17" + + "DA6388450B6B629668E14B2379F5A244CD2" + + "2828E500814E6C8107981F7F213E2A13BC4" + + "8231B90EEA2E81C1716CC30C4338CAC0FC8" + + "B63AE5E58BA2F190A0F40449F638EBE94A1" + + "9836A8F48B968020E8C7955546592134B92" + + "D02F723173BD9422F2DC80A8F00405FA216" + + "86B22CA290614B7F4AF13A4E15634F8EF6D" + + "7D2270898202CAC10B801414A40323C4430" + + "7F0633895BA826BF468A641E1758328887D" + + "33456402AD8C1688C539044B90534C9308F" + + "27963B0FE389A0526577180F22B49852156" + + "86E3B6FD8899632D501E9700F8E2F61B218" + + "24023D4F0B6AC85FA7F0A131443AAAF5381" + + "3E0B2013013F1E8AB763991D2255BEA9C7B" + + "5039E80355605C6F017E8500A9F082B65DA" + + "523EB8B9CE6D3226B9128D54AAEB7D94FE4" + + "3A425D780C873166282521360BCFF242BEC" + + "28A02D432E0D724808F6B50281EBAC66589" + + "4080252D20D84A5F1140150A829BEEFE8B8" + + "0166B1268C26E195F09E9B5494300505720" + + "A658D8AA29FB8290609394B4A2AAA546114" + + "7229B306B660D65000394D44434A3A2EB4F" + + "4EE337E18ABCB25133A9D36D24565423D75" + + "29868CCB3317E7B8076086442C04435840E" + + "A88C530249313D474FE72D9E18262AA0408" + + "F5027C4861917054892ADE96DCB2A09C309" + + "E9111E08652B0FBA7A124A0ADAC93BA53D6" + + "0140959308BC5BFF014004237A41F7107AB" + + "818BF92C3CDD0CC1B63A188970CB88EE4B1" + + "0DD28408F3218C0D7CDCDD1481B28781AC5" + + "D288D5F799231D458F8438978023DE0EC22" + + "898BA425A248437C9B026587A6A487C33D1" + + "8A0B1117DB814487172D01BDEB4CBB97F0C" + + "885925AF38BEB8222100F3C2235DF26757E" + + "4FD981292B3D0333A5509515C8BA06D1C24" + + "42FA69DA402E608A8050398646FA04801BC" + + "87C8201D80185F0B3370E620484CB6BF745" + + "456714211909420CD41C0B50925F9D3D399" + + "638B9F358EEE09A38D64F92112AC4A01948" + + "53C8217DF0902519C36CBA9BD0C4819CECA" + + "430B92A0228100440CC253B7B36E0A407B1" + + "668C0C96E6E5A2821B302E9767E44DA3140" + + "F1DC3412088840EA86668E3A1862E3DE767" + + "682723393255A9E9BA8EF13661A753F3525" + + "136A05B1E34CFBA80BF4A8009B5747E54C0" + + "04038A0FF7115FA05DBC681D68DCC82EA69" + + "55CB67A24C100A04294C0C25B1005014380" + + "707D7C3ECE4936C492542A27A02D26BC137" + + "E119C29485C6F987B2C8A5B89B32540E502" + + "64850B5F118F0AA0C80283745108B128990" + + "AD15EB547B08A66623FB01C582FEB200390" + + "2DC3538AA80F2517EC7CB2A3A0E297296B0" + + "625760991AA3B6A6938C4FB6BC752326486" + + "C5E62A6AE1DD55B03E60029D93E3DD82080" + + "8664AA2E85443DDEA0BE052426"; public static byte[] hexStringToByteArray(String s) { int len = s.length(); diff --git a/android/app/src/com/android/bluetooth/btservice/JniCallbacks.java b/android/app/src/com/android/bluetooth/btservice/JniCallbacks.java index e81d23d7f2..f8904bd6d4 100644 --- a/android/app/src/com/android/bluetooth/btservice/JniCallbacks.java +++ b/android/app/src/com/android/bluetooth/btservice/JniCallbacks.java @@ -48,8 +48,8 @@ class JniCallbacks { throw new CloneNotSupportedException(); } - void sspRequestCallback(byte[] address, byte[] name, int cod, int pairingVariant, int passkey) { - mBondStateMachine.sspRequestCallback(address, name, cod, pairingVariant, passkey); + void sspRequestCallback(byte[] address, int pairingVariant, int passkey) { + mBondStateMachine.sspRequestCallback(address, pairingVariant, passkey); } void devicePropertyChangedCallback(byte[] address, int[] types, byte[][] val) { diff --git a/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java b/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java index 32d8e51b10..5a0df36d6a 100644 --- a/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java +++ b/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java @@ -57,7 +57,7 @@ import java.util.List; public class MetricsLogger { private static final String TAG = "BluetoothMetricsLogger"; private static final String BLOOMFILTER_PATH = "/data/misc/bluetooth"; - private static final String BLOOMFILTER_FILE = "/devices_for_metrics_v2"; + private static final String BLOOMFILTER_FILE = "/devices_for_metrics_v3"; public static final String BLOOMFILTER_FULL_PATH = BLOOMFILTER_PATH + BLOOMFILTER_FILE; // 6 hours timeout for counter metrics diff --git a/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java b/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java index 0ef0cea22a..fd94f967ae 100644 --- a/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java +++ b/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java @@ -485,6 +485,7 @@ public class RemoteDevices { /** * @param deviceType the mDeviceType to set */ + @VisibleForTesting void setDeviceType(int deviceType) { synchronized (mObject) { this.mDeviceType = deviceType; 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 4eeb513324..2fe84e633d 100644 --- a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java @@ -1042,7 +1042,10 @@ public class LeAudioService extends ProfileService { TAG, "createBroadcast reached maximum allowed broadcasts number: " + getMaximumNumberOfBroadcasts()); - notifyBroadcastStartFailed(BluetoothStatusCodes.ERROR_LOCAL_NOT_ENOUGH_RESOURCES); + mHandler.post( + () -> + notifyBroadcastStartFailed( + BluetoothStatusCodes.ERROR_LOCAL_NOT_ENOUGH_RESOURCES)); return; } @@ -1172,8 +1175,11 @@ public class LeAudioService extends ProfileService { LeAudioBroadcastDescriptor descriptor = mBroadcastDescriptors.get(broadcastId); if (descriptor == null) { - notifyBroadcastUpdateFailed( - broadcastId, BluetoothStatusCodes.ERROR_LE_BROADCAST_INVALID_BROADCAST_ID); + mHandler.post( + () -> + notifyBroadcastUpdateFailed( + broadcastId, + BluetoothStatusCodes.ERROR_LE_BROADCAST_INVALID_BROADCAST_ID)); Log.e(TAG, "updateBroadcast: No valid descriptor for broadcastId: " + broadcastId); return; } @@ -1243,8 +1249,10 @@ public class LeAudioService extends ProfileService { LeAudioBroadcastDescriptor descriptor = mBroadcastDescriptors.get(broadcastId); if (descriptor == null) { - notifyOnBroadcastStopFailed( - BluetoothStatusCodes.ERROR_LE_BROADCAST_INVALID_BROADCAST_ID); + mHandler.post( + () -> + notifyOnBroadcastStopFailed( + BluetoothStatusCodes.ERROR_LE_BROADCAST_INVALID_BROADCAST_ID)); Log.e(TAG, "stopBroadcast: No valid descriptor for broadcastId: " + broadcastId); return; } @@ -1265,8 +1273,10 @@ public class LeAudioService extends ProfileService { LeAudioBroadcastDescriptor descriptor = mBroadcastDescriptors.get(broadcastId); if (descriptor == null) { - notifyOnBroadcastStopFailed( - BluetoothStatusCodes.ERROR_LE_BROADCAST_INVALID_BROADCAST_ID); + mHandler.post( + () -> + notifyOnBroadcastStopFailed( + BluetoothStatusCodes.ERROR_LE_BROADCAST_INVALID_BROADCAST_ID)); Log.e(TAG, "destroyBroadcast: No valid descriptor for broadcastId: " + broadcastId); return; } @@ -2376,7 +2386,10 @@ public class LeAudioService extends ProfileService { } if (descriptor.isActive()) { - notifyGroupStatusChanged(groupId, LeAudioStackEvent.GROUP_STATUS_ACTIVE); + mHandler.post( + () -> + notifyGroupStatusChanged( + groupId, LeAudioStackEvent.GROUP_STATUS_ACTIVE)); updateInbandRingtoneForTheGroup(groupId); } } finally { @@ -2430,7 +2443,10 @@ public class LeAudioService extends ProfileService { Log.d(TAG, "Clear for group: " + groupId); descriptor.mHasFallbackDeviceWhenGettingInactive = false; clearLostDevicesWhileStreaming(descriptor); - notifyGroupStatusChanged(groupId, LeAudioStackEvent.GROUP_STATUS_INACTIVE); + mHandler.post( + () -> + notifyGroupStatusChanged( + groupId, LeAudioStackEvent.GROUP_STATUS_INACTIVE)); updateInbandRingtoneForTheGroup(groupId); } finally { mGroupReadLock.unlock(); @@ -2916,7 +2932,7 @@ public class LeAudioService extends ProfileService { } descriptor.mCodecStatus = status; - notifyUnicastCodecConfigChanged(groupId, status); + mHandler.post(() -> notifyUnicastCodecConfigChanged(groupId, status)); if (descriptor.isActive()) { // Audio framework needs to be notified so it get new codec config @@ -2940,8 +2956,11 @@ public class LeAudioService extends ProfileService { } if (descriptor.isInactive()) { - notifyGroupStatusChanged( - groupId, BluetoothLeAudio.GROUP_STATUS_INACTIVE); + mHandler.post( + () -> + notifyGroupStatusChanged( + groupId, + BluetoothLeAudio.GROUP_STATUS_INACTIVE)); } } boolean availableContextChanged = @@ -3077,7 +3096,11 @@ public class LeAudioService extends ProfileService { if (success) { Log.d(TAG, "Broadcast broadcastId: " + broadcastId + " created."); mBroadcastDescriptors.put(broadcastId, new LeAudioBroadcastDescriptor()); - notifyBroadcastStarted(broadcastId, BluetoothStatusCodes.REASON_LOCAL_APP_REQUEST); + mHandler.post( + () -> + notifyBroadcastStarted( + broadcastId, + BluetoothStatusCodes.REASON_LOCAL_APP_REQUEST)); // Start sending the actual stream startBroadcast(broadcastId); @@ -3097,7 +3120,7 @@ public class LeAudioService extends ProfileService { updateBroadcastActiveDevice(null, mActiveBroadcastAudioDevice, false); } - notifyBroadcastStartFailed(BluetoothStatusCodes.ERROR_UNKNOWN); + mHandler.post(() -> notifyBroadcastStartFailed(BluetoothStatusCodes.ERROR_UNKNOWN)); } mAwaitingBroadcastCreateResponse = false; @@ -3121,7 +3144,10 @@ public class LeAudioService extends ProfileService { } // TODO: Improve reason reporting or extend the native stack event with reason code - notifyOnBroadcastStopped(broadcastId, BluetoothStatusCodes.REASON_LOCAL_APP_REQUEST); + mHandler.post( + () -> + notifyOnBroadcastStopped( + broadcastId, BluetoothStatusCodes.REASON_LOCAL_APP_REQUEST)); BassClientService bassClientService = getBassClientService(); if (bassClientService != null) { bassClientService.stopReceiversSourceSynchronization(broadcastId); @@ -3152,8 +3178,11 @@ public class LeAudioService extends ProfileService { Log.d(TAG, "Broadcast broadcastId: " + broadcastId + " stopped."); // Playback stopped - notifyPlaybackStopped(broadcastId, - BluetoothStatusCodes.REASON_LOCAL_APP_REQUEST); + mHandler.post( + () -> + notifyPlaybackStopped( + broadcastId, + BluetoothStatusCodes.REASON_LOCAL_APP_REQUEST)); transitionFromBroadcastToUnicast(); destroyBroadcast(broadcastId); @@ -3170,8 +3199,11 @@ public class LeAudioService extends ProfileService { } // Playback paused - notifyPlaybackStopped(broadcastId, - BluetoothStatusCodes.REASON_LOCAL_STACK_REQUEST); + mHandler.post( + () -> + notifyPlaybackStopped( + broadcastId, + BluetoothStatusCodes.REASON_LOCAL_STACK_REQUEST)); if (!Flags.leaudioBroadcastAssistantPeripheralEntrustment()) { if (bassClientService != null) { @@ -3188,8 +3220,11 @@ public class LeAudioService extends ProfileService { Log.d(TAG, "Broadcast broadcastId: " + broadcastId + " streaming."); // Stream resumed - notifyPlaybackStarted(broadcastId, - BluetoothStatusCodes.REASON_LOCAL_STACK_REQUEST); + mHandler.post( + () -> + notifyPlaybackStarted( + broadcastId, + BluetoothStatusCodes.REASON_LOCAL_STACK_REQUEST)); clearBroadcastTimeoutCallback(); @@ -3233,7 +3268,10 @@ public class LeAudioService extends ProfileService { return; } descriptor.mMetadata = stackEvent.broadcastMetadata; - notifyBroadcastMetadataChanged(broadcastId, stackEvent.broadcastMetadata); + mHandler.post( + () -> + notifyBroadcastMetadataChanged( + broadcastId, stackEvent.broadcastMetadata)); } } else if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_NATIVE_INITIALIZED) { mLeAudioNativeIsInitialized = true; @@ -3249,7 +3287,10 @@ public class LeAudioService extends ProfileService { } else if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_UNICAST_MONITOR_MODE_STATUS) { handleUnicastStreamStatusChange(stackEvent.valueInt1, stackEvent.valueInt2); } else if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_GROUP_STREAM_STATUS_CHANGED) { - notifyGroupStreamStatusChanged(stackEvent.valueInt1, stackEvent.valueInt2); + mHandler.post( + () -> + notifyGroupStreamStatusChanged( + stackEvent.valueInt1, stackEvent.valueInt2)); } } @@ -4085,7 +4126,7 @@ public class LeAudioService extends ProfileService { } deviceDescriptor.mGroupId = groupId; - notifyGroupNodeAdded(device, groupId); + mHandler.post(() -> notifyGroupNodeAdded(device, groupId)); } finally { mGroupWriteLock.unlock(); } @@ -4165,7 +4206,7 @@ public class LeAudioService extends ProfileService { updateFallbackUnicastGroupIdForBroadcast(LE_AUDIO_GROUP_ID_INVALID); } } - notifyGroupNodeRemoved(device, groupId); + mHandler.post(() -> notifyGroupNodeRemoved(device, groupId)); } finally { mGroupReadLock.unlock(); } @@ -4314,7 +4355,8 @@ public class LeAudioService extends ProfileService { int n = mBroadcastCallbacks.beginBroadcast(); for (int i = 0; i < n; i++) { try { - mBroadcastCallbacks.getBroadcastItem(i) + mBroadcastCallbacks + .getBroadcastItem(i) .onBroadcastUpdateFailed(reason, broadcastId); } catch (RemoteException e) { continue; @@ -4330,7 +4372,8 @@ public class LeAudioService extends ProfileService { int n = mBroadcastCallbacks.beginBroadcast(); for (int i = 0; i < n; i++) { try { - mBroadcastCallbacks.getBroadcastItem(i) + mBroadcastCallbacks + .getBroadcastItem(i) .onBroadcastMetadataChanged(broadcastId, metadata); } catch (RemoteException e) { continue; @@ -4559,7 +4602,7 @@ public class LeAudioService extends ProfileService { updateBroadcastActiveDevice(null, mActiveBroadcastAudioDevice, false); } - notifyBroadcastStartFailed(BluetoothStatusCodes.ERROR_TIMEOUT); + mHandler.post(() -> notifyBroadcastStartFailed(BluetoothStatusCodes.ERROR_TIMEOUT)); } } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BaseDataTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BaseDataTest.java index 13f81f3597..2a65124dee 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BaseDataTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BaseDataTest.java @@ -20,6 +20,10 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; +import com.google.common.primitives.Bytes; + +import java.util.Random; + import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -114,4 +118,78 @@ public class BaseDataTest { assertThat(level.index).isEqualTo(4); assertThat(level.codecConfigLength).isEqualTo(3); } + + @Test + public void parseBaseData_longMetaData() { + assertThrows(IllegalArgumentException.class, () -> BaseData.parseBaseData(null)); + + int metaDataLength = 142; + + byte[] serviceDataLevel1 = + new byte[] { + // LEVEL 1 + (byte) 0x01, + (byte) 0x02, + (byte) 0x03, // presentationDelay + (byte) 0x01 // numSubGroups + }; + + byte[] serviceDataLevel2 = + new byte[] { + // LEVEL 2 + (byte) 0x01, // numSubGroups + (byte) 0x00, + (byte) 0x00, + (byte) 0x00, + (byte) 0x00, + (byte) 0x00, // UNKNOWN_CODEC + (byte) 0x02, // codecConfigLength + (byte) 0x01, + (byte) 'A', // codecConfigInfo + (byte) metaDataLength, // metaDataLength 142 + }; + + byte[] metadataHeader = + new byte[] { + (byte) (metaDataLength - 1), // length 141 + (byte) 0xFF + }; + + byte[] metadataPayload = new byte[140]; + new Random().nextBytes(metadataPayload); + + byte[] serviceDataLevel3 = + new byte[] { + // LEVEL 3 + (byte) 0x04, // index + (byte) 0x03, // codecConfigLength + (byte) 0x02, + (byte) 'B', + (byte) 'C' // codecConfigInfo + }; + + BaseData data = + BaseData.parseBaseData( + Bytes.concat( + serviceDataLevel1, + Bytes.concat(serviceDataLevel2, metadataHeader, metadataPayload), + serviceDataLevel3)); + BaseData.BaseInformation level = data.getLevelOne(); + assertThat(level.presentationDelay).isEqualTo(new byte[] {0x01, 0x02, 0x03}); + assertThat(level.numSubGroups).isEqualTo(1); + + assertThat(data.getLevelTwo().size()).isEqualTo(1); + level = data.getLevelTwo().get(0); + + assertThat(level.numSubGroups).isEqualTo(1); + assertThat(level.codecId).isEqualTo(new byte[] {0x00, 0x00, 0x00, 0x00, 0x00}); + assertThat(level.codecConfigLength).isEqualTo(2); + assertThat(level.metaDataLength).isEqualTo(metaDataLength); + assertThat(level.metaData).isEqualTo(Bytes.concat(metadataHeader, metadataPayload)); + + assertThat(data.getLevelThree().size()).isEqualTo(1); + level = data.getLevelThree().get(0); + assertThat(level.index).isEqualTo(4); + assertThat(level.codecConfigLength).isEqualTo(3); + } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java index 9b47a1095a..ab5b0c33b9 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java @@ -94,6 +94,8 @@ import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.flags.Flags; +import com.google.common.primitives.Bytes; + import org.hamcrest.core.IsInstanceOf; import org.junit.After; import org.junit.Assert; @@ -111,6 +113,7 @@ import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Random; import java.util.UUID; @MediumTest @@ -1518,6 +1521,86 @@ public class BassClientStateMachineTest { } @Test + public void receiveSinkReceiveState_inConnectedState() { + initToConnectedState(); + mBassClientStateMachine.connectGatt(true); + mBassClientStateMachine.mNumOfBroadcastReceiverStates = 2; + BassClientService.Callbacks callbacks = Mockito.mock(BassClientService.Callbacks.class); + when(mBassClientService.getCallbacks()).thenReturn(callbacks); + + // Prepare mBluetoothLeBroadcastReceiveStates with metadata for test + int sourceId = 1; + int metaDataLength = 142; + byte[] value = + new byte[] { + (byte) sourceId, // sourceId + (byte) (mSourceTestDevice.getAddressType() & 0xFF), // sourceAddressType + Utils.getByteAddress(mSourceTestDevice)[5], + Utils.getByteAddress(mSourceTestDevice)[4], + Utils.getByteAddress(mSourceTestDevice)[3], + Utils.getByteAddress(mSourceTestDevice)[2], + Utils.getByteAddress(mSourceTestDevice)[1], + Utils.getByteAddress(mSourceTestDevice)[0], // sourceAddress + 0x00, // sourceAdvSid + 0x00, + 0x00, + 0x00, // broadcastIdBytes + (byte) BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_IDLE, + (byte) BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_CODE_REQUIRED, + // no badBroadcastCode + 0x01, // numSubGroups 1 + 0x00, + 0x00, + 0x00, + 0x00, // audioSyncIndex + (byte) metaDataLength, // metaDataLength + }; + + byte[] metadataHeader = + new byte[] { + (byte) (metaDataLength - 1), // length 141 + (byte) 0xFF + }; + + byte[] metadataPayload = new byte[140]; + new Random().nextBytes(metadataPayload); + + BluetoothGattCharacteristic characteristic = + Mockito.mock(BluetoothGattCharacteristic.class); + when(characteristic.getValue()) + .thenReturn(Bytes.concat(value, metadataHeader, metadataPayload)); + when(characteristic.getInstanceId()).thenReturn(sourceId); + when(characteristic.getUuid()).thenReturn(BassConstants.BASS_BCAST_RECEIVER_STATE); + + mBassClientStateMachine.mGattCallback.onCharacteristicRead( + null, characteristic, GATT_SUCCESS); + TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + + assertThat(mBassClientStateMachine.getAllSources().size()).isEqualTo(1); + BluetoothLeBroadcastReceiveState recvState = mBassClientStateMachine.getAllSources().get(0); + + assertThat(recvState.getSourceId()).isEqualTo(sourceId); + assertThat(recvState.getSourceAddressType()).isEqualTo(mSourceTestDevice.getAddressType()); + assertThat(recvState.getSourceDevice()).isEqualTo(mSourceTestDevice); + assertThat(recvState.getSourceAdvertisingSid()).isEqualTo(0x00); + assertThat(recvState.getBroadcastId()).isEqualTo(0x00); + assertThat(recvState.getPaSyncState()) + .isEqualTo(BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_IDLE); + assertThat(recvState.getBigEncryptionState()) + .isEqualTo(BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_CODE_REQUIRED); + assertThat(recvState.getNumSubgroups()).isEqualTo(1); + + assertThat(recvState.getBisSyncState().size()).isEqualTo(1); + assertThat(recvState.getBisSyncState().get(0)).isEqualTo(0x00); + + assertThat(recvState.getSubgroupMetadata().size()).isEqualTo(1); + BluetoothLeAudioContentMetadata metaData = recvState.getSubgroupMetadata().get(0); + assertThat(metaData.getRawMetadata().length).isEqualTo(metaDataLength); + assertThat(metaData.getRawMetadata()) + .isEqualTo(Bytes.concat(metadataHeader, metadataPayload)); + } + + @Test public void sendRemoveBcastSourceMessage_inConnectedState() { initToConnectedState(); BassClientService.Callbacks callbacks = Mockito.mock(BassClientService.Callbacks.class); diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/PublicBroadcastDataTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/PublicBroadcastDataTest.java index 30fe842842..7ff4f38854 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/PublicBroadcastDataTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/PublicBroadcastDataTest.java @@ -20,6 +20,10 @@ import static com.google.common.truth.Truth.assertThat; import android.bluetooth.BluetoothLeBroadcastMetadata; +import com.google.common.primitives.Bytes; + +import java.util.Random; + import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -81,4 +85,60 @@ public class PublicBroadcastDataTest { assertThat(dataNoMetaData.getMetadataLength()).isEqualTo(0); assertThat(dataNoMetaData.getMetadata()).isEqualTo(new byte[] {}); } + + @Test + public void parsePublicBroadcastData_longMetaData() { + assertThat(PublicBroadcastData.parsePublicBroadcastData(null)).isNull(); + + int metaDataLength = 142; + byte[] serviceDataInvalid = + new byte[] { + (byte) 0x02, // features, non-encrypted, standard quality prsent + }; + assertThat(PublicBroadcastData.parsePublicBroadcastData(serviceDataInvalid)).isNull(); + + byte[] serviceDataInvalid2 = + new byte[] { + (byte) 0x02, // features, non-encrypted, standard quality prsent + (byte) 0x03, // metaDataLength + (byte) 0x06, + (byte) 0x07, // invalid metaData + }; + assertThat(PublicBroadcastData.parsePublicBroadcastData(serviceDataInvalid2)).isNull(); + + byte[] serviceData = + new byte[] { + (byte) 0x07, // features + (byte) metaDataLength, // metaDataLength + }; + + byte[] metadataHeader = + new byte[] { + (byte) (metaDataLength - 1), // length 141 + (byte) 0xFF + }; + + byte[] metadataPayload = new byte[140]; + new Random().nextBytes(metadataPayload); + + PublicBroadcastData data = + PublicBroadcastData.parsePublicBroadcastData( + Bytes.concat(serviceData, metadataHeader, metadataPayload)); + assertThat(data.isEncrypted()).isTrue(); + assertThat(data.getAudioConfigQuality()).isEqualTo(3); + assertThat(data.getMetadataLength()).isEqualTo(metaDataLength); + assertThat(data.getMetadata()).isEqualTo(Bytes.concat(metadataHeader, metadataPayload)); + + byte[] serviceDataNoMetaData = + new byte[] { + (byte) 0x02, // features, non-encrypted, standard quality prsent + (byte) 0x00, // metaDataLength + }; + PublicBroadcastData dataNoMetaData = + PublicBroadcastData.parsePublicBroadcastData(serviceDataNoMetaData); + assertThat(dataNoMetaData.isEncrypted()).isFalse(); + assertThat(dataNoMetaData.getAudioConfigQuality()).isEqualTo(1); + assertThat(dataNoMetaData.getMetadataLength()).isEqualTo(0); + assertThat(dataNoMetaData.getMetadata()).isEqualTo(new byte[] {}); + } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterPropertiesTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterPropertiesTest.java index 2b7283ed34..3ea1e6d55f 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterPropertiesTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterPropertiesTest.java @@ -101,8 +101,13 @@ public class AdapterPropertiesTest { @Test public void testCleanupPrevBondRecordsFor() { mRemoteDevices.reset(); - mRemoteDevices.addDeviceProperties(TEST_BT_ADDR_BYTES); - mRemoteDevices.addDeviceProperties(TEST_BT_ADDR_BYTES_2); + mRemoteDevices + .addDeviceProperties(TEST_BT_ADDR_BYTES) + .setDeviceType(BluetoothDevice.DEVICE_TYPE_LE); + mRemoteDevices + .addDeviceProperties(TEST_BT_ADDR_BYTES_2) + .setDeviceType(BluetoothDevice.DEVICE_TYPE_LE); + BluetoothDevice device1, device2; device1 = mRemoteDevices.getDevice(TEST_BT_ADDR_BYTES); device2 = mRemoteDevices.getDevice(TEST_BT_ADDR_BYTES_2); diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceRestartTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceRestartTest.java index dd995fb79d..93a6688fe4 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceRestartTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceRestartTest.java @@ -90,6 +90,7 @@ public class AdapterServiceRestartTest { private @Mock IBluetoothCallback mIBluetoothCallback; private @Mock Binder mBinder; private @Mock android.app.Application mApplication; + private @Mock MetricsLogger mMockMetricsLogger; private @Mock AdapterNativeInterface mNativeInterface; private @Mock BluetoothKeystoreNativeInterface mKeystoreNativeInterface; private @Mock BluetoothQualityReportNativeInterface mQualityNativeInterface; @@ -223,9 +224,14 @@ public class AdapterServiceRestartTest { doReturn(Process.BLUETOOTH_UID).when(mMockPackageManager) .getPackageUidAsUser(any(), anyInt(), anyInt()); + when(mMockMetricsLogger.init(any())).thenReturn(true); + when(mMockMetricsLogger.close()).thenReturn(true); + AdapterServiceTest.configureEnabledProfiles(); Config.init(mMockContext); + mAdapterService.setMetricsLogger(mMockMetricsLogger); + // Attach a context to the service for permission checks. mAdapterService.attach(mMockContext, null, null, null, mApplication, null); mAdapterService.onCreate(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java index a7acee18f2..9af70370cb 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java @@ -143,6 +143,7 @@ public class AdapterServiceTest { private @Mock IBluetoothCallback mIBluetoothCallback; private @Mock Binder mBinder; private @Mock android.app.Application mApplication; + private @Mock MetricsLogger mMockMetricsLogger; private @Mock AdapterNativeInterface mNativeInterface; private @Mock BluetoothKeystoreNativeInterface mKeystoreNativeInterface; private @Mock BluetoothQualityReportNativeInterface mQualityNativeInterface; @@ -311,9 +312,14 @@ public class AdapterServiceTest { when(mMockService.getName()).thenReturn("Service1"); when(mMockService2.getName()).thenReturn("Service2"); + when(mMockMetricsLogger.init(any())).thenReturn(true); + when(mMockMetricsLogger.close()).thenReturn(true); + configureEnabledProfiles(); Config.init(mMockContext); + mAdapterService.setMetricsLogger(mMockMetricsLogger); + // Attach a context to the service for permission checks. mAdapterService.attach(mMockContext, null, null, null, mApplication, null); mAdapterService.onCreate(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/MetricsLoggerTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/MetricsLoggerTest.java index e301f5c152..d93deef81c 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/MetricsLoggerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/MetricsLoggerTest.java @@ -64,17 +64,17 @@ public class MetricsLoggerTest { SANITIZED_DEVICE_NAME_MAP.put("Someone's AirpoDs", "airpods"); SANITIZED_DEVICE_NAME_MAP.put("Galaxy Buds pro", "galaxybudspro"); SANITIZED_DEVICE_NAME_MAP.put("Someone's AirpoDs", "airpods"); - SANITIZED_DEVICE_NAME_MAP.put("My BMW X5", "bmw"); + SANITIZED_DEVICE_NAME_MAP.put("My BMW X5", "bmwx5"); SANITIZED_DEVICE_NAME_MAP.put("Jane Doe's Tesla Model--X", "teslamodelx"); SANITIZED_DEVICE_NAME_MAP.put("TESLA of Jane DOE", "tesla"); - SANITIZED_DEVICE_NAME_MAP.put("SONY WH-1000XM4", "wh1000xm4"); - SANITIZED_DEVICE_NAME_MAP.put("Amazon Echo Dot", "echo"); + SANITIZED_DEVICE_NAME_MAP.put("SONY WH-1000XM4", "sonywh1000xm4"); + SANITIZED_DEVICE_NAME_MAP.put("Amazon Echo Dot", "amazonechodot"); SANITIZED_DEVICE_NAME_MAP.put("Chevy my link", "chevymylink"); SANITIZED_DEVICE_NAME_MAP.put("Dad's Hyundai i10", "hyundai"); SANITIZED_DEVICE_NAME_MAP.put("Mike's new Galaxy Buds 2", "galaxybuds2"); SANITIZED_DEVICE_NAME_MAP.put("My third Ford F-150", "fordf150"); SANITIZED_DEVICE_NAME_MAP.put("Bose QuietComfort 35 Series 2", "bosequietcomfort35"); - SANITIZED_DEVICE_NAME_MAP.put("Fitbit versa 3 band", "versa3"); + SANITIZED_DEVICE_NAME_MAP.put("Fitbit versa 3 band", "fitbitversa3"); SANITIZED_DEVICE_NAME_MAP.put("my vw bt", "myvw"); SANITIZED_DEVICE_NAME_MAP.put("SomeDevice1", ""); SANITIZED_DEVICE_NAME_MAP.put("My traverse", "traverse"); @@ -252,6 +252,7 @@ public class MetricsLoggerTest { String deviceName = entry.getKey(); String sha256 = MetricsLogger.getSha256String(entry.getValue()); Assert.assertEquals( + deviceName, sha256, mTestableMetricsLogger.logAllowlistedDeviceNameHash(1, deviceName, true)); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java index 3b9270d63d..382ed57cd1 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java @@ -334,6 +334,8 @@ public class LeAudioBroadcastServiceTest { // Check if metadata is requested when the broadcast starts to stream verify(mLeAudioBroadcasterNativeInterface, times(1)).getBroadcastMetadata(eq(broadcastId)); + TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); + Assert.assertFalse(mOnBroadcastStartFailedCalled); Assert.assertTrue(mOnBroadcastStartedCalled); } @@ -355,6 +357,8 @@ public class LeAudioBroadcastServiceTest { state_event.valueInt1 = broadcastId; mService.messageFromNative(state_event); + TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); + Assert.assertTrue(mOnBroadcastStoppedCalled); Assert.assertFalse(mOnBroadcastStopFailedCalled); } @@ -427,6 +431,8 @@ public class LeAudioBroadcastServiceTest { create_event.valueBool1 = false; mService.messageFromNative(create_event); + TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); + Assert.assertFalse(mOnBroadcastStartedCalled); Assert.assertTrue(mOnBroadcastStartFailedCalled); } @@ -472,6 +478,8 @@ public class LeAudioBroadcastServiceTest { // Verify if broadcast is auto-started on start verify(mLeAudioBroadcasterNativeInterface, times(1)).startBroadcast(eq(broadcastId)); + TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); + Assert.assertTrue(mOnBroadcastStartedCalled); // Notify initial paused state @@ -549,6 +557,9 @@ public class LeAudioBroadcastServiceTest { // Stop non-existing broadcast mService.stopBroadcast(broadcastId); + + TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); + Assert.assertFalse(mOnBroadcastStoppedCalled); Assert.assertTrue(mOnBroadcastStopFailedCalled); @@ -559,6 +570,9 @@ public class LeAudioBroadcastServiceTest { meta_builder.setProgramInfo("Public broadcast info"); mService.updateBroadcast(broadcastId, buildBroadcastSettingsFromMetadata(meta_builder.build(), null, 1)); + + TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); + Assert.assertFalse(mOnBroadcastUpdatedCalled); Assert.assertTrue(mOnBroadcastUpdateFailedCalled); } @@ -625,6 +639,8 @@ public class LeAudioBroadcastServiceTest { create_event.valueBool1 = true; mService.messageFromNative(create_event); + TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); + // Inject metadata stack event and verify if getter API works as expected LeAudioStackEvent state_event = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_METADATA_CHANGED); @@ -632,6 +648,8 @@ public class LeAudioBroadcastServiceTest { state_event.broadcastMetadata = createBroadcastMetadata(); mService.messageFromNative(state_event); + TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); + List<BluetoothLeBroadcastMetadata> meta_list = mService.getAllBroadcastMetadata(); Assert.assertNotNull(meta_list); Assert.assertNotEquals(meta_list.size(), 0); @@ -844,6 +862,8 @@ public class LeAudioBroadcastServiceTest { BluetoothLeAudioContentMetadata meta = meta_builder.build(); BluetoothLeBroadcastSettings settings = buildBroadcastSettingsFromMetadata(meta, code, 1); + TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); + verifyBroadcastStarted(broadcastId, settings); mOnBroadcastStartedCalled = false; mOnBroadcastStartFailedCalled = false; @@ -851,6 +871,8 @@ public class LeAudioBroadcastServiceTest { // verify creating another broadcast will fail mService.createBroadcast(settings); + TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); + Assert.assertFalse(mOnBroadcastStartedCalled); Assert.assertTrue(mOnBroadcastStartFailedCalled); Assert.assertEquals( diff --git a/android/pandora/OWNERS b/android/pandora/OWNERS index a188b6cbc3..792fa63ca0 100644 --- a/android/pandora/OWNERS +++ b/android/pandora/OWNERS @@ -1,5 +1,4 @@ # Bug component: 1099313 girardier@google.com licorne@google.com -uael@google.com charliebout@google.com diff --git a/android/pandora/test/OWNERS b/android/pandora/test/OWNERS index 9b396a0698..792fa63ca0 100644 --- a/android/pandora/test/OWNERS +++ b/android/pandora/test/OWNERS @@ -2,4 +2,3 @@ girardier@google.com licorne@google.com charliebout@google.com -uael@google.com @@ -614,19 +614,25 @@ class HostBuild(): self._target_all() +# Default to 10 min timeouts on all git operations. +GIT_TIMEOUT_SEC = 600 + + class Bootstrap(): - def __init__(self, base_dir, bt_dir, partial_staging): + def __init__(self, base_dir, bt_dir, partial_staging, clone_timeout): """ Construct bootstrapper. Args: base_dir: Where to stage everything. bt_dir: Where bluetooth source is kept (will be symlinked) partial_staging: Whether to do a partial clone for staging. + clone_timeout: Timeout for clone operations. """ self.base_dir = os.path.abspath(base_dir) self.bt_dir = os.path.abspath(bt_dir) self.partial_staging = partial_staging + self.clone_timeout = clone_timeout # Create base directory if it doesn't already exist os.makedirs(self.base_dir, exist_ok=True) @@ -641,6 +647,21 @@ class Bootstrap(): self.dir_setup_complete = os.path.join(self.base_dir, '.setup-complete') + def _run_with_timeout(self, cmd, cwd, timeout=None): + """Runs a command using subprocess.check_output. """ + print('Running command: {} [at cwd={}]'.format(' '.join(cmd), cwd)) + with subprocess.Popen(cmd, cwd=cwd) as proc: + try: + outs, errs = proc.communicate(timeout=timeout) + except subprocess.TimeoutExpired: + proc.kill() + outs, errs = proc.communicate() + print('Timeout on {}'.format(' '.join(cmd)), file=sys.stderr) + raise + + if proc.returncode != 0: + raise Exception('Cmd {} had return code {}'.format(' '.join(cmd), proc.returncode)) + def _update_platform2(self): """Updates repositories used for build.""" for project in BOOTSTRAP_GIT_REPOS.keys(): @@ -648,7 +669,7 @@ class Bootstrap(): (repo, commit) = BOOTSTRAP_GIT_REPOS[project] # Update to required commit when necessary or pull the latest code. - if commit: + if commit is not None: head = subprocess.check_output(['git', 'rev-parse', 'HEAD'], cwd=cwd).strip() if head != commit: subprocess.check_call(['git', 'fetch'], cwd=cwd) @@ -681,9 +702,29 @@ class Bootstrap(): # Check out all repos in git directory for project in BOOTSTRAP_GIT_REPOS.keys(): (repo, commit) = BOOTSTRAP_GIT_REPOS[project] - subprocess.check_call(['git', 'clone', repo, project] + clone_options, cwd=self.git_dir) + + # Try repo clone several times. + # Currently, we set timeout on this operation after + # |self.clone_timeout|. If it fails, try to recover. + tries = 2 + for x in range(tries): + try: + self._run_with_timeout(['git', 'clone', repo, project] + clone_options, + cwd=self.git_dir, + timeout=self.clone_timeout) + except subprocess.TimeoutExpired: + shutil.rmtree(os.path.join(self.git_dir, project)) + if x == tries - 1: + raise + # All other exceptions should raise + except: + raise + # No exceptions/problems should not retry. + else: + break + # Pin to commit. - if commit: + if commit is not None: subprocess.check_call(['git', 'checkout', commit], cwd=os.path.join(self.git_dir, project)) # Symlink things @@ -890,6 +931,10 @@ if __name__ == '__main__': help='Bootstrap git repositories with partial clones. Use to speed up initial git clone for automated builds.', default=False, action='store_true') + parser.add_argument('--clone-timeout', + help='Timeout for repository cloning during bootstrap.', + default=GIT_TIMEOUT_SEC, + type=int) args = parser.parse_args() # Make sure we get absolute path + expanded path for bootstrap directory @@ -901,7 +946,7 @@ if __name__ == '__main__': raise Exception("Only x86_64 machines are currently supported by this build script.") if args.run_bootstrap: - bootstrap = Bootstrap(args.bootstrap_dir, os.path.dirname(__file__), args.partial_staging) + bootstrap = Bootstrap(args.bootstrap_dir, os.path.dirname(__file__), args.partial_staging, args.clone_timeout) bootstrap.bootstrap() elif args.print_env: build = HostBuild(args) diff --git a/flags/BUILD.gn b/flags/BUILD.gn new file mode 100644 index 0000000000..13c381300b --- /dev/null +++ b/flags/BUILD.gn @@ -0,0 +1,41 @@ +import("//bt/flags/aconfig.gni") + +aconfig("bluetooth_flags_c_lib") { + sources = [ + "a2dp.aconfig", + "asha.aconfig", + "audio_routing.aconfig", + "avrcp_controller.aconfig", + "bta_dm.aconfig", + "btif_dm.aconfig", + "connectivity.aconfig", + "did.aconfig", + "discovery_service.aconfig", + "dumpsys.aconfig", + "framework.aconfig", + "gap.aconfig", + "hap.aconfig", + "hfp.aconfig", + "hid.aconfig", + "l2cap.aconfig", + "le_advertising.aconfig", + "leaudio.aconfig", + "map.aconfig", + "mapclient.aconfig", + "metric.aconfig", + "opp.aconfig", + "pairing.aconfig", + "ranging.aconfig", + "rfcomm.aconfig", + "rnr.aconfig", + "sdp.aconfig", + "security.aconfig", + "sniff.aconfig", + "sockets.aconfig", + "system_service.aconfig", + "vcp.aconfig", + "vsc.aconfig", + ] + package = "com.android.bluetooth.flags" + deps = [ "//bt/floss/libflags:libflags" ] +} diff --git a/flags/aconfig.gni b/flags/aconfig.gni new file mode 100644 index 0000000000..4891c9f2cb --- /dev/null +++ b/flags/aconfig.gni @@ -0,0 +1,84 @@ +# +# Copyright 2024 Google, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Generate c++ files for each aconfig file +# +# Parameters: +# sources: aconfig source files +# package: aconfig package +template("aconfig") { + forward_variables_from(invoker, + [ + "sources", + "package", + ]) + assert(defined(sources), "sources must be set") + assert(defined(package), "package must be set") + + outdir = rebase_path(target_gen_dir) + + aconfig_cpp_file_name = string_replace(package, ".", "_") + + aconfig_declarations = [] + + foreach(source, sources) { + source = rebase_path(source) + aconfig_declarations += [ "--declarations=${source}" ] + } + + aconfig_cache = "${target_name}_cache" + + action(aconfig_cache) { + script = "//common-mk/file_generator_wrapper.py" + args = [ + "aconfig", + "create-cache", + "--package=${package}", + "--cache=${outdir}/${aconfig_cache}", + ] + aconfig_declarations + + outputs = [ "${outdir}/${aconfig_cache}" ] + } + + action("${target_name}_cpp") { + script = "//common-mk/file_generator_wrapper.py" + args = [ + "aconfig", + "create-cpp-lib", + "--cache=${outdir}/${aconfig_cache}", + "--out=${outdir}", + ] + + outputs = [ + "${outdir}/include/${aconfig_cpp_file_name}.h", + "${outdir}/${aconfig_cpp_file_name}.cc", + ] + + deps = [ ":${aconfig_cache}" ] + } + + all_dependent_config_name = "_${target_name}_all_dependent_config" + config(all_dependent_config_name) { + include_dirs = [ "${outdir}/include" ] + } + + static_library(target_name) { + sources = [] + sources = [ "${outdir}/${aconfig_cpp_file_name}.cc" ] + deps = [ ":${target_name}_cpp" ] + invoker.deps + all_dependent_configs = [ ":${all_dependent_config_name}" ] + } +} diff --git a/flags/btif_dm.aconfig b/flags/btif_dm.aconfig index 6e7d79b2e3..1acaf7aedf 100644 --- a/flags/btif_dm.aconfig +++ b/flags/btif_dm.aconfig @@ -21,3 +21,13 @@ flag { description: "Force BR/EDR transport for retrying SDP service discovery" bug: "326656580" } + +flag { + name: "do_not_replace_existing_cod_with_uncategorized_cod" + namespace: "bluetooth" + description: "Don't replace an existing stored class of device with one determined to be uncategorized" + bug: "335909751" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/flags/connectivity.aconfig b/flags/connectivity.aconfig index 372f5db8ab..ef83336d00 100644 --- a/flags/connectivity.aconfig +++ b/flags/connectivity.aconfig @@ -14,10 +14,3 @@ flag { description: "Guard the le shim connection map with a mutex" bug: "302054609" } - -flag { - name: "api_get_connection_state_sync_on_main" - namespace: "bluetooth" - description: "API call is unprotected from thread race conditions" - bug: "325333718" -} diff --git a/flags/gap.aconfig b/flags/gap.aconfig index 6152695548..c088ddad2a 100644 --- a/flags/gap.aconfig +++ b/flags/gap.aconfig @@ -196,3 +196,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "le_scan_use_uid_for_importance" + namespace: "bluetooth" + description: "Use uid instead of the first package name for fetching the importance of clients" + bug: "336965663" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/flags/hid.aconfig b/flags/hid.aconfig index 5869ff51c7..fe143c5a52 100644 --- a/flags/hid.aconfig +++ b/flags/hid.aconfig @@ -25,3 +25,23 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "save_initial_hid_connection_policy" + namespace: "bluetooth" + description: "Save HID connection policy on initial successful connection" + bug: "335904609" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { + name: "android_headtracker_service" + namespace: "bluetooth" + description: "Support headtracking through Android Headtracker Service" + bug: "335708774" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/flags/leaudio.aconfig b/flags/leaudio.aconfig index 1dd7061b37..b30aaa8670 100644 --- a/flags/leaudio.aconfig +++ b/flags/leaudio.aconfig @@ -308,4 +308,34 @@ flag { metadata { purpose: PURPOSE_BUGFIX } +} + +flag { + name: "run_clock_recovery_in_worker_thread" + namespace: "bluetooth" + description: "Fix thread ownership issue in clock_recovery" + bug: "333657963" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { + name: "leaudio_broadcast_extract_periodic_scanner_from_state_machine" + namespace: "bluetooth" + description: "Extract periodic scanner from state machine to make it independent from remote devices" + bug: "333691526" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { + name: "leaudio_allowed_context_mask" + namespace: "bluetooth" + description: "Set allowed context mask to filter stream requests in native" + bug: "336468573" + metadata { + purpose: PURPOSE_BUGFIX + } }
\ No newline at end of file diff --git a/floss/build/Dockerfile b/floss/build/Dockerfile index 2be3277773..2e0f3a3241 100644 --- a/floss/build/Dockerfile +++ b/floss/build/Dockerfile @@ -61,13 +61,14 @@ RUN apt-get update && \ # Next install the Rust toolchain. Download the toolchain to the local folder # using curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs ADD rustup/rustup.sh /tmp -RUN /tmp/rustup.sh -y --default-toolchain 1.68.2 +RUN /tmp/rustup.sh -y --default-toolchain 1.77.1 # Add .cargo/bin to $PATH ENV PATH="/root/.cargo/bin:${PATH}" # Install cargo packages required on build image. RUN cargo install --locked cxxbridge-cmd@1.0.94 pdl-compiler@0.1.1 grpcio-compiler@0.13.0 +RUN cargo install --git https://android.googlesource.com/platform/build#8f9ca807 aconfig # Rename llvm packages. By default, they are named 11vm-ar-13, etc. which won't # work properly with the build. diff --git a/floss/libflags/BUILD.gn b/floss/libflags/BUILD.gn new file mode 100644 index 0000000000..6a3fb5d768 --- /dev/null +++ b/floss/libflags/BUILD.gn @@ -0,0 +1,25 @@ +# +# Copyright 2024 Google, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +config("libflags_config") { + include_dirs = [ "include" ] +} + +static_library("libflags") { + sources = [ "get_flags.cc" ] + include_dirs = [ "//bt/system" ] + public_configs = [ ":libflags_config" ] +} diff --git a/floss/libflags/get_flags.cc b/floss/libflags/get_flags.cc new file mode 100644 index 0000000000..d7152e2edb --- /dev/null +++ b/floss/libflags/get_flags.cc @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2024 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 "server_configurable_flags/get_flags.h" + +namespace server_configurable_flags { + +std::string GetServerConfigurableFlag( + const std::string& experiment_category_name, + const std::string& experiment_flag_name, const std::string& default_value) { + return default_value; +} +} // namespace server_configurable_flags diff --git a/floss/libflags/include/server_configurable_flags/get_flags.h b/floss/libflags/include/server_configurable_flags/get_flags.h new file mode 100644 index 0000000000..04f413e749 --- /dev/null +++ b/floss/libflags/include/server_configurable_flags/get_flags.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#pragma once + +#include <string> + +namespace server_configurable_flags { + +std::string GetServerConfigurableFlag( + const std::string& experiment_category_name, + const std::string& experiment_flag_name, const std::string& default_value); + +} // namespace server_configurable_flags diff --git a/framework/OWNERS b/framework/OWNERS index fdf7a66c29..de66227202 100644 --- a/framework/OWNERS +++ b/framework/OWNERS @@ -1,4 +1,3 @@ hallstrom@google.com -sattiraju@google.com siyuanh@google.com wescande@google.com diff --git a/framework/java/android/bluetooth/BluetoothLeAudioCodecConfig.java b/framework/java/android/bluetooth/BluetoothLeAudioCodecConfig.java index 4c820b68d3..b0fa26c025 100644 --- a/framework/java/android/bluetooth/BluetoothLeAudioCodecConfig.java +++ b/framework/java/android/bluetooth/BluetoothLeAudioCodecConfig.java @@ -307,6 +307,54 @@ public final class BluetoothLeAudioCodecConfig implements Parcelable { out.writeInt(mMaxOctetsPerFrame); } + private String sampleRateToString(@SampleRate int sampleRateBit) { + switch (sampleRateBit) { + case SAMPLE_RATE_NONE: + return "None"; + case SAMPLE_RATE_8000: + return "8 kHz"; + case SAMPLE_RATE_11025: + return "11.025 kHz"; + case SAMPLE_RATE_16000: + return "16 kHz"; + case SAMPLE_RATE_22050: + return "22.05 kHz"; + case SAMPLE_RATE_24000: + return "24 kHz"; + case SAMPLE_RATE_32000: + return "32 kHz"; + case SAMPLE_RATE_44100: + return "44.1 kHz"; + case SAMPLE_RATE_48000: + return "48 kHz"; + case SAMPLE_RATE_88200: + return "88.2 kHz"; + case SAMPLE_RATE_96000: + return "96 kHz"; + case SAMPLE_RATE_176400: + return "176.4 kHz"; + case SAMPLE_RATE_192000: + return "192 kHz"; + case SAMPLE_RATE_384000: + return "384 kHz"; + default: + return "Unknown bit " + sampleRateBit; + } + } + + private String frameDurationToString(@FrameDuration int frameDurationBit) { + switch (frameDurationBit) { + case FRAME_DURATION_NONE: + return "None"; + case FRAME_DURATION_7500: + return "7.5 ms"; + case FRAME_DURATION_10000: + return "10 ms"; + default: + return "Unknown bit " + frameDurationBit; + } + } + @Override public String toString() { return "{codecName:" @@ -316,13 +364,13 @@ public final class BluetoothLeAudioCodecConfig implements Parcelable { + ",mCodecPriority:" + mCodecPriority + ",mSampleRate:" - + mSampleRate + + sampleRateToString(mSampleRate) + ",mBitsPerSample:" + mBitsPerSample - + ",mChannelCount:" + + ",mChannelCountBitMask:" + mChannelCount + ",mFrameDuration:" - + mFrameDuration + + frameDurationToString(mFrameDuration) + ",mOctetsPerFrame:" + mOctetsPerFrame + ",mMinOctetsPerFrame:" diff --git a/framework/java/android/bluetooth/BluetoothLeAudioCodecConfigMetadata.java b/framework/java/android/bluetooth/BluetoothLeAudioCodecConfigMetadata.java index 680c15dfca..0a50828d15 100644 --- a/framework/java/android/bluetooth/BluetoothLeAudioCodecConfigMetadata.java +++ b/framework/java/android/bluetooth/BluetoothLeAudioCodecConfigMetadata.java @@ -29,7 +29,6 @@ import static android.bluetooth.BluetoothLeAudioCodecConfig.SAMPLE_RATE_8000; import static android.bluetooth.BluetoothLeAudioCodecConfig.SAMPLE_RATE_NONE; import static android.bluetooth.BluetoothLeAudioCodecConfig.SampleRate; -import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; @@ -125,6 +124,17 @@ public final class BluetoothLeAudioCodecConfigMetadata implements Parcelable { Arrays.hashCode(mRawMetadata)); } + @Override + public String toString() { + return "BluetoothLeAudioCodecConfigMetadata{" + + ("audioLocation=" + mAudioLocation) + + (", sampleRate=" + mSampleRate) + + (", frameDuration=" + mFrameDuration) + + (", octetsPerFrame=" + mOctetsPerFrame) + + (", rawMetadata=" + Arrays.toString(mRawMetadata)) + + '}'; + } + /** * Get the audio location information as defined in the Generic Audio section of Bluetooth * Assigned numbers. diff --git a/framework/java/android/bluetooth/BluetoothLeAudioContentMetadata.java b/framework/java/android/bluetooth/BluetoothLeAudioContentMetadata.java index bc263f032f..ef08c0d1c5 100644 --- a/framework/java/android/bluetooth/BluetoothLeAudioContentMetadata.java +++ b/framework/java/android/bluetooth/BluetoothLeAudioContentMetadata.java @@ -69,6 +69,15 @@ public final class BluetoothLeAudioContentMetadata implements Parcelable { return Objects.hash(mProgramInfo, mLanguage, Arrays.hashCode(mRawMetadata)); } + @Override + public String toString() { + return "BluetoothLeAudioContentMetadata{" + + ("programInfo=" + mProgramInfo) + + (", language=" + mLanguage) + + (", rawMetadata=" + Arrays.toString(mRawMetadata)) + + '}'; + } + /** * Get the title and/or summary of Audio Stream content in UTF-8 format. * diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcastChannel.java b/framework/java/android/bluetooth/BluetoothLeBroadcastChannel.java index 6384a5feff..9960183880 100644 --- a/framework/java/android/bluetooth/BluetoothLeBroadcastChannel.java +++ b/framework/java/android/bluetooth/BluetoothLeBroadcastChannel.java @@ -63,6 +63,15 @@ public final class BluetoothLeBroadcastChannel implements Parcelable { return Objects.hash(mIsSelected, mChannelIndex, mCodecMetadata); } + @Override + public String toString() { + return "BluetoothLeBroadcastChannel{" + + ("isSelected=" + mIsSelected) + + (", channelIndex=" + mChannelIndex) + + (", codecMetadata=" + mCodecMetadata) + + '}'; + } + /** * Return true if the channel is selected by Broadcast Assistant for the Broadcast Sink. * diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java b/framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java index 2d7db9199c..db8d3c2e33 100644 --- a/framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java +++ b/framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java @@ -189,6 +189,26 @@ public final class BluetoothLeBroadcastMetadata implements Parcelable { mSubgroups); } + @Override + public String toString() { + return "BluetoothLeBroadcastMetadata{" + + ("sourceAddressType=" + mSourceAddressType) + + (", sourceDevice=" + mSourceDevice) + + (", sourceAdvertisingSid=" + mSourceAdvertisingSid) + + (", broadcastId=" + mBroadcastId) + + (", paSyncInterval=" + mPaSyncInterval) + + (", isEncrypted=" + mIsEncrypted) + + (", isPublicBroadcast=" + mIsPublicBroadcast) + + (", broadcastName=" + mBroadcastName) + + (", broadcastCode=" + Arrays.toString(mBroadcastCode)) + + (", presentationDelayMicros=" + mPresentationDelayMicros) + + (", audioConfigQuality=" + mAudioConfigQuality) + + (", rssi=" + mRssi) + + (", publicBroadcastMetadata=" + mPublicBroadcastMetadata) + + (", subgroups=" + mSubgroups) + + '}'; + } + /** * Get the address type of the Broadcast Source. * diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcastSubgroup.java b/framework/java/android/bluetooth/BluetoothLeBroadcastSubgroup.java index 871dae4c15..e2b654c830 100644 --- a/framework/java/android/bluetooth/BluetoothLeBroadcastSubgroup.java +++ b/framework/java/android/bluetooth/BluetoothLeBroadcastSubgroup.java @@ -67,6 +67,16 @@ public final class BluetoothLeBroadcastSubgroup implements Parcelable { return Objects.hash(mCodecId, mCodecSpecificConfig, mContentMetadata, mChannels); } + @Override + public String toString() { + return "BluetoothLeBroadcastSubgroup{" + + ("codecId=" + mCodecId) + + (", codecSpecificConfig=" + mCodecSpecificConfig) + + (", contentMetadata=" + mContentMetadata) + + (", channels=" + mChannels) + + '}'; + } + /** * Get the codec ID field as defined by the Basic Audio Profile. * diff --git a/pandora/OWNERS b/pandora/OWNERS index 610b34604a..0a149b65a0 100644 --- a/pandora/OWNERS +++ b/pandora/OWNERS @@ -1,5 +1,4 @@ # Project owners girardier@google.com licorne@google.com -uael@google.com charliebout@google.com diff --git a/service/OWNERS b/service/OWNERS index e6ac9a0c3f..5b3f4bad26 100644 --- a/service/OWNERS +++ b/service/OWNERS @@ -1,2 +1 @@ -mylesgw@google.com wescande@google.com diff --git a/service/src/AutoOnFeature.kt b/service/src/AutoOnFeature.kt index 03fcabeeef..e8c96c589c 100644 --- a/service/src/AutoOnFeature.kt +++ b/service/src/AutoOnFeature.kt @@ -109,6 +109,10 @@ public fun notifyBluetoothOn(context: Context) { } else { Log.i(TAG, "Feature was set to its default value ${defaultFeatureValue}") } + } else { + // When Bluetooth turned on state, any saved time will be obsolete. + // This happen only when the phone reboot while Bluetooth is ON + Timer.resetStorage(context.contentResolver) } } @@ -138,6 +142,7 @@ public fun setUserEnabled( Counter.logIncrement( if (status) "bluetooth.value_auto_on_enabled" else "bluetooth.value_auto_on_disabled" ) + Timer.resetStorage(context.contentResolver) resetAutoOnTimerForUser(looper, context, state, callback_on) } @@ -204,7 +209,7 @@ private constructor( return date?.let { LocalDateTime.parse(it) } } - private fun resetStorage(resolver: ContentResolver) { + fun resetStorage(resolver: ContentResolver) { Settings.Secure.putString(resolver, STORAGE_KEY, null) } diff --git a/service/src/AutoOnFeatureTest.kt b/service/src/AutoOnFeatureTest.kt index 3b282e9faa..4a490c2119 100644 --- a/service/src/AutoOnFeatureTest.kt +++ b/service/src/AutoOnFeatureTest.kt @@ -210,6 +210,16 @@ class AutoOnFeatureTest { } @Test + fun notifyBluetoothOn_whenStorage_resetStorage() { + Settings.Secure.putString(resolver, Timer.STORAGE_KEY, timerTarget.toString()) + shadowOf(looper).idle() + + notifyBluetoothOn(context) + + expectNoStorageTime() + } + + @Test fun apiIsUserEnable_whenItWasNeverUsed_throwException() { restoreSettings() @@ -259,7 +269,21 @@ class AutoOnFeatureTest { disableUserSettings() setUserEnabled(true) - setupTimer() + + assertThat(timer).isNotNull() + } + + @Test + fun apiSetUserEnableToggle_whenScheduled_isRescheduled() { + val pastTime = timerTarget.minusDays(3) + Settings.Secure.putString(resolver, Timer.STORAGE_KEY, pastTime.toString()) + shadowOf(looper).idle() + + setUserEnabled(false) + expectNoStorageTime() + + setUserEnabled(true) + expectStorageTime() assertThat(timer).isNotNull() } diff --git a/system/audio_hal_interface/aidl/client_interface_aidl.cc b/system/audio_hal_interface/aidl/client_interface_aidl.cc index 6e0aae2eae..62affdb348 100644 --- a/system/audio_hal_interface/aidl/client_interface_aidl.cc +++ b/system/audio_hal_interface/aidl/client_interface_aidl.cc @@ -329,9 +329,25 @@ bool BluetoothAudioClientInterface::UpdateAudioConfig( return true; } + if (!session_started_) { + log::info("BluetoothAudioHal session has not started"); + return true; + } + auto aidl_retval = provider_->updateAudioConfiguration(audio_config); if (!aidl_retval.isOk()) { - log::error("BluetoothAudioHal failure: {}", aidl_retval.getDescription()); + if (audio_config.getTag() != transport_->GetAudioConfiguration().getTag()) { + log::warn( + "BluetoothAudioHal audio config type: {} doesn't " + "match provider's audio config type: {}", + ::aidl::android::hardware::bluetooth::audio::toString( + audio_config.getTag()), + ::aidl::android::hardware::bluetooth::audio::toString( + transport_->GetAudioConfiguration().getTag())); + } else { + log::warn("BluetoothAudioHal is not ready: {} ", + aidl_retval.getDescription()); + } } return true; } @@ -556,8 +572,8 @@ size_t BluetoothAudioSinkClientInterface::ReadAudioData(uint8_t* p_buf, timeout_ms -= kDefaultDataReadPollIntervalMs; continue; } else { - log::warn("{}/{} no data {} ms", (len - total_read), len, - (kDefaultDataReadTimeoutMs - timeout_ms)); + log::warn("{}/{} no data {} ms", len - total_read, len, + kDefaultDataReadTimeoutMs - timeout_ms); break; } } while (total_read < len); @@ -566,7 +582,7 @@ size_t BluetoothAudioSinkClientInterface::ReadAudioData(uint8_t* p_buf, (kDefaultDataReadTimeoutMs - kDefaultDataReadPollIntervalMs) && timeout_ms >= kDefaultDataReadPollIntervalMs) { log::verbose("underflow {} -> {} read {} ms", len, total_read, - (kDefaultDataReadTimeoutMs - timeout_ms)); + kDefaultDataReadTimeoutMs - timeout_ms); } else { log::verbose("{} -> {} read", len, total_read); } @@ -620,8 +636,8 @@ size_t BluetoothAudioSourceClientInterface::WriteAudioData(const uint8_t* p_buf, timeout_ms -= kDefaultDataWritePollIntervalMs; continue; } else { - log::warn("{}/{} no data {} ms", (len - total_written), len, - (kDefaultDataWriteTimeoutMs - timeout_ms)); + log::warn("{}/{} no data {} ms", len - total_written, len, + kDefaultDataWriteTimeoutMs - timeout_ms); break; } } while (total_written < len); @@ -630,7 +646,7 @@ size_t BluetoothAudioSourceClientInterface::WriteAudioData(const uint8_t* p_buf, (kDefaultDataWriteTimeoutMs - kDefaultDataWritePollIntervalMs) && timeout_ms >= kDefaultDataWritePollIntervalMs) { log::verbose("underflow {} -> {} read {} ms", len, total_written, - (kDefaultDataWriteTimeoutMs - timeout_ms)); + kDefaultDataWriteTimeoutMs - timeout_ms); } else { log::verbose("{} -> {} written", len, total_written); } 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 948e9a68e3..7bca5af5aa 100644 --- a/system/audio_hal_interface/aidl/le_audio_software_aidl.cc +++ b/system/audio_hal_interface/aidl/le_audio_software_aidl.cc @@ -23,6 +23,7 @@ #include <bluetooth/log.h> #include <atomic> +#include <bitset> #include <unordered_map> #include <vector> @@ -335,7 +336,7 @@ bool LeAudioTransport::IsRequestCompletedAfterUpdate( auto ret = std::get<1>(result); log::verbose("new state: {}, return {}", (int)(start_request_state_.load()), - ret ? "true" : "false"); + ret); return ret; } @@ -767,14 +768,17 @@ bluetooth::audio::le_audio::OffloadCapabilities get_offload_capabilities() { str_capability_log += " Decode Capability: " + hal_decode_cap.toString(); } - audio_set_config.topology_info = { - {{static_cast<uint8_t>(hal_decode_cap.deviceCount), - static_cast<uint8_t>(hal_encode_cap.deviceCount)}}}; - if (hal_bcast_capability_to_stack_format(hal_bcast_cap, bcast_cap)) { - // Set device_cnt, ase_cnt to zero to ignore these fields for broadcast - audio_set_config.topology_info = {{{0, 0}}}; - audio_set_config.confs.sink.push_back(AseConfiguration(bcast_cap)); + AudioSetConfiguration audio_set_config = { + .name = "broadcast offload capability"}; + // Note: The offloader config supports multiple channels per stream + // (subgroup), corresponding to the number of BISes, where each BIS + // has a single channel. + bcast_cap.channel_count_per_iso_stream = 1; + auto bis_cnt = hal_bcast_cap.channelCountPerStream; + while (bis_cnt--) { + audio_set_config.confs.sink.push_back(AseConfiguration(bcast_cap)); + } broadcast_offload_capabilities.push_back(audio_set_config); str_capability_log += " Broadcast Capability: " + hal_bcast_cap.toString(); diff --git a/system/audio_hal_interface/hidl/client_interface_hidl.cc b/system/audio_hal_interface/hidl/client_interface_hidl.cc index 9c40c516bf..2e07712330 100644 --- a/system/audio_hal_interface/hidl/client_interface_hidl.cc +++ b/system/audio_hal_interface/hidl/client_interface_hidl.cc @@ -784,8 +784,8 @@ size_t BluetoothAudioSinkClientInterface::ReadAudioData(uint8_t* p_buf, timeout_ms -= kDefaultDataReadPollIntervalMs; continue; } else { - log::warn("{}/{} no data {} ms", (len - total_read), len, - (kDefaultDataReadTimeoutMs - timeout_ms)); + log::warn("{}/{} no data {} ms", len - total_read, len, + kDefaultDataReadTimeoutMs - timeout_ms); break; } } while (total_read < len); @@ -794,7 +794,7 @@ size_t BluetoothAudioSinkClientInterface::ReadAudioData(uint8_t* p_buf, (kDefaultDataReadTimeoutMs - kDefaultDataReadPollIntervalMs) && timeout_ms >= kDefaultDataReadPollIntervalMs) { log::verbose("underflow {} -> {} read {} ms", len, total_read, - (kDefaultDataReadTimeoutMs - timeout_ms)); + kDefaultDataReadTimeoutMs - timeout_ms); } else { log::verbose("{} -> {} read", len, total_read); } @@ -859,8 +859,8 @@ size_t BluetoothAudioSourceClientInterface::WriteAudioData(const uint8_t* p_buf, timeout_ms -= kDefaultDataWritePollIntervalMs; continue; } else { - log::warn("{}/{} no data {} ms", (len - total_written), len, - (kDefaultDataWriteTimeoutMs - timeout_ms)); + log::warn("{}/{} no data {} ms", len - total_written, len, + kDefaultDataWriteTimeoutMs - timeout_ms); break; } } while (total_written < len); @@ -869,7 +869,7 @@ size_t BluetoothAudioSourceClientInterface::WriteAudioData(const uint8_t* p_buf, (kDefaultDataWriteTimeoutMs - kDefaultDataWritePollIntervalMs) && timeout_ms >= kDefaultDataWritePollIntervalMs) { log::verbose("underflow {} -> {} read {} ms", len, total_written, - (kDefaultDataWriteTimeoutMs - timeout_ms)); + kDefaultDataWriteTimeoutMs - timeout_ms); } else { log::verbose("{} -> {} written", len, total_written); } diff --git a/system/audio_hal_interface/hidl/le_audio_software_hidl.cc b/system/audio_hal_interface/hidl/le_audio_software_hidl.cc index a03bcaf1f4..34a549e0ce 100644 --- a/system/audio_hal_interface/hidl/le_audio_software_hidl.cc +++ b/system/audio_hal_interface/hidl/le_audio_software_hidl.cc @@ -266,8 +266,7 @@ bool LeAudioTransport::IsRequestCompletedAfterUpdate( auto ret = std::get<1>(result); log::verbose("new state: {}, return: {}", - static_cast<int>(start_request_state_.load()), - ret ? "true" : "false"); + static_cast<int>(start_request_state_.load()), ret); return ret; } diff --git a/system/audio_hal_interface/le_audio_software.cc b/system/audio_hal_interface/le_audio_software.cc index 5442e24c43..87661dc274 100644 --- a/system/audio_hal_interface/le_audio_software.cc +++ b/system/audio_hal_interface/le_audio_software.cc @@ -106,8 +106,6 @@ void LeAudioClientInterface::Sink::Cleanup() { static_cast<int>(HalVersionManager::GetHalTransport()), is_broadcaster_); - StopSession(); - /* Cleanup transport interface and instance according to type and role */ if (HalVersionManager::GetHalTransport() == BluetoothAudioHalTransport::HIDL) { @@ -466,7 +464,6 @@ size_t LeAudioClientInterface::Sink::Read(uint8_t* p_buf, uint32_t len) { void LeAudioClientInterface::Source::Cleanup() { log::info("source"); - StopSession(); if (hidl::le_audio::LeAudioSourceTransport::interface) { delete hidl::le_audio::LeAudioSourceTransport::interface; hidl::le_audio::LeAudioSourceTransport::interface = nullptr; @@ -799,7 +796,7 @@ LeAudioClientInterface::Sink* LeAudioClientInterface::GetSink( return nullptr; } - Sink* sink = is_broadcasting_session_type ? broadcast_sink_ : unicast_sink_; + auto& sink = is_broadcasting_session_type ? broadcast_sink_ : unicast_sink_; if (sink == nullptr) { sink = new Sink(is_broadcasting_session_type); } else { diff --git a/system/bta/Android.bp b/system/bta/Android.bp index 2900f82f25..f023ce103c 100644 --- a/system/bta/Android.bp +++ b/system/bta/Android.bp @@ -39,7 +39,9 @@ filegroup { "dm/bta_dm_api.cc", "dm/bta_dm_cfg.cc", "dm/bta_dm_ci.cc", + "dm/bta_dm_device_search.cc", "dm/bta_dm_disc.cc", + "dm/bta_dm_disc_legacy.cc", "dm/bta_dm_gatt_client.cc", "dm/bta_dm_main.cc", "dm/bta_dm_pm.cc", diff --git a/system/bta/BUILD.gn b/system/bta/BUILD.gn index 7f590b7df1..dfc08fb5fb 100644 --- a/system/bta/BUILD.gn +++ b/system/bta/BUILD.gn @@ -43,7 +43,9 @@ static_library("bta") { "dm/bta_dm_sec_api.cc", "dm/bta_dm_cfg.cc", "dm/bta_dm_ci.cc", + "dm/bta_dm_device_search.cc", "dm/bta_dm_disc.cc", + "dm/bta_dm_disc_legacy.cc", "dm/bta_dm_gatt_client.cc", "dm/bta_dm_main.cc", "dm/bta_dm_pm.cc", diff --git a/system/bta/ag/bta_ag_rfc.cc b/system/bta/ag/bta_ag_rfc.cc index f26ba86827..e4e6f0c487 100644 --- a/system/bta/ag/bta_ag_rfc.cc +++ b/system/bta/ag/bta_ag_rfc.cc @@ -267,9 +267,8 @@ void bta_ag_start_servers(tBTA_AG_SCB* p_scb, tBTA_SERVICE_MASK services) { /* TODO: CR#137125 to handle to error properly */ log::error( "RFCOMM_CreateConnectionWithSecurity ERROR {}, p_scb={}, " - "services={}, mgmt_cback_index={}", - status, fmt::ptr(p_scb), loghex(services), - management_callback_index); + "services=0x{:x}, mgmt_cback_index={}", + status, fmt::ptr(p_scb), services, management_callback_index); } log::verbose("p_scb=0x{}, services=0x{:04x}, mgmt_cback_index={}", fmt::ptr(p_scb), services, management_callback_index); diff --git a/system/bta/ag/bta_ag_sco.cc b/system/bta/ag/bta_ag_sco.cc index f81b4fcc48..7b6eedab5d 100644 --- a/system/bta/ag/bta_ag_sco.cc +++ b/system/bta/ag/bta_ag_sco.cc @@ -1670,8 +1670,7 @@ bool bta_ag_is_sco_managed_by_audio() { bool value = false; if (IS_FLAG_ENABLED(is_sco_managed_by_audio)) { value = osi_property_get_bool("bluetooth.sco.managed_by_audio", false); - log::verbose("is_sco_managed_by_audio enabled={}", - value ? "true" : "false"); + log::verbose("is_sco_managed_by_audio enabled={}", value); } return value; } diff --git a/system/bta/av/bta_av_aact.cc b/system/bta/av/bta_av_aact.cc index e9cc567ee7..b56fd00034 100644 --- a/system/bta/av/bta_av_aact.cc +++ b/system/bta/av/bta_av_aact.cc @@ -495,7 +495,7 @@ void bta_av_sink_data_cback(uint8_t handle, BT_HDR* p_pkt, uint32_t time_stamp, ******************************************************************************/ static void bta_av_a2dp_sdp_cback(bool found, tA2DP_Service* p_service, const RawAddress& peer_address) { - log::verbose("peer {} : found={}", peer_address, (found) ? "true" : "false"); + log::verbose("peer {} : found={}", peer_address, found); tBTA_AV_SCB* p_scb = NULL; if (peer_address != RawAddress::kEmpty) { @@ -516,8 +516,7 @@ static void bta_av_a2dp_sdp_cback(bool found, tA2DP_Service* p_service, if (!found) { log::error("peer {} A2DP service discovery failed", p_scb->PeerAddress()); } - log::verbose("peer {} found={}", p_scb->PeerAddress(), - (found) ? "true" : "false"); + log::verbose("peer {} found={}", p_scb->PeerAddress(), found); tBTA_AV_SDP_RES* p_msg = (tBTA_AV_SDP_RES*)osi_malloc(sizeof(tBTA_AV_SDP_RES)); @@ -2290,7 +2289,7 @@ void bta_av_start_ok(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) { } log::verbose("peer {} wait:0x{:x} use_rtp_header_marker_bit:{}", p_scb->PeerAddress(), p_scb->wait, - (p_scb->use_rtp_header_marker_bit) ? "true" : "false"); + p_scb->use_rtp_header_marker_bit); if (p_data && (p_data->hdr.offset != BTA_AV_RS_NONE)) { p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_BITS; diff --git a/system/bta/av/bta_av_api.cc b/system/bta/av/bta_av_api.cc index e2eb265f4c..c031de7541 100644 --- a/system/bta/av/bta_av_api.cc +++ b/system/bta/av/bta_av_api.cc @@ -156,7 +156,7 @@ void BTA_AvDeregister(tBTA_AV_HNDL hndl) { void BTA_AvOpen(const RawAddress& bd_addr, tBTA_AV_HNDL handle, bool use_rc, uint16_t uuid) { log::info("peer {} bta_handle:0x{:x} use_rc={} uuid=0x{:x}", bd_addr, handle, - (use_rc) ? "true" : "false", uuid); + use_rc, uuid); tBTA_AV_API_OPEN* p_buf = (tBTA_AV_API_OPEN*)osi_malloc(sizeof(tBTA_AV_API_OPEN)); @@ -236,7 +236,7 @@ void BTA_AvStart(tBTA_AV_HNDL handle, bool use_latency_mode) { log::info( "Starting audio/video stream data transfer bta_handle:{}, " "use_latency_mode:{}", - handle, use_latency_mode ? "true" : "false"); + handle, use_latency_mode); tBTA_AV_DO_START* p_buf = (tBTA_AV_DO_START*)osi_malloc(sizeof(tBTA_AV_DO_START)); @@ -626,7 +626,7 @@ void BTA_AvMetaCmd(uint8_t rc_handle, uint8_t label, tBTA_AV_CMD cmd_code, void BTA_AvSetLatency(tBTA_AV_HNDL handle, bool is_low_latency) { log::info( "Set audio/video stream low latency bta_handle:{}, is_low_latency:{}", - handle, is_low_latency ? "true" : "false"); + handle, is_low_latency); tBTA_AV_API_SET_LATENCY* p_buf = (tBTA_AV_API_SET_LATENCY*)osi_malloc(sizeof(tBTA_AV_API_SET_LATENCY)); diff --git a/system/bta/av/bta_av_ci.cc b/system/bta/av/bta_av_ci.cc index b43748a67c..904873992f 100644 --- a/system/bta/av/bta_av_ci.cc +++ b/system/bta/av/bta_av_ci.cc @@ -73,8 +73,7 @@ void bta_av_ci_setconfig(tBTA_AV_HNDL bta_av_handle, uint8_t err_code, log::info( "bta_av_handle=0x{:x} err_code={} category={} num_seid={} " "recfg_needed={} avdt_handle={}", - bta_av_handle, err_code, category, num_seid, - recfg_needed ? "true" : "false", avdt_handle); + bta_av_handle, err_code, category, num_seid, recfg_needed, avdt_handle); tBTA_AV_CI_SETCONFIG* p_buf = (tBTA_AV_CI_SETCONFIG*)osi_malloc(sizeof(tBTA_AV_CI_SETCONFIG)); diff --git a/system/bta/csis/csis_client.cc b/system/bta/csis/csis_client.cc index c149c3b135..089a73ca18 100644 --- a/system/bta/csis/csis_client.cc +++ b/system/bta/csis/csis_client.cc @@ -1009,7 +1009,7 @@ class CsisClientImpl : public CsisClient { void CsisLockCompleted(std::shared_ptr<CsisGroup>& csis_group, bool lock, CsisGroupLockStatus status) { log::debug("group id: {}, target state {}", csis_group->GetGroupId(), - (lock ? "lock" : "unlock")); + lock ? "lock" : "unlock"); NotifyGroupStatus(csis_group->GetGroupId(), lock, status, std::move(csis_group->GetLockCb())); @@ -1246,7 +1246,7 @@ class CsisClientImpl : public CsisClient { #ifdef CSIS_DEBUG auto irk = BTM_BleGetPeerIRK(address); - log::info("LTK {}", (base::HexEncode(*pltk.data(), 16))); + log::info("LTK {}", base::HexEncode(*pltk.data(), 16)); log::info("IRK {}", base::HexEncode(*irk.data(), 16)); #endif @@ -2200,9 +2200,9 @@ class CsisClientImpl : public CsisClient { tGATT_STATUS register_status = BTA_GATTC_RegisterForNotifications(gatt_if_, address, value_handle); log::debug( - "BTA_GATTC_RegisterForNotifications, status=0x{:02x}, value={}, " + "BTA_GATTC_RegisterForNotifications, status=0x{:02x}, value=0x{:x}, " "ccc=0x{:04x}", - register_status, loghex(value_handle), ccc_handle); + register_status, value_handle, ccc_handle); if (register_status != GATT_SUCCESS) return; } diff --git a/system/bta/dm/bta_dm_act.cc b/system/bta/dm/bta_dm_act.cc index d80cbeca68..4ac0c8e0f6 100644 --- a/system/bta/dm/bta_dm_act.cc +++ b/system/bta/dm/bta_dm_act.cc @@ -33,6 +33,7 @@ #include <cstdint> #include <vector> +#include "bta/dm/bta_dm_device_search.h" #include "bta/dm/bta_dm_disc.h" #include "bta/dm/bta_dm_gatt_client.h" #include "bta/dm/bta_dm_int.h" @@ -222,6 +223,7 @@ void BTA_dm_on_hw_off() { bta_dm_deinit_cb(); bta_dm_disc_stop(); + bta_dm_search_stop(); } void BTA_dm_on_hw_on() { @@ -314,7 +316,12 @@ void bta_dm_disable() { BTM_SetConnectability(BTM_NON_CONNECTABLE); bta_dm_disable_pm(); - bta_dm_disc_disable_search_and_disc(); + if (IS_FLAG_ENABLED(separate_service_and_device_discovery)) { + bta_dm_disc_disable_search(); + bta_dm_disc_disable_disc(); + } else { + bta_dm_disc_disable_search_and_disc(); + } bta_dm_cb.disabling = true; connection_manager::reset(false); @@ -657,8 +664,8 @@ static tBTA_DM_PEER_DEVICE* allocate_device_for(const RawAddress& bd_addr, return nullptr; } -void bta_dm_acl_up(const RawAddress& bd_addr, tBT_TRANSPORT transport, - uint16_t acl_handle) { +static void bta_dm_acl_up(const RawAddress& bd_addr, tBT_TRANSPORT transport, + uint16_t acl_handle) { auto device = allocate_device_for(bd_addr, transport); if (device == nullptr) { log::warn("Unable to allocate device resources for new connection"); @@ -1696,6 +1703,13 @@ tBTA_DM_PEER_DEVICE* allocate_device_for(const RawAddress& bd_addr, return ::allocate_device_for(bd_addr, transport); } +void bta_dm_acl_up(const RawAddress& bd_addr, tBT_TRANSPORT transport, + uint16_t acl_handle) { + ::bta_dm_acl_up(bd_addr, transport, acl_handle); +} +void bta_dm_acl_down(const RawAddress& bd_addr, tBT_TRANSPORT transport) { + ::bta_dm_acl_down(bd_addr, transport); +} void bta_dm_init_cb() { ::bta_dm_init_cb(); } void bta_dm_deinit_cb() { ::bta_dm_deinit_cb(); } void BTA_dm_on_hw_on() { ::BTA_dm_on_hw_on(); } diff --git a/system/bta/dm/bta_dm_api.cc b/system/bta/dm/bta_dm_api.cc index 6f72198c7d..9f8f464b30 100644 --- a/system/bta/dm/bta_dm_api.cc +++ b/system/bta/dm/bta_dm_api.cc @@ -28,6 +28,7 @@ #include <vector> +#include "bta/dm/bta_dm_device_search.h" #include "bta/dm/bta_dm_disc.h" #include "bta/dm/bta_dm_int.h" #include "bta/dm/bta_dm_sec_int.h" diff --git a/system/bta/dm/bta_dm_device_search.cc b/system/bta/dm/bta_dm_device_search.cc new file mode 100644 index 0000000000..15e13fa8eb --- /dev/null +++ b/system/bta/dm/bta_dm_device_search.cc @@ -0,0 +1,1038 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "bt_bta_sd" + +#include "bta/dm/bta_dm_device_search.h" + +#include <android_bluetooth_flags.h> +#include <base/functional/bind.h> +#include <base/strings/stringprintf.h> +#include <bluetooth/log.h> +#include <stddef.h> + +#include <cstdint> +#include <string> +#include <variant> +#include <vector> + +#include "android_bluetooth_flags.h" +#include "bta/dm/bta_dm_device_search_int.h" +#include "bta/dm/bta_dm_disc_legacy.h" +#include "bta/include/bta_gatt_api.h" +#include "bta/include/bta_sdp_api.h" +#include "btif/include/btif_config.h" +#include "common/circular_buffer.h" +#include "common/init_flags.h" +#include "common/strings.h" +#include "device/include/interop.h" +#include "internal_include/bt_target.h" +#include "main/shim/dumpsys.h" +#include "os/logging/log_adapter.h" +#include "osi/include/allocator.h" +#include "stack/btm/btm_int_types.h" // TimestampedStringCircularBuffer +#include "stack/btm/neighbor_inquiry.h" +#include "stack/include/bt_dev_class.h" +#include "stack/include/bt_name.h" +#include "stack/include/bt_uuid16.h" +#include "stack/include/btm_client_interface.h" +#include "stack/include/btm_log_history.h" +#include "stack/include/btm_sec_api.h" // BTM_IsRemoteNameKnown +#include "stack/include/gap_api.h" // GAP_BleReadPeerPrefConnParams +#include "stack/include/hidh_api.h" +#include "stack/include/main_thread.h" +#include "stack/include/sdp_status.h" +#include "stack/sdp/sdpint.h" // is_sdp_pbap_pce_disabled +#include "storage/config_keys.h" +#include "types/raw_address.h" + +using namespace bluetooth; + +namespace { +constexpr char kBtmLogTag[] = "DEV_SEARCH"; + +tBTA_DM_SEARCH_CB bta_dm_search_cb; +} // namespace + +static void bta_dm_inq_results_cb(tBTM_INQ_RESULTS* p_inq, const uint8_t* p_eir, + uint16_t eir_len); +static void bta_dm_inq_cmpl(); +static void bta_dm_inq_cmpl_cb(void* p_result); +static void bta_dm_search_cmpl(); +static void bta_dm_discover_next_device(void); +static void bta_dm_remname_cback(const tBTM_REMOTE_DEV_NAME* p); + +static bool bta_dm_read_remote_device_name(const RawAddress& bd_addr, + tBT_TRANSPORT transport); +static void bta_dm_discover_name(const RawAddress& remote_bd_addr); +static void bta_dm_execute_queued_search_request(); +static void bta_dm_search_cancel_notify(); +static void bta_dm_disable_search(); + +static void bta_dm_search_sm_execute(tBTA_DM_DEV_SEARCH_EVT event, + std::unique_ptr<tBTA_DM_SEARCH_MSG> msg); +static void bta_dm_observe_results_cb(tBTM_INQ_RESULTS* p_inq, + const uint8_t* p_eir, uint16_t eir_len); +static void bta_dm_observe_cmpl_cb(void* p_result); + +static void bta_dm_search_set_state(tBTA_DM_DEVICE_SEARCH_STATE state) { + bta_dm_search_cb.search_state = state; +} +static tBTA_DM_DEVICE_SEARCH_STATE bta_dm_search_get_state() { + return bta_dm_search_cb.search_state; +} + +static void post_search_evt(tBTA_DM_DEV_SEARCH_EVT event, + std::unique_ptr<tBTA_DM_SEARCH_MSG> msg) { + if (do_in_main_thread(FROM_HERE, base::BindOnce(&bta_dm_search_sm_execute, + event, std::move(msg))) != + BT_STATUS_SUCCESS) { + log::error("post_search_evt failed"); + } +} + +void bta_dm_disc_disable_search() { + if (!IS_FLAG_ENABLED(separate_service_and_device_discovery)) { + log::info("no-op when flag is disabled"); + return; + } + bta_dm_disable_search(); +} + +/******************************************************************************* + * + * Function bta_dm_search_start + * + * Description Starts an inquiry + * + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_search_start(tBTA_DM_API_SEARCH& search) { + get_btm_client_interface().db.BTM_ClearInqDb(nullptr); + /* save search params */ + bta_dm_search_cb.p_device_search_cback = search.p_cback; + + const tBTM_STATUS btm_status = + BTM_StartInquiry(bta_dm_inq_results_cb, bta_dm_inq_cmpl_cb); + switch (btm_status) { + case BTM_CMD_STARTED: + // Completion callback will be executed when controller inquiry + // timer pops or is cancelled by the user + break; + default: + log::warn("Unable to start device discovery search btm_status:{}", + btm_status_text(btm_status)); + // Not started so completion callback is executed now + bta_dm_inq_cmpl(); + break; + } +} + +/******************************************************************************* + * + * Function bta_dm_search_cancel + * + * Description Cancels an ongoing search for devices + * + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_search_cancel() { + if (BTM_IsInquiryActive()) { + BTM_CancelInquiry(); + bta_dm_search_cancel_notify(); + bta_dm_search_cmpl(); + } + /* If no Service Search going on then issue cancel remote name in case it is + active */ + else if (!bta_dm_search_cb.name_discover_done) { + get_btm_client_interface().peer.BTM_CancelRemoteDeviceName(); +#ifndef TARGET_FLOSS + /* bta_dm_search_cmpl is called when receiving the remote name cancel evt */ + if (!IS_FLAG_ENABLED( + bta_dm_defer_device_discovery_state_change_until_rnr_complete)) { + bta_dm_search_cmpl(); + } +#endif + } else { + bta_dm_inq_cmpl(); + } +} + +/******************************************************************************* + * + * Function bta_dm_inq_cmpl_cb + * + * Description Inquiry complete callback from BTM + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_inq_cmpl_cb(void* /* p_result */) { + log::verbose(""); + + bta_dm_inq_cmpl(); +} + +/******************************************************************************* + * + * Function bta_dm_inq_results_cb + * + * Description Inquiry results callback from BTM + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_inq_results_cb(tBTM_INQ_RESULTS* p_inq, const uint8_t* p_eir, + uint16_t eir_len) { + tBTA_DM_SEARCH result; + tBTM_INQ_INFO* p_inq_info; + uint16_t service_class; + + result.inq_res.bd_addr = p_inq->remote_bd_addr; + + // Pass the original address to GattService#onScanResult + result.inq_res.original_bda = p_inq->original_bda; + + result.inq_res.dev_class = p_inq->dev_class; + BTM_COD_SERVICE_CLASS(service_class, p_inq->dev_class); + result.inq_res.is_limited = + (service_class & BTM_COD_SERVICE_LMTD_DISCOVER) ? true : false; + result.inq_res.rssi = p_inq->rssi; + + result.inq_res.ble_addr_type = p_inq->ble_addr_type; + result.inq_res.inq_result_type = p_inq->inq_result_type; + result.inq_res.device_type = p_inq->device_type; + result.inq_res.flag = p_inq->flag; + result.inq_res.include_rsi = p_inq->include_rsi; + result.inq_res.clock_offset = p_inq->clock_offset; + + /* application will parse EIR to find out remote device name */ + result.inq_res.p_eir = const_cast<uint8_t*>(p_eir); + result.inq_res.eir_len = eir_len; + + result.inq_res.ble_evt_type = p_inq->ble_evt_type; + + p_inq_info = + get_btm_client_interface().db.BTM_InqDbRead(p_inq->remote_bd_addr); + if (p_inq_info != NULL) { + /* initialize remt_name_not_required to false so that we get the name by + * default */ + result.inq_res.remt_name_not_required = false; + } + + if (bta_dm_search_cb.p_device_search_cback) + bta_dm_search_cb.p_device_search_cback(BTA_DM_INQ_RES_EVT, &result); + + if (p_inq_info) { + /* application indicates if it knows the remote name, inside the callback + copy that to the inquiry data base*/ + if (result.inq_res.remt_name_not_required) + p_inq_info->appl_knows_rem_name = true; + } +} + +/******************************************************************************* + * + * Function bta_dm_remname_cback + * + * Description Remote name complete call back from BTM + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_remname_cback(const tBTM_REMOTE_DEV_NAME* p_remote_name) { + log::assert_that(p_remote_name != nullptr, + "assert failed: p_remote_name != nullptr"); + + log::info( + "Remote name request complete peer:{} btm_status:{} hci_status:{} " + "name[0]:{:c} length:{}", + p_remote_name->bd_addr, btm_status_text(p_remote_name->status), + hci_error_code_text(p_remote_name->hci_status), + p_remote_name->remote_bd_name[0], + strnlen((const char*)p_remote_name->remote_bd_name, BD_NAME_LEN)); + + if (bta_dm_search_cb.peer_bdaddr != p_remote_name->bd_addr) { + // if we got a different response, maybe ignore it + // we will have made a request directly from BTM_ReadRemoteDeviceName so we + // expect a dedicated response for us + if (p_remote_name->hci_status == HCI_ERR_CONNECTION_EXISTS) { + log::info( + "Assume command failed due to disconnection hci_status:{} peer:{}", + hci_error_code_text(p_remote_name->hci_status), + p_remote_name->bd_addr); + } else { + log::info( + "Ignored remote name response for the wrong address exp:{} act:{}", + bta_dm_search_cb.peer_bdaddr, p_remote_name->bd_addr); + return; + } + } + + /* remote name discovery is done but it could be failed */ + bta_dm_search_cb.name_discover_done = true; + bd_name_copy(bta_dm_search_cb.peer_name, p_remote_name->remote_bd_name); + + auto msg = std::make_unique<tBTA_DM_SEARCH_MSG>(tBTA_DM_REMOTE_NAME{}); + auto& rmt_name_msg = std::get<tBTA_DM_REMOTE_NAME>(*msg); + rmt_name_msg.bd_addr = bta_dm_search_cb.peer_bdaddr; + rmt_name_msg.hci_status = p_remote_name->hci_status; + bd_name_copy(rmt_name_msg.bd_name, p_remote_name->remote_bd_name); + + post_search_evt(BTA_DM_REMT_NAME_EVT, std::move(msg)); +} + +/******************************************************************************* + * + * Function bta_dm_read_remote_device_name + * + * Description Initiate to get remote device name + * + * Returns true if started to get remote name + * + ******************************************************************************/ +static bool bta_dm_read_remote_device_name(const RawAddress& bd_addr, + tBT_TRANSPORT transport) { + tBTM_STATUS btm_status; + + log::verbose(""); + + bta_dm_search_cb.peer_bdaddr = bd_addr; + bta_dm_search_cb.peer_name[0] = 0; + + btm_status = get_btm_client_interface().peer.BTM_ReadRemoteDeviceName( + bta_dm_search_cb.peer_bdaddr, bta_dm_remname_cback, transport); + + if (btm_status == BTM_CMD_STARTED) { + log::verbose("BTM_ReadRemoteDeviceName is started"); + + return (true); + } else if (btm_status == BTM_BUSY) { + log::verbose("BTM_ReadRemoteDeviceName is busy"); + + return (true); + } else { + log::warn("BTM_ReadRemoteDeviceName returns 0x{:02X}", btm_status); + + return (false); + } +} + +/******************************************************************************* + * + * Function bta_dm_inq_cmpl + * + * Description Process the inquiry complete event from BTM + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_inq_cmpl() { + if (bta_dm_search_get_state() == BTA_DM_SEARCH_CANCELLING) { + bta_dm_search_set_state(BTA_DM_SEARCH_IDLE); + bta_dm_execute_queued_search_request(); + return; + } + + if (bta_dm_search_get_state() != BTA_DM_SEARCH_ACTIVE) { + return; + } + + log::verbose("bta_dm_inq_cmpl"); + + bta_dm_search_cb.p_btm_inq_info = + get_btm_client_interface().db.BTM_InqDbFirst(); + if (bta_dm_search_cb.p_btm_inq_info != NULL) { + /* start name discovery from the first device on inquiry result + */ + bta_dm_search_cb.name_discover_done = false; + bta_dm_search_cb.peer_name[0] = 0; + bta_dm_discover_name( + bta_dm_search_cb.p_btm_inq_info->results.remote_bd_addr); + } else { + bta_dm_search_cmpl(); + } +} + +static void bta_dm_remote_name_cmpl( + const tBTA_DM_REMOTE_NAME& remote_name_msg) { + BTM_LogHistory(kBtmLogTag, remote_name_msg.bd_addr, "Remote name completed", + base::StringPrintf( + "status:%s state:%s name:\"%s\"", + hci_status_code_text(remote_name_msg.hci_status).c_str(), + bta_dm_state_text(bta_dm_search_get_state()).c_str(), + PRIVATE_NAME(remote_name_msg.bd_name))); + + tBTM_INQ_INFO* p_btm_inq_info = + get_btm_client_interface().db.BTM_InqDbRead(remote_name_msg.bd_addr); + if (!bd_name_is_empty(remote_name_msg.bd_name) && p_btm_inq_info) { + p_btm_inq_info->appl_knows_rem_name = true; + } + + // Callback with this property + if (bta_dm_search_cb.p_device_search_cback != nullptr) { + tBTA_DM_SEARCH search_data = { + .name_res = {.bd_addr = remote_name_msg.bd_addr, .bd_name = {}}, + }; + if (remote_name_msg.hci_status == HCI_SUCCESS) { + bd_name_copy(search_data.name_res.bd_name, remote_name_msg.bd_name); + } + bta_dm_search_cb.p_device_search_cback(BTA_DM_NAME_READ_EVT, &search_data); + } else { + log::warn("Received remote name complete without callback"); + } + + switch (bta_dm_search_get_state()) { + case BTA_DM_SEARCH_ACTIVE: + bta_dm_discover_name(bta_dm_search_cb.peer_bdaddr); + break; + case BTA_DM_SEARCH_IDLE: + case BTA_DM_SEARCH_CANCELLING: + log::warn("Received remote name request in state:{}", + bta_dm_state_text(bta_dm_search_get_state())); + break; + } +} + +static void bta_dm_search_cmpl() { + bta_dm_search_set_state(BTA_DM_SEARCH_IDLE); + + if (bta_dm_search_cb.p_device_search_cback) { + bta_dm_search_cb.p_device_search_cback(BTA_DM_DISC_CMPL_EVT, nullptr); + } + + bta_dm_execute_queued_search_request(); +} + +static void bta_dm_execute_queued_search_request() { + if (!bta_dm_search_cb.p_pending_search) return; + + log::info("Start pending search"); + post_search_evt(BTA_DM_API_SEARCH_EVT, + std::move(bta_dm_search_cb.p_pending_search)); + bta_dm_search_cb.p_pending_search.reset(); +} + +/******************************************************************************* + * + * Function bta_dm_search_clear_queue + * + * Description Clears the queue if API search cancel is called + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_search_clear_queue() { + bta_dm_search_cb.p_pending_search.reset(); +} + +/******************************************************************************* + * + * Function bta_dm_search_cancel_notify + * + * Description Notify application that search has been cancelled + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_search_cancel_notify() { + if (bta_dm_search_cb.p_device_search_cback) { + bta_dm_search_cb.p_device_search_cback(BTA_DM_SEARCH_CANCEL_CMPL_EVT, NULL); + } + switch (bta_dm_search_get_state()) { + case BTA_DM_SEARCH_ACTIVE: + case BTA_DM_SEARCH_CANCELLING: + if (!bta_dm_search_cb.name_discover_done) { + get_btm_client_interface().peer.BTM_CancelRemoteDeviceName(); + } + break; + case BTA_DM_SEARCH_IDLE: + // Nothing to do + break; + } +} + +/******************************************************************************* + * + * Function bta_dm_discover_next_device + * + * Description Starts discovery on the next device in Inquiry data base + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_discover_next_device(void) { + log::verbose("bta_dm_discover_next_device"); + + /* searching next device on inquiry result */ + bta_dm_search_cb.p_btm_inq_info = get_btm_client_interface().db.BTM_InqDbNext( + bta_dm_search_cb.p_btm_inq_info); + if (bta_dm_search_cb.p_btm_inq_info != NULL) { + bta_dm_search_cb.name_discover_done = false; + bta_dm_search_cb.peer_name[0] = 0; + bta_dm_discover_name( + bta_dm_search_cb.p_btm_inq_info->results.remote_bd_addr); + } else { + post_search_evt(BTA_DM_SEARCH_CMPL_EVT, nullptr); + } +} + +/*TODO: this function is duplicated, make it common ?*/ +static tBT_TRANSPORT bta_dm_determine_discovery_transport( + const RawAddress& remote_bd_addr) { + tBT_DEVICE_TYPE dev_type; + tBLE_ADDR_TYPE addr_type; + + get_btm_client_interface().peer.BTM_ReadDevInfo(remote_bd_addr, &dev_type, + &addr_type); + if (dev_type == BT_DEVICE_TYPE_BLE || addr_type == BLE_ADDR_RANDOM) { + return BT_TRANSPORT_LE; + } else if (dev_type == BT_DEVICE_TYPE_DUMO) { + if (get_btm_client_interface().peer.BTM_IsAclConnectionUp( + remote_bd_addr, BT_TRANSPORT_BR_EDR)) { + return BT_TRANSPORT_BR_EDR; + } else if (get_btm_client_interface().peer.BTM_IsAclConnectionUp( + remote_bd_addr, BT_TRANSPORT_LE)) { + return BT_TRANSPORT_LE; + } + } + return BT_TRANSPORT_BR_EDR; +} + +static void bta_dm_discover_name(const RawAddress& remote_bd_addr) { + const tBT_TRANSPORT transport = + bta_dm_determine_discovery_transport(remote_bd_addr); + + log::verbose("BDA: {}", remote_bd_addr); + + bta_dm_search_cb.peer_bdaddr = remote_bd_addr; + + log::verbose( + "name_discover_done = {} p_btm_inq_info 0x{} state = {}, transport={}", + bta_dm_search_cb.name_discover_done, + fmt::ptr(bta_dm_search_cb.p_btm_inq_info), bta_dm_search_get_state(), + transport); + + if (bta_dm_search_cb.p_btm_inq_info) { + log::verbose("appl_knows_rem_name {}", + bta_dm_search_cb.p_btm_inq_info->appl_knows_rem_name); + } + if (((bta_dm_search_cb.p_btm_inq_info) && + (bta_dm_search_cb.p_btm_inq_info->results.device_type == + BT_DEVICE_TYPE_BLE) && + (bta_dm_search_get_state() == BTA_DM_SEARCH_ACTIVE)) || + (transport == BT_TRANSPORT_LE && + interop_match_addr(INTEROP_DISABLE_NAME_REQUEST, + &bta_dm_search_cb.peer_bdaddr))) { + /* Do not perform RNR for LE devices at inquiry complete*/ + bta_dm_search_cb.name_discover_done = true; + } + // If we already have the name we can skip getting the name + if (BTM_IsRemoteNameKnown(remote_bd_addr, transport) && + bluetooth::common::init_flags::sdp_skip_rnr_if_known_is_enabled()) { + log::debug( + "Security record already known skipping read remote name peer:{}", + remote_bd_addr); + bta_dm_search_cb.name_discover_done = true; + } + + /* if name discovery is not done and application needs remote name */ + if ((!bta_dm_search_cb.name_discover_done) && + ((bta_dm_search_cb.p_btm_inq_info == NULL) || + (bta_dm_search_cb.p_btm_inq_info && + (!bta_dm_search_cb.p_btm_inq_info->appl_knows_rem_name)))) { + if (bta_dm_read_remote_device_name(bta_dm_search_cb.peer_bdaddr, + transport)) { + BTM_LogHistory(kBtmLogTag, bta_dm_search_cb.peer_bdaddr, + "Read remote name", + base::StringPrintf("Transport:%s", + bt_transport_text(transport).c_str())); + return; + } else { + log::error("Unable to start read remote device name"); + } + + /* starting name discovery failed */ + bta_dm_search_cb.name_discover_done = true; + } + + /* name discovery is done for this device */ + if (bta_dm_search_get_state() == BTA_DM_SEARCH_ACTIVE) { + // if p_btm_inq_info is nullptr, there is no more inquiry results to + // discover name for + if (bta_dm_search_cb.p_btm_inq_info) { + bta_dm_discover_next_device(); + } else { + log::info("end of parsing inquiry result"); + } + } else { + log::info("name discovery finished in bad state: {}", + bta_dm_state_text(bta_dm_search_get_state())); + } +} + +/******************************************************************************* + * + * Function bta_dm_is_search_request_queued + * + * Description Checks if there is a queued search request + * + * Returns bool + * + ******************************************************************************/ +bool bta_dm_is_search_request_queued() { + if (!IS_FLAG_ENABLED(separate_service_and_device_discovery)) { + return bta_dm_disc_legacy::bta_dm_is_search_request_queued(); + } + return bta_dm_search_cb.p_pending_search != NULL; +} + +/******************************************************************************* + * + * Function bta_dm_queue_search + * + * Description Queues search command + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_queue_search(tBTA_DM_API_SEARCH& search) { + if (bta_dm_search_cb.p_pending_search) { + log::warn("Overwrote previous device discovery inquiry scan request"); + } + bta_dm_search_cb.p_pending_search.reset(new tBTA_DM_SEARCH_MSG(search)); + log::info("Queued device discovery inquiry scan request"); +} + +/******************************************************************************* + * + * Function bta_dm_observe_results_cb + * + * Description Callback for BLE Observe result + * + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_observe_results_cb(tBTM_INQ_RESULTS* p_inq, + const uint8_t* p_eir, uint16_t eir_len) { + tBTA_DM_SEARCH result; + tBTM_INQ_INFO* p_inq_info; + log::verbose("bta_dm_observe_results_cb"); + + result.inq_res.bd_addr = p_inq->remote_bd_addr; + result.inq_res.original_bda = p_inq->original_bda; + result.inq_res.rssi = p_inq->rssi; + result.inq_res.ble_addr_type = p_inq->ble_addr_type; + result.inq_res.inq_result_type = p_inq->inq_result_type; + result.inq_res.device_type = p_inq->device_type; + result.inq_res.flag = p_inq->flag; + result.inq_res.ble_evt_type = p_inq->ble_evt_type; + result.inq_res.ble_primary_phy = p_inq->ble_primary_phy; + result.inq_res.ble_secondary_phy = p_inq->ble_secondary_phy; + result.inq_res.ble_advertising_sid = p_inq->ble_advertising_sid; + result.inq_res.ble_tx_power = p_inq->ble_tx_power; + result.inq_res.ble_periodic_adv_int = p_inq->ble_periodic_adv_int; + + /* application will parse EIR to find out remote device name */ + result.inq_res.p_eir = const_cast<uint8_t*>(p_eir); + result.inq_res.eir_len = eir_len; + + p_inq_info = + get_btm_client_interface().db.BTM_InqDbRead(p_inq->remote_bd_addr); + if (p_inq_info != NULL) { + /* initialize remt_name_not_required to false so that we get the name by + * default */ + result.inq_res.remt_name_not_required = false; + } + + if (p_inq_info) { + /* application indicates if it knows the remote name, inside the callback + copy that to the inquiry data base*/ + if (result.inq_res.remt_name_not_required) + p_inq_info->appl_knows_rem_name = true; + } +} + +/******************************************************************************* + * + * Function bta_dm_opportunistic_observe_results_cb + * + * Description Callback for BLE Observe result + * + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_opportunistic_observe_results_cb(tBTM_INQ_RESULTS* p_inq, + const uint8_t* p_eir, + uint16_t eir_len) { + tBTA_DM_SEARCH result; + tBTM_INQ_INFO* p_inq_info; + + result.inq_res.bd_addr = p_inq->remote_bd_addr; + result.inq_res.rssi = p_inq->rssi; + result.inq_res.ble_addr_type = p_inq->ble_addr_type; + result.inq_res.inq_result_type = p_inq->inq_result_type; + result.inq_res.device_type = p_inq->device_type; + result.inq_res.flag = p_inq->flag; + result.inq_res.ble_evt_type = p_inq->ble_evt_type; + result.inq_res.ble_primary_phy = p_inq->ble_primary_phy; + result.inq_res.ble_secondary_phy = p_inq->ble_secondary_phy; + result.inq_res.ble_advertising_sid = p_inq->ble_advertising_sid; + result.inq_res.ble_tx_power = p_inq->ble_tx_power; + result.inq_res.ble_periodic_adv_int = p_inq->ble_periodic_adv_int; + + /* application will parse EIR to find out remote device name */ + result.inq_res.p_eir = const_cast<uint8_t*>(p_eir); + result.inq_res.eir_len = eir_len; + + p_inq_info = + get_btm_client_interface().db.BTM_InqDbRead(p_inq->remote_bd_addr); + if (p_inq_info != NULL) { + /* initialize remt_name_not_required to false so that we get the name by + * default */ + result.inq_res.remt_name_not_required = false; + } + + if (bta_dm_search_cb.p_csis_scan_cback) + bta_dm_search_cb.p_csis_scan_cback(BTA_DM_INQ_RES_EVT, &result); + + if (p_inq_info) { + /* application indicates if it knows the remote name, inside the callback + copy that to the inquiry data base*/ + if (result.inq_res.remt_name_not_required) + p_inq_info->appl_knows_rem_name = true; + } +} + +/******************************************************************************* + * + * Function bta_dm_observe_cmpl_cb + * + * Description Callback for BLE Observe complete + * + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_observe_cmpl_cb(void* p_result) { + log::verbose("bta_dm_observe_cmpl_cb"); + + if (bta_dm_search_cb.p_csis_scan_cback) { + auto num_resps = ((tBTM_INQUIRY_CMPL*)p_result)->num_resp; + tBTA_DM_SEARCH data{.observe_cmpl{.num_resps = num_resps}}; + bta_dm_search_cb.p_csis_scan_cback(BTA_DM_OBSERVE_CMPL_EVT, &data); + } +} + +static void bta_dm_start_scan(uint8_t duration_sec, + bool low_latency_scan = false) { + tBTM_STATUS status = get_btm_client_interface().ble.BTM_BleObserve( + true, duration_sec, bta_dm_observe_results_cb, bta_dm_observe_cmpl_cb, + low_latency_scan); + + if (status != BTM_CMD_STARTED) { + log::warn("BTM_BleObserve failed. status {}", status); + if (bta_dm_search_cb.p_csis_scan_cback) { + tBTA_DM_SEARCH data{.observe_cmpl = {.num_resps = 0}}; + bta_dm_search_cb.p_csis_scan_cback(BTA_DM_OBSERVE_CMPL_EVT, &data); + } + } +} + +void bta_dm_ble_scan(bool start, uint8_t duration_sec, + bool low_latency_scan = false) { + if (!start) { + get_btm_client_interface().ble.BTM_BleObserve(false, 0, NULL, NULL, false); + return; + } + + bta_dm_start_scan(duration_sec, low_latency_scan); +} + +void bta_dm_ble_csis_observe(bool observe, tBTA_DM_SEARCH_CBACK* p_cback) { + if (!observe) { + bta_dm_search_cb.p_csis_scan_cback = NULL; + BTM_BleOpportunisticObserve(false, NULL); + return; + } + + /* Save the callback to be called when a scan results are available */ + bta_dm_search_cb.p_csis_scan_cback = p_cback; + BTM_BleOpportunisticObserve(true, bta_dm_opportunistic_observe_results_cb); +} + +namespace bluetooth { +namespace legacy { +namespace testing { + +void bta_dm_remname_cback(const tBTM_REMOTE_DEV_NAME* p) { + ::bta_dm_remname_cback(p); +} + +void bta_dm_remote_name_cmpl(const tBTA_DM_REMOTE_NAME& remote_name_msg) { + ::bta_dm_remote_name_cmpl(remote_name_msg); +} + +} // namespace testing +} // namespace legacy +} // namespace bluetooth + +namespace { +constexpr size_t kSearchStateHistorySize = 50; +constexpr char kTimeFormatString[] = "%Y-%m-%d %H:%M:%S"; + +constexpr unsigned MillisPerSecond = 1000; +std::string EpochMillisToString(long long time_ms) { + time_t time_sec = time_ms / MillisPerSecond; + struct tm tm; + localtime_r(&time_sec, &tm); + std::string s = bluetooth::common::StringFormatTime(kTimeFormatString, tm); + return base::StringPrintf( + "%s.%03u", s.c_str(), + static_cast<unsigned int>(time_ms % MillisPerSecond)); +} + +} // namespace + +struct tSEARCH_STATE_HISTORY { + const tBTA_DM_DEVICE_SEARCH_STATE state; + const tBTA_DM_DEV_SEARCH_EVT event; + std::string ToString() const { + return base::StringPrintf("state:%25s event:%s", + bta_dm_state_text(state).c_str(), + bta_dm_event_text(event).c_str()); + } +}; + +bluetooth::common::TimestampedCircularBuffer<tSEARCH_STATE_HISTORY> + search_state_history_(kSearchStateHistorySize); + +/******************************************************************************* + * + * Function bta_dm_search_sm_execute + * + * Description State machine event handling function for DM + * + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_search_sm_execute(tBTA_DM_DEV_SEARCH_EVT event, + std::unique_ptr<tBTA_DM_SEARCH_MSG> msg) { + log::info("state:{}, event:{}[0x{:x}]", + bta_dm_state_text(bta_dm_search_get_state()), + bta_dm_event_text(event), event); + search_state_history_.Push({ + .state = bta_dm_search_get_state(), + .event = event, + }); + + switch (bta_dm_search_get_state()) { + case BTA_DM_SEARCH_IDLE: + switch (event) { + case BTA_DM_API_SEARCH_EVT: + bta_dm_search_set_state(BTA_DM_SEARCH_ACTIVE); + log::assert_that(std::holds_alternative<tBTA_DM_API_SEARCH>(*msg), + "bad message type: {}", msg->index()); + + bta_dm_search_start(std::get<tBTA_DM_API_SEARCH>(*msg)); + break; + case BTA_DM_API_SEARCH_CANCEL_EVT: + bta_dm_search_clear_queue(); + bta_dm_search_cancel_notify(); + break; + default: + log::info("Received unexpected event {}[0x{:x}] in state {}", + bta_dm_event_text(event), event, + bta_dm_state_text(bta_dm_search_get_state())); + } + break; + case BTA_DM_SEARCH_ACTIVE: + switch (event) { + case BTA_DM_REMT_NAME_EVT: + log::assert_that(std::holds_alternative<tBTA_DM_REMOTE_NAME>(*msg), + "bad message type: {}", msg->index()); + + bta_dm_remote_name_cmpl(std::get<tBTA_DM_REMOTE_NAME>(*msg)); + break; + case BTA_DM_SEARCH_CMPL_EVT: + bta_dm_search_cmpl(); + break; + case BTA_DM_API_SEARCH_CANCEL_EVT: + bta_dm_search_clear_queue(); + bta_dm_search_set_state(BTA_DM_SEARCH_CANCELLING); + bta_dm_search_cancel(); + break; + default: + log::info("Received unexpected event {}[0x{:x}] in state {}", + bta_dm_event_text(event), event, + bta_dm_state_text(bta_dm_search_get_state())); + } + break; + case BTA_DM_SEARCH_CANCELLING: + switch (event) { + case BTA_DM_API_SEARCH_EVT: + log::assert_that(std::holds_alternative<tBTA_DM_API_SEARCH>(*msg), + "bad message type: {}", msg->index()); + + bta_dm_queue_search(std::get<tBTA_DM_API_SEARCH>(*msg)); + break; + case BTA_DM_API_SEARCH_CANCEL_EVT: + bta_dm_search_clear_queue(); + bta_dm_search_cancel_notify(); + break; + case BTA_DM_REMT_NAME_EVT: + case BTA_DM_SEARCH_CMPL_EVT: + bta_dm_search_set_state(BTA_DM_SEARCH_IDLE); + bta_dm_search_cancel_notify(); + bta_dm_execute_queued_search_request(); + break; + default: + log::info("Received unexpected event {}[0x{:x}] in state {}", + bta_dm_event_text(event), event, + bta_dm_state_text(bta_dm_search_get_state())); + } + break; + } +} + +static void bta_dm_disable_search(void) { + switch (bta_dm_search_get_state()) { + case BTA_DM_SEARCH_IDLE: + break; + case BTA_DM_SEARCH_ACTIVE: + case BTA_DM_SEARCH_CANCELLING: + default: + log::debug( + "Search state machine is not idle so issuing search cancel current " + "state:{}", + bta_dm_state_text(bta_dm_search_get_state())); + bta_dm_search_cancel(); + } +} + +void bta_dm_disc_start_device_discovery(tBTA_DM_SEARCH_CBACK* p_cback) { + if (!IS_FLAG_ENABLED(separate_service_and_device_discovery)) { + bta_dm_disc_legacy::bta_dm_disc_start_device_discovery(p_cback); + return; + } + bta_dm_search_sm_execute(BTA_DM_API_SEARCH_EVT, + std::make_unique<tBTA_DM_SEARCH_MSG>( + tBTA_DM_API_SEARCH{.p_cback = p_cback})); +} + +void bta_dm_disc_stop_device_discovery() { + if (!IS_FLAG_ENABLED(separate_service_and_device_discovery)) { + bta_dm_disc_legacy::bta_dm_disc_stop_device_discovery(); + return; + } + bta_dm_search_sm_execute(BTA_DM_API_SEARCH_CANCEL_EVT, nullptr); +} + +static void bta_dm_disc_init_search_cb(tBTA_DM_SEARCH_CB& bta_dm_search_cb) { + bta_dm_search_cb = {}; + bta_dm_search_cb.search_state = BTA_DM_SEARCH_IDLE; +} + +static void bta_dm_search_reset() { + bta_dm_search_cb.p_pending_search.reset(); + bta_dm_disc_init_search_cb(::bta_dm_search_cb); +} + +void bta_dm_search_stop() { + if (!IS_FLAG_ENABLED(separate_service_and_device_discovery)) { + log::info("no-op when flag is disabled"); + return; + } + bta_dm_search_reset(); +} + +void bta_dm_disc_discover_next_device() { + if (!IS_FLAG_ENABLED(separate_service_and_device_discovery)) { + bta_dm_disc_legacy::bta_dm_disc_discover_next_device(); + return; + } + bta_dm_discover_next_device(); +} + +#define DUMPSYS_TAG "shim::legacy::bta::dm" +void DumpsysBtaDmSearch(int fd) { + if (!IS_FLAG_ENABLED(separate_service_and_device_discovery)) { + log::info("no-op when flag is disabled"); + return; + } + auto copy = search_state_history_.Pull(); + LOG_DUMPSYS(fd, " last %zu search state transitions", copy.size()); + for (const auto& it : copy) { + LOG_DUMPSYS(fd, " %s %s", EpochMillisToString(it.timestamp).c_str(), + it.entry.ToString().c_str()); + } + LOG_DUMPSYS(fd, " current bta_dm_search_state:%s", + bta_dm_state_text(bta_dm_search_get_state()).c_str()); +} +#undef DUMPSYS_TAG + +namespace bluetooth { +namespace legacy { +namespace testing { + +void bta_dm_disc_init_search_cb(tBTA_DM_SEARCH_CB& bta_dm_search_cb) { + ::bta_dm_disc_init_search_cb(bta_dm_search_cb); +} +void bta_dm_discover_next_device() { ::bta_dm_discover_next_device(); } + +tBTA_DM_SEARCH_CB bta_dm_disc_get_search_cb() { + tBTA_DM_SEARCH_CB search_cb = {}; + ::bta_dm_disc_init_search_cb(search_cb); + return search_cb; +} +tBTA_DM_SEARCH_CB& bta_dm_disc_search_cb() { return ::bta_dm_search_cb; } +bool bta_dm_read_remote_device_name(const RawAddress& bd_addr, + tBT_TRANSPORT transport) { + return ::bta_dm_read_remote_device_name(bd_addr, transport); +} + +void bta_dm_inq_cmpl() { ::bta_dm_inq_cmpl(); } +void bta_dm_inq_cmpl_cb(void* p_result) { ::bta_dm_inq_cmpl_cb(p_result); } +void bta_dm_observe_cmpl_cb(void* p_result) { + ::bta_dm_observe_cmpl_cb(p_result); +} +void bta_dm_observe_results_cb(tBTM_INQ_RESULTS* p_inq, const uint8_t* p_eir, + uint16_t eir_len) { + ::bta_dm_observe_results_cb(p_inq, p_eir, eir_len); +} +void bta_dm_opportunistic_observe_results_cb(tBTM_INQ_RESULTS* p_inq, + const uint8_t* p_eir, + uint16_t eir_len) { + ::bta_dm_opportunistic_observe_results_cb(p_inq, p_eir, eir_len); +} +void bta_dm_queue_search(tBTA_DM_API_SEARCH& search) { + ::bta_dm_queue_search(search); +} + +void bta_dm_start_scan(uint8_t duration_sec, bool low_latency_scan = false) { + ::bta_dm_start_scan(duration_sec, low_latency_scan); +} + +} // namespace testing +} // namespace legacy +} // namespace bluetooth diff --git a/system/bta/dm/bta_dm_device_search.h b/system/bta/dm/bta_dm_device_search.h new file mode 100644 index 0000000000..c12779440e --- /dev/null +++ b/system/bta/dm/bta_dm_device_search.h @@ -0,0 +1,41 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "bta/include/bta_api.h" // tBTA_DM_SEARCH_CBACK +#include "stack/include/bt_hdr.h" +#include "types/bt_transport.h" +#include "types/raw_address.h" + +// Bta module start and stop entry points +void bta_dm_search_stop(); + +// Bta device discovery start and stop entry points +void bta_dm_disc_start_device_discovery(tBTA_DM_SEARCH_CBACK*); +void bta_dm_disc_stop_device_discovery(); + +void bta_dm_disc_disable_search(); + +// LE observe and scan interface +void bta_dm_ble_scan(bool start, uint8_t duration_sec, bool low_latency_scan); +void bta_dm_ble_csis_observe(bool observe, tBTA_DM_SEARCH_CBACK* p_cback); + +// Checks if there is a device discovery request queued +bool bta_dm_is_search_request_queued(); + +// Provide data for the dumpsys procedure +void DumpsysBtaDmSearch(int fd);
\ No newline at end of file diff --git a/system/bta/dm/bta_dm_device_search_int.h b/system/bta/dm/bta_dm_device_search_int.h new file mode 100644 index 0000000000..14f93129c8 --- /dev/null +++ b/system/bta/dm/bta_dm_device_search_int.h @@ -0,0 +1,101 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <base/strings/stringprintf.h> +#include <bluetooth/log.h> + +#include <queue> +#include <string> + +#include "macros.h" +#include "stack/btm/neighbor_inquiry.h" +#include "types/raw_address.h" + +/* DM search events */ +typedef enum : uint16_t { + /* DM search API events */ + BTA_DM_API_SEARCH_EVT, + BTA_DM_API_SEARCH_CANCEL_EVT, + BTA_DM_INQUIRY_CMPL_EVT, + BTA_DM_REMT_NAME_EVT, + BTA_DM_SEARCH_CMPL_EVT, +} tBTA_DM_DEV_SEARCH_EVT; + +inline std::string bta_dm_event_text(const tBTA_DM_DEV_SEARCH_EVT& event) { + switch (event) { + CASE_RETURN_TEXT(BTA_DM_API_SEARCH_EVT); + CASE_RETURN_TEXT(BTA_DM_API_SEARCH_CANCEL_EVT); + CASE_RETURN_TEXT(BTA_DM_INQUIRY_CMPL_EVT); + CASE_RETURN_TEXT(BTA_DM_REMT_NAME_EVT); + CASE_RETURN_TEXT(BTA_DM_SEARCH_CMPL_EVT); + } +} + +/* data type for BTA_DM_API_SEARCH_EVT */ +typedef struct { + tBTA_DM_SEARCH_CBACK* p_cback; +} tBTA_DM_API_SEARCH; + +typedef struct { + RawAddress bd_addr; + BD_NAME bd_name; /* Name of peer device. */ + tHCI_STATUS hci_status; +} tBTA_DM_REMOTE_NAME; + +using tBTA_DM_SEARCH_MSG = + std::variant<tBTA_DM_API_SEARCH, tBTA_DM_REMOTE_NAME>; + +/* DM search state */ +typedef enum { + BTA_DM_SEARCH_IDLE, + BTA_DM_SEARCH_ACTIVE, + BTA_DM_SEARCH_CANCELLING, +} tBTA_DM_DEVICE_SEARCH_STATE; + +inline std::string bta_dm_state_text(const tBTA_DM_DEVICE_SEARCH_STATE& state) { + switch (state) { + CASE_RETURN_TEXT(BTA_DM_SEARCH_IDLE); + CASE_RETURN_TEXT(BTA_DM_SEARCH_ACTIVE); + CASE_RETURN_TEXT(BTA_DM_SEARCH_CANCELLING); + } +} + +/* DM search control block */ +typedef struct { + tBTA_DM_SEARCH_CBACK* p_device_search_cback; + tBTM_INQ_INFO* p_btm_inq_info; + /* This covers device search state. That is scanning through android Settings + * to discover LE and Classic devices. Runs Name discovery on Inquiry Results + */ + tBTA_DM_DEVICE_SEARCH_STATE search_state; + bool name_discover_done; + /* peer address used for name discovery */ + RawAddress peer_bdaddr; + BD_NAME peer_name; + std::unique_ptr<tBTA_DM_SEARCH_MSG> p_pending_search; + tBTA_DM_SEARCH_CBACK* p_csis_scan_cback; +} tBTA_DM_SEARCH_CB; + +namespace fmt { +template <> +struct formatter<tBTA_DM_DEV_SEARCH_EVT> + : enum_formatter<tBTA_DM_DEV_SEARCH_EVT> {}; +template <> +struct formatter<tBTA_DM_DEVICE_SEARCH_STATE> + : enum_formatter<tBTA_DM_DEVICE_SEARCH_STATE> {}; +} // namespace fmt diff --git a/system/bta/dm/bta_dm_disc.cc b/system/bta/dm/bta_dm_disc.cc index df44bb23b5..30acf769d0 100644 --- a/system/bta/dm/bta_dm_disc.cc +++ b/system/bta/dm/bta_dm_disc.cc @@ -22,8 +22,8 @@ #include <base/functional/bind.h> #include <base/strings/stringprintf.h> #include <bluetooth/log.h> -#include <stddef.h> +#include <cstddef> #include <cstdint> #include <string> #include <variant> @@ -31,6 +31,7 @@ #include "android_bluetooth_flags.h" #include "bta/dm/bta_dm_disc_int.h" +#include "bta/dm/bta_dm_disc_legacy.h" #include "bta/include/bta_gatt_api.h" #include "bta/include/bta_sdp_api.h" #include "btif/include/btif_config.h" @@ -71,13 +72,14 @@ tBTM_CONTRL_STATE bta_dm_pm_obtain_controller_state(void); namespace { constexpr char kBtmLogTag[] = "SDP"; -tBTA_DM_SEARCH_CB bta_dm_search_cb; +tBTA_DM_SERVICE_DISCOVERY_CB bta_dm_discovery_cb; } // namespace -static void bta_dm_search_sm_execute(tBTA_DM_EVT event, - std::unique_ptr<tBTA_DM_MSG> msg); -static void post_disc_evt(tBTA_DM_EVT event, std::unique_ptr<tBTA_DM_MSG> msg) { - if (do_in_main_thread(FROM_HERE, base::BindOnce(&bta_dm_search_sm_execute, +static void bta_dm_disc_sm_execute(tBTA_DM_DISC_EVT event, + std::unique_ptr<tBTA_DM_MSG> msg); +static void post_disc_evt(tBTA_DM_DISC_EVT event, + std::unique_ptr<tBTA_DM_MSG> msg) { + if (do_in_main_thread(FROM_HERE, base::BindOnce(&bta_dm_disc_sm_execute, event, std::move(msg))) != BT_STATUS_SUCCESS) { log::error("post_disc_evt failed"); @@ -85,32 +87,15 @@ static void post_disc_evt(tBTA_DM_EVT event, std::unique_ptr<tBTA_DM_MSG> msg) { } static void bta_dm_gatt_disc_complete(uint16_t conn_id, tGATT_STATUS status); -static void bta_dm_inq_results_cb(tBTM_INQ_RESULTS* p_inq, const uint8_t* p_eir, - uint16_t eir_len); -static void bta_dm_inq_cmpl(); -static void bta_dm_inq_cmpl_cb(void* p_result); -static void bta_dm_service_search_remname_cback(const RawAddress& bd_addr, - DEV_CLASS dc, BD_NAME bd_name); -static void bta_dm_remname_cback(const tBTM_REMOTE_DEV_NAME* p); static void bta_dm_find_services(const RawAddress& bd_addr); -static void bta_dm_discover_next_device(void); static void bta_dm_sdp_callback(const RawAddress& bd_addr, tSDP_STATUS sdp_status); - -static bool bta_dm_read_remote_device_name(const RawAddress& bd_addr, - tBT_TRANSPORT transport); -static void bta_dm_discover_name(const RawAddress& remote_bd_addr); -static void bta_dm_discover_services(const RawAddress& remote_bd_addr); - -static void bta_dm_disable_search_and_disc(void); - +static void bta_dm_disable_disc(void); static void bta_dm_gattc_register(void); static void btm_dm_start_gatt_discovery(const RawAddress& bd_addr); static void bta_dm_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data); -static void bta_dm_search_cmpl(); static void bta_dm_free_sdp_db(); -static void bta_dm_execute_queued_request(); -static void bta_dm_search_cancel_notify(); +static void bta_dm_execute_queued_discovery_request(); static void bta_dm_close_gatt_conn(); TimestampedStringCircularBuffer disc_gatt_history_{50}; @@ -193,19 +178,45 @@ gatt_interface_t& get_gatt_interface() { return *gatt_interface; } } // namespace -void bta_dm_disc_disable_search_and_disc() { bta_dm_disable_search_and_disc(); } +void bta_dm_disc_disable_search_and_disc() { + if (IS_FLAG_ENABLED(separate_service_and_device_discovery)) { + log::info("No one should be calling this when flag is enabled"); + return; + } + bta_dm_disc_legacy::bta_dm_disc_disable_search_and_disc(); +} + +void bta_dm_disc_disable_disc() { + if (!IS_FLAG_ENABLED(separate_service_and_device_discovery)) { + log::info("no-op when flag is disabled"); + return; + } + bta_dm_disable_disc(); +} void bta_dm_disc_gatt_cancel_open(const RawAddress& bd_addr) { + if (!IS_FLAG_ENABLED(separate_service_and_device_discovery)) { + bta_dm_disc_legacy::bta_dm_disc_gatt_cancel_open(bd_addr); + return; + } get_gatt_interface().BTA_GATTC_CancelOpen(0, bd_addr, false); } void bta_dm_disc_gatt_refresh(const RawAddress& bd_addr) { + if (!IS_FLAG_ENABLED(separate_service_and_device_discovery)) { + bta_dm_disc_legacy::bta_dm_disc_gatt_refresh(bd_addr); + return; + } get_gatt_interface().BTA_GATTC_Refresh(bd_addr); } void bta_dm_disc_remove_device(const RawAddress& bd_addr) { - if (bta_dm_search_cb.state == BTA_DM_DISCOVER_ACTIVE && - bta_dm_search_cb.peer_bdaddr == bd_addr) { + if (!IS_FLAG_ENABLED(separate_service_and_device_discovery)) { + bta_dm_disc_legacy::bta_dm_disc_remove_device(bd_addr); + return; + } + if (bta_dm_discovery_cb.service_discovery_state == BTA_DM_DISCOVER_ACTIVE && + bta_dm_discovery_cb.peer_bdaddr == bd_addr) { log::info( "Device removed while service discovery was pending, conclude the " "service disvovery"); @@ -214,13 +225,13 @@ void bta_dm_disc_remove_device(const RawAddress& bd_addr) { } } -void bta_dm_disc_discover_next_device() { bta_dm_discover_next_device(); } - -void bta_dm_disc_gattc_register() { bta_dm_gattc_register(); } - -static void bta_dm_observe_results_cb(tBTM_INQ_RESULTS* p_inq, - const uint8_t* p_eir, uint16_t eir_len); -static void bta_dm_observe_cmpl_cb(void* p_result); +void bta_dm_disc_gattc_register() { + if (!IS_FLAG_ENABLED(separate_service_and_device_discovery)) { + bta_dm_disc_legacy::bta_dm_disc_gattc_register(); + return; + } + bta_dm_gattc_register(); +} const uint16_t bta_service_id_to_uuid_lkup_tbl[BTA_MAX_SERVICE_ID] = { UUID_SERVCLASS_PNP_INFORMATION, /* Reserved */ @@ -258,107 +269,15 @@ const uint16_t bta_service_id_to_uuid_lkup_tbl[BTA_MAX_SERVICE_ID] = { #define MAX_DISC_RAW_DATA_BUF (4096) static uint8_t g_disc_raw_data_buf[MAX_DISC_RAW_DATA_BUF]; -static void bta_dm_search_set_state(tBTA_DM_STATE state) { - bta_dm_search_cb.state = state; +static void bta_dm_discovery_set_state(tBTA_DM_SERVICE_DISCOVERY_STATE state) { + bta_dm_discovery_cb.service_discovery_state = state; } -static tBTA_DM_STATE bta_dm_search_get_state() { - return bta_dm_search_cb.state; +static tBTA_DM_SERVICE_DISCOVERY_STATE bta_dm_discovery_get_state() { + return bta_dm_discovery_cb.service_discovery_state; } -/******************************************************************************* - * - * Function bta_dm_search_start - * - * Description Starts an inquiry - * - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_search_start(tBTA_DM_API_SEARCH& search) { - bta_dm_gattc_register(); - - get_btm_client_interface().db.BTM_ClearInqDb(nullptr); - /* save search params */ - bta_dm_search_cb.p_device_search_cback = search.p_cback; - - const tBTM_STATUS btm_status = - BTM_StartInquiry(bta_dm_inq_results_cb, bta_dm_inq_cmpl_cb); - switch (btm_status) { - case BTM_CMD_STARTED: - // Completion callback will be executed when controller inquiry - // timer pops or is cancelled by the user - break; - default: - log::warn("Unable to start device discovery search btm_status:{}", - btm_status_text(btm_status)); - // Not started so completion callback is executed now - bta_dm_inq_cmpl(); - break; - } -} - -/******************************************************************************* - * - * Function bta_dm_search_cancel - * - * Description Cancels an ongoing search for devices - * - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_search_cancel() { - if (BTM_IsInquiryActive()) { - BTM_CancelInquiry(); - bta_dm_search_cancel_notify(); - bta_dm_search_cmpl(); - } - /* If no Service Search going on then issue cancel remote name in case it is - active */ - else if (!bta_dm_search_cb.name_discover_done) { - get_btm_client_interface().peer.BTM_CancelRemoteDeviceName(); -#ifndef TARGET_FLOSS - /* bta_dm_search_cmpl is called when receiving the remote name cancel evt */ - if (!IS_FLAG_ENABLED( - bta_dm_defer_device_discovery_state_change_until_rnr_complete)) { - bta_dm_search_cmpl(); - } -#endif - } else { - bta_dm_inq_cmpl(); - } -} - -/******************************************************************************* - * - * Function bta_dm_discover - * - * Description Discovers services on a remote device - * - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_discover(tBTA_DM_API_DISCOVER& discover) { - bta_dm_gattc_register(); - - bta_dm_search_cb.service_search_cbacks = discover.cbacks; - bta_dm_search_cb.services_to_search = BTA_ALL_SERVICE_MASK; - bta_dm_search_cb.service_index = 0; - bta_dm_search_cb.services_found = 0; - bta_dm_search_cb.peer_name[0] = 0; - bta_dm_search_cb.p_btm_inq_info = - get_btm_client_interface().db.BTM_InqDbRead(discover.bd_addr); - bta_dm_search_cb.transport = discover.transport; - - bta_dm_search_cb.name_discover_done = false; - - log::info( - "bta_dm_discovery: starting service discovery to {} , transport: {}", - discover.bd_addr, bt_transport_text(discover.transport)); - bta_dm_discover_services(discover.bd_addr); -} +// TODO. Currently we did nothing +static void bta_dm_discovery_cancel() {} /******************************************************************************* * @@ -370,153 +289,18 @@ static void bta_dm_discover(tBTA_DM_API_DISCOVER& discover) { * Returns void * ******************************************************************************/ -static void bta_dm_disable_search_and_disc(void) { - switch (bta_dm_search_get_state()) { - case BTA_DM_SEARCH_IDLE: +static void bta_dm_disable_disc(void) { + switch (bta_dm_discovery_get_state()) { + case BTA_DM_DISCOVER_IDLE: break; - case BTA_DM_SEARCH_ACTIVE: - case BTA_DM_SEARCH_CANCELLING: case BTA_DM_DISCOVER_ACTIVE: default: log::debug( - "Search state machine is not idle so issuing search cancel current " + "Discovery state machine is not idle so issuing discovery cancel " + "current " "state:{}", - bta_dm_state_text(bta_dm_search_get_state())); - bta_dm_search_cancel(); - } -} - -/******************************************************************************* - * - * Function bta_dm_read_remote_device_name - * - * Description Initiate to get remote device name - * - * Returns true if started to get remote name - * - ******************************************************************************/ -static bool bta_dm_read_remote_device_name(const RawAddress& bd_addr, - tBT_TRANSPORT transport) { - tBTM_STATUS btm_status; - - log::verbose(""); - - bta_dm_search_cb.peer_bdaddr = bd_addr; - bta_dm_search_cb.peer_name[0] = 0; - - btm_status = get_btm_client_interface().peer.BTM_ReadRemoteDeviceName( - bta_dm_search_cb.peer_bdaddr, bta_dm_remname_cback, transport); - - if (btm_status == BTM_CMD_STARTED) { - log::verbose("BTM_ReadRemoteDeviceName is started"); - - return (true); - } else if (btm_status == BTM_BUSY) { - log::verbose("BTM_ReadRemoteDeviceName is busy"); - - /* Remote name discovery is on going now so BTM cannot notify through - * "bta_dm_remname_cback" */ - /* adding callback to get notified that current reading remote name done */ - - get_btm_client_interface().security.BTM_SecAddRmtNameNotifyCallback( - &bta_dm_service_search_remname_cback); - - return (true); - } else { - log::warn("BTM_ReadRemoteDeviceName returns 0x{:02X}", btm_status); - - return (false); - } -} - -/******************************************************************************* - * - * Function bta_dm_inq_cmpl - * - * Description Process the inquiry complete event from BTM - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_inq_cmpl() { - if (bta_dm_search_get_state() == BTA_DM_SEARCH_CANCELLING) { - bta_dm_search_set_state(BTA_DM_SEARCH_IDLE); - bta_dm_execute_queued_request(); - return; - } - - if (bta_dm_search_get_state() != BTA_DM_SEARCH_ACTIVE) { - return; - } - - log::verbose("bta_dm_inq_cmpl"); - - bta_dm_search_cb.p_btm_inq_info = - get_btm_client_interface().db.BTM_InqDbFirst(); - if (bta_dm_search_cb.p_btm_inq_info != NULL) { - /* start name discovery from the first device on inquiry result - */ - bta_dm_search_cb.name_discover_done = false; - bta_dm_search_cb.peer_name[0] = 0; - bta_dm_discover_name( - bta_dm_search_cb.p_btm_inq_info->results.remote_bd_addr); - } else { - bta_dm_search_cmpl(); - } -} - -static void bta_dm_remote_name_cmpl( - const tBTA_DM_REMOTE_NAME& remote_name_msg) { - BTM_LogHistory(kBtmLogTag, remote_name_msg.bd_addr, "Remote name completed", - base::StringPrintf( - "status:%s state:%s name:\"%s\"", - hci_status_code_text(remote_name_msg.hci_status).c_str(), - bta_dm_state_text(bta_dm_search_get_state()).c_str(), - PRIVATE_NAME(remote_name_msg.bd_name))); - - tBTM_INQ_INFO* p_btm_inq_info = - get_btm_client_interface().db.BTM_InqDbRead(remote_name_msg.bd_addr); - if (!bd_name_is_empty(remote_name_msg.bd_name) && p_btm_inq_info) { - p_btm_inq_info->appl_knows_rem_name = true; - } - - // Callback with this property - if (bta_dm_search_cb.p_device_search_cback != nullptr || - bta_dm_search_cb.service_search_cbacks.on_name_read != nullptr) { - // Both device and service search callbacks end up sending event to java. - // It's enough to send callback to just one of them. - if (bta_dm_search_cb.p_device_search_cback != nullptr) { - tBTA_DM_SEARCH search_data = { - .name_res = {.bd_addr = remote_name_msg.bd_addr, .bd_name = {}}, - }; - if (remote_name_msg.hci_status == HCI_SUCCESS) { - bd_name_copy(search_data.name_res.bd_name, remote_name_msg.bd_name); - } - bta_dm_search_cb.p_device_search_cback(BTA_DM_NAME_READ_EVT, - &search_data); - } else if (bta_dm_search_cb.service_search_cbacks.on_name_read != nullptr) { - bta_dm_search_cb.service_search_cbacks.on_name_read( - remote_name_msg.bd_addr, remote_name_msg.hci_status, - remote_name_msg.bd_name); - } - } else { - log::warn("Received remote name complete without callback"); - } - - switch (bta_dm_search_get_state()) { - case BTA_DM_SEARCH_ACTIVE: - bta_dm_discover_name(bta_dm_search_cb.peer_bdaddr); - break; - case BTA_DM_DISCOVER_ACTIVE: - /* TODO: Get rid of this case when Name and Service discovery state - * machines are separated */ - bta_dm_discover_name(remote_name_msg.bd_addr); - break; - case BTA_DM_SEARCH_IDLE: - case BTA_DM_SEARCH_CANCELLING: - log::warn("Received remote name request in state:{}", - bta_dm_state_text(bta_dm_search_get_state())); - break; + bta_dm_state_text(bta_dm_discovery_get_state())); + bta_dm_discovery_cancel(); } } @@ -563,7 +347,7 @@ static void bta_dm_store_audio_profiles_version() { for (const auto& audio_profile : audio_profiles) { tSDP_DISC_REC* sdp_rec = get_legacy_stack_sdp_api()->db.SDP_FindServiceInDb( - bta_dm_search_cb.p_sdp_db, audio_profile.servclass_uuid, NULL); + bta_dm_discovery_cb.p_sdp_db, audio_profile.servclass_uuid, NULL); if (sdp_rec == NULL) continue; if (get_legacy_stack_sdp_api()->record.SDP_FindAttributeInRec( @@ -588,16 +372,23 @@ static void bta_dm_store_audio_profiles_version() { } } -/******************************************************************************* - * - * Function bta_dm_sdp_result - * - * Description Process the discovery result from sdp - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_sdp_result(tBTA_DM_SDP_RESULT& sdp_event) { +static void bta_dm_sdp_result(tSDP_STATUS sdp_result); + +/* Callback from sdp with discovery status */ +static void bta_dm_sdp_callback(const RawAddress& /* bd_addr */, + tSDP_STATUS sdp_status) { + log::info("{}", bta_dm_state_text(bta_dm_discovery_get_state())); + + if (bta_dm_discovery_get_state() == BTA_DM_DISCOVER_IDLE) { + bta_dm_free_sdp_db(); + return; + } + + do_in_main_thread(FROM_HERE, base::BindOnce(&bta_dm_sdp_result, sdp_status)); +} + +/* Process the discovery result from sdp */ +static void bta_dm_sdp_result(tSDP_STATUS sdp_result) { tSDP_DISC_REC* p_sdp_rec = NULL; bool scn_found = false; uint16_t service = 0xFFFF; @@ -605,38 +396,35 @@ static void bta_dm_sdp_result(tBTA_DM_SDP_RESULT& sdp_event) { std::vector<Uuid> uuid_list; - const tSDP_RESULT sdp_result = sdp_event.sdp_result; + if ((sdp_result == SDP_SUCCESS) || (sdp_result == SDP_NO_RECS_MATCH) || + (sdp_result == SDP_DB_FULL)) { + log::verbose("sdp_result::0x{:x}", sdp_result); + std::vector<Uuid> gatt_uuids; - if ((sdp_event.sdp_result == SDP_SUCCESS) || - (sdp_event.sdp_result == SDP_NO_RECS_MATCH) || - (sdp_event.sdp_result == SDP_DB_FULL)) { - log::verbose("sdp_result::0x{:x}", sdp_event.sdp_result); do { p_sdp_rec = NULL; - if (bta_dm_search_cb.service_index == (BTA_USER_SERVICE_ID + 1)) { + if (bta_dm_discovery_cb.service_index == (BTA_USER_SERVICE_ID + 1)) { if (p_sdp_rec && get_legacy_stack_sdp_api()->record.SDP_FindProtocolListElemInRec( p_sdp_rec, UUID_PROTOCOL_RFCOMM, &pe)) { - bta_dm_search_cb.peer_scn = (uint8_t)pe.params[0]; + bta_dm_discovery_cb.peer_scn = (uint8_t)pe.params[0]; scn_found = true; } } else { service = - bta_service_id_to_uuid_lkup_tbl[bta_dm_search_cb.service_index - 1]; + bta_service_id_to_uuid_lkup_tbl[bta_dm_discovery_cb.service_index - + 1]; p_sdp_rec = get_legacy_stack_sdp_api()->db.SDP_FindServiceInDb( - bta_dm_search_cb.p_sdp_db, service, p_sdp_rec); + bta_dm_discovery_cb.p_sdp_db, service, p_sdp_rec); } /* finished with BR/EDR services, now we check the result for GATT based * service UUID */ - if (bta_dm_search_cb.service_index == BTA_MAX_SERVICE_ID) { + if (bta_dm_discovery_cb.service_index == BTA_MAX_SERVICE_ID) { /* all GATT based services */ - - std::vector<Uuid> gatt_uuids; - do { /* find a service record, report it */ p_sdp_rec = get_legacy_stack_sdp_api()->db.SDP_FindServiceInDb( - bta_dm_search_cb.p_sdp_db, 0, p_sdp_rec); + bta_dm_discovery_cb.p_sdp_db, 0, p_sdp_rec); if (p_sdp_rec) { Uuid service_uuid; if (get_legacy_stack_sdp_api()->record.SDP_FindServiceUUIDInRec( @@ -648,45 +436,36 @@ static void bta_dm_sdp_result(tBTA_DM_SDP_RESULT& sdp_event) { if (!gatt_uuids.empty()) { log::info("GATT services discovered using SDP"); - - // send all result back to app - BD_NAME bd_name; - bd_name_from_char_pointer(bd_name, bta_dm_get_remname()); - - bta_dm_search_cb.service_search_cbacks.on_gatt_results( - bta_dm_search_cb.peer_bdaddr, bd_name, gatt_uuids, - /* transport_le */ false); } } else { if ((p_sdp_rec != NULL)) { if (service != UUID_SERVCLASS_PNP_INFORMATION) { - bta_dm_search_cb.services_found |= + bta_dm_discovery_cb.services_found |= (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK( - bta_dm_search_cb.service_index - 1)); - uint16_t tmp_svc = - bta_service_id_to_uuid_lkup_tbl[bta_dm_search_cb.service_index - - 1]; + bta_dm_discovery_cb.service_index - 1)); + uint16_t tmp_svc = bta_service_id_to_uuid_lkup_tbl + [bta_dm_discovery_cb.service_index - 1]; /* Add to the list of UUIDs */ uuid_list.push_back(Uuid::From16Bit(tmp_svc)); } } } - if (bta_dm_search_cb.services_to_search == 0) { - bta_dm_search_cb.service_index++; + if (bta_dm_discovery_cb.services_to_search == 0) { + bta_dm_discovery_cb.service_index++; } else /* regular one service per search or PNP search */ break; - } while (bta_dm_search_cb.service_index <= BTA_MAX_SERVICE_ID); + } while (bta_dm_discovery_cb.service_index <= BTA_MAX_SERVICE_ID); - log::verbose("services_found = {:04x}", bta_dm_search_cb.services_found); + log::verbose("services_found = {:04x}", bta_dm_discovery_cb.services_found); /* Collect the 128-bit services here and put them into the list */ p_sdp_rec = NULL; do { /* find a service record, report it */ p_sdp_rec = get_legacy_stack_sdp_api()->db.SDP_FindServiceInDb_128bit( - bta_dm_search_cb.p_sdp_db, p_sdp_rec); + bta_dm_discovery_cb.p_sdp_db, p_sdp_rec); if (p_sdp_rec) { // SDP_FindServiceUUIDInRec_128bit is used only once, refactor? Uuid temp_uuid; @@ -699,99 +478,93 @@ static void bta_dm_sdp_result(tBTA_DM_SDP_RESULT& sdp_event) { if (bluetooth::common::init_flags:: dynamic_avrcp_version_enhancement_is_enabled() && - bta_dm_search_cb.services_to_search == 0) { + bta_dm_discovery_cb.services_to_search == 0) { bta_dm_store_audio_profiles_version(); } #if TARGET_FLOSS tSDP_DI_GET_RECORD di_record; if (get_legacy_stack_sdp_api()->device_id.SDP_GetDiRecord( - 1, &di_record, bta_dm_search_cb.p_sdp_db) == SDP_SUCCESS) { - bta_dm_search_cb.service_search_cbacks.on_did_received( - bta_dm_search_cb.peer_bdaddr, di_record.rec.vendor_id_source, + 1, &di_record, bta_dm_discovery_cb.p_sdp_db) == SDP_SUCCESS) { + bta_dm_discovery_cb.service_search_cbacks.on_did_received( + bta_dm_discovery_cb.peer_bdaddr, di_record.rec.vendor_id_source, di_record.rec.vendor, di_record.rec.product, di_record.rec.version); } #endif /* if there are more services to search for */ - if (bta_dm_search_cb.services_to_search) { + if (bta_dm_discovery_cb.services_to_search) { /* Free up the p_sdp_db before checking the next one */ bta_dm_free_sdp_db(); - bta_dm_find_services(bta_dm_search_cb.peer_bdaddr); + bta_dm_find_services(bta_dm_discovery_cb.peer_bdaddr); } else { /* callbacks */ /* start next bd_addr if necessary */ - - get_btm_client_interface().security.BTM_SecDeleteRmtNameNotifyCallback( - &bta_dm_service_search_remname_cback); - BTM_LogHistory( - kBtmLogTag, bta_dm_search_cb.peer_bdaddr, "Discovery completed", + kBtmLogTag, bta_dm_discovery_cb.peer_bdaddr, "Discovery completed", base::StringPrintf("Result:%s services_found:0x%x service_index:0x%d", sdp_result_text(sdp_result).c_str(), - bta_dm_search_cb.services_found, - bta_dm_search_cb.service_index)); + bta_dm_discovery_cb.services_found, + bta_dm_discovery_cb.service_index)); auto msg = std::make_unique<tBTA_DM_MSG>(tBTA_DM_SVC_RES{}); auto& disc_result = std::get<tBTA_DM_SVC_RES>(*msg); disc_result.result = BTA_SUCCESS; disc_result.uuids = std::move(uuid_list); + disc_result.gatt_uuids = std::move(gatt_uuids); // Copy the raw_data to the discovery result structure - if (bta_dm_search_cb.p_sdp_db != NULL && - bta_dm_search_cb.p_sdp_db->raw_used != 0 && - bta_dm_search_cb.p_sdp_db->raw_data != NULL) { + if (bta_dm_discovery_cb.p_sdp_db != NULL && + bta_dm_discovery_cb.p_sdp_db->raw_used != 0 && + bta_dm_discovery_cb.p_sdp_db->raw_data != NULL) { log::verbose("raw_data used = 0x{:x} raw_data_ptr = 0x{}", - bta_dm_search_cb.p_sdp_db->raw_used, - fmt::ptr(bta_dm_search_cb.p_sdp_db->raw_data)); + bta_dm_discovery_cb.p_sdp_db->raw_used, + fmt::ptr(bta_dm_discovery_cb.p_sdp_db->raw_data)); - bta_dm_search_cb.p_sdp_db->raw_data = + bta_dm_discovery_cb.p_sdp_db->raw_data = NULL; // no need to free this - it is a global assigned. - bta_dm_search_cb.p_sdp_db->raw_used = 0; - bta_dm_search_cb.p_sdp_db->raw_size = 0; + bta_dm_discovery_cb.p_sdp_db->raw_used = 0; + bta_dm_discovery_cb.p_sdp_db->raw_size = 0; } else { log::verbose("raw data size is 0 or raw_data is null!!"); } /* Done with p_sdp_db. Free it */ bta_dm_free_sdp_db(); - disc_result.services = bta_dm_search_cb.services_found; + disc_result.services = bta_dm_discovery_cb.services_found; // Piggy back the SCN over result field if (scn_found) { disc_result.result = - static_cast<tBTA_STATUS>((3 + bta_dm_search_cb.peer_scn)); + static_cast<tBTA_STATUS>((3 + bta_dm_discovery_cb.peer_scn)); disc_result.services |= BTA_USER_SERVICE_MASK; log::verbose("Piggy back the SCN over result field SCN={}", - bta_dm_search_cb.peer_scn); + bta_dm_discovery_cb.peer_scn); } - disc_result.bd_addr = bta_dm_search_cb.peer_bdaddr; + disc_result.bd_addr = bta_dm_discovery_cb.peer_bdaddr; - bta_dm_search_sm_execute(BTA_DM_DISCOVERY_RESULT_EVT, std::move(msg)); + bta_dm_disc_sm_execute(BTA_DM_DISCOVERY_RESULT_EVT, std::move(msg)); } } else { BTM_LogHistory( - kBtmLogTag, bta_dm_search_cb.peer_bdaddr, "Discovery failed", + kBtmLogTag, bta_dm_discovery_cb.peer_bdaddr, "Discovery failed", base::StringPrintf("Result:%s", sdp_result_text(sdp_result).c_str())); log::error("SDP connection failed {}", sdp_status_text(sdp_result)); - if (sdp_event.sdp_result == SDP_CONN_FAILED) - bta_dm_search_cb.wait_disc = false; + if (sdp_result == SDP_CONN_FAILED) + bta_dm_discovery_cb.wait_disc = false; /* not able to connect go to next device */ - if (bta_dm_search_cb.p_sdp_db) - osi_free_and_reset((void**)&bta_dm_search_cb.p_sdp_db); - - get_btm_client_interface().security.BTM_SecDeleteRmtNameNotifyCallback( - &bta_dm_service_search_remname_cback); + if (bta_dm_discovery_cb.p_sdp_db) + osi_free_and_reset((void**)&bta_dm_discovery_cb.p_sdp_db); auto msg = std::make_unique<tBTA_DM_MSG>(tBTA_DM_SVC_RES{}); auto& disc_result = std::get<tBTA_DM_SVC_RES>(*msg); disc_result.result = BTA_FAILURE; - disc_result.services = bta_dm_search_cb.services_found; - disc_result.bd_addr = bta_dm_search_cb.peer_bdaddr; + disc_result.services = bta_dm_discovery_cb.services_found; + disc_result.bd_addr = bta_dm_discovery_cb.peer_bdaddr; - bta_dm_search_sm_execute(BTA_DM_DISCOVERY_RESULT_EVT, std::move(msg)); + bta_dm_disc_sm_execute(BTA_DM_DISCOVERY_RESULT_EVT, std::move(msg)); } } @@ -802,132 +575,58 @@ static void bta_dm_read_dis_cmpl(const RawAddress& addr, if (!p_dis_value) { log::warn("read DIS failed"); } else { - bta_dm_search_cb.service_search_cbacks.on_did_received( + bta_dm_discovery_cb.service_search_cbacks.on_did_received( addr, p_dis_value->pnp_id.vendor_id_src, p_dis_value->pnp_id.vendor_id, p_dis_value->pnp_id.product_id, p_dis_value->pnp_id.product_version); } - bta_dm_execute_queued_request(); + bta_dm_execute_queued_discovery_request(); } #endif /******************************************************************************* * - * Function bta_dm_search_cmpl + * Function bta_dm_disc_result * - * Description Sends event to application + * Description Service discovery result when discovering services on a + * device * * Returns void * ******************************************************************************/ -static void bta_dm_search_cmpl() { - bta_dm_search_set_state(BTA_DM_SEARCH_IDLE); - - uint16_t conn_id = bta_dm_search_cb.conn_id; - - std::vector<Uuid> gatt_services; +static void bta_dm_disc_result(tBTA_DM_SVC_RES& disc_result) { + log::verbose(""); - bool send_gatt_results = - bluetooth::common::init_flags:: - always_send_services_if_gatt_disc_done_is_enabled() - ? bta_dm_search_cb.gatt_disc_active - : false; - - /* no BLE connection, i.e. Classic service discovery end */ - if (conn_id == GATT_INVALID_CONN_ID) { - if (bta_dm_search_cb.gatt_disc_active) { - log::warn( - "GATT active but no BLE connection, likely disconnected midway " - "through"); - } else { - log::info("No BLE connection, processing classic results"); + /* if any BR/EDR service discovery has been done, report the event */ + if (!disc_result.is_gatt_over_ble) { + auto& r = disc_result; + if (!r.gatt_uuids.empty()) { + log::info("Sending GATT services discovered using SDP"); + // send GATT result back to app, if any + bta_dm_discovery_cb.service_search_cbacks.on_gatt_results( + r.bd_addr, BD_NAME{}, r.gatt_uuids, /* transport_le */ false); } + bta_dm_discovery_cb.service_search_cbacks.on_service_discovery_results( + r.bd_addr, r.services, r.uuids, r.result, r.hci_status); } else { - btgatt_db_element_t* db = NULL; - int count = 0; - get_gatt_interface().BTA_GATTC_GetGattDb(conn_id, 0x0000, 0xFFFF, &db, - &count); - if (count != 0) { - for (int i = 0; i < count; i++) { - // we process service entries only - if (db[i].type == BTGATT_DB_PRIMARY_SERVICE) { - gatt_services.push_back(db[i].uuid); - } - } - osi_free(db); - log::info( - "GATT services discovered using LE Transport, will always send to " - "upper layer"); - send_gatt_results = true; - } else { - log::warn("Empty GATT database - no BLE services discovered"); - } - } + GAP_BleReadPeerPrefConnParams(bta_dm_discovery_cb.peer_bdaddr); - // send all result back to app - if (send_gatt_results) { - if (bta_dm_search_cb.service_search_cbacks.on_gatt_results != nullptr) { - log::info("Sending GATT results to upper layer"); - - BD_NAME bd_name; - bd_name_from_char_pointer(bd_name, bta_dm_get_remname()); - bta_dm_search_cb.service_search_cbacks.on_gatt_results( - bta_dm_search_cb.peer_bdaddr, bd_name, gatt_services, - /* transport_le */ true); - } else { - log::warn("on_gatt_results is nullptr!"); - } + bta_dm_discovery_cb.service_search_cbacks.on_gatt_results( + bta_dm_discovery_cb.peer_bdaddr, BD_NAME{}, disc_result.gatt_uuids, + /* transport_le */ true); } - if (bta_dm_search_cb.p_device_search_cback) { - bta_dm_search_cb.p_device_search_cback(BTA_DM_DISC_CMPL_EVT, nullptr); - } - bta_dm_search_cb.gatt_disc_active = false; + bta_dm_discovery_set_state(BTA_DM_DISCOVER_IDLE); #if TARGET_FLOSS - if (conn_id != GATT_INVALID_CONN_ID && - DIS_ReadDISInfo(bta_dm_search_cb.peer_bdaddr, bta_dm_read_dis_cmpl, + if (bta_dm_discovery_cb.conn_id != GATT_INVALID_CONN_ID && + DIS_ReadDISInfo(bta_dm_discovery_cb.peer_bdaddr, bta_dm_read_dis_cmpl, DIS_ATTR_PNP_ID_BIT)) { return; } #endif - bta_dm_execute_queued_request(); -} - -/******************************************************************************* - * - * Function bta_dm_disc_result - * - * Description Service discovery result when discovering services on a - * device - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_disc_result(tBTA_DM_SVC_RES& disc_result) { - log::verbose(""); - - /* disc_res.device_type is set only when GATT discovery is finished in - * bta_dm_gatt_disc_complete */ - bool is_gatt_over_ble = ((disc_result.device_type & BT_DEVICE_TYPE_BLE) != 0); - - /* if any BR/EDR service discovery has been done, report the event */ - if (!is_gatt_over_ble) { - auto& r = disc_result; - bta_dm_search_cb.service_search_cbacks.on_service_discovery_results( - r.bd_addr, r.services, r.device_type, r.uuids, r.result, r.hci_status); - } - - /* Services were discovered while device search is in progress. - * Don't execute bta_dm_search_cmpl, as it would also finish the device - * search. It will be executed later when device search is finished. */ - if (bta_dm_search_get_state() != BTA_DM_SEARCH_ACTIVE) { - get_gatt_interface().BTA_GATTC_CancelOpen(0, bta_dm_search_cb.peer_bdaddr, - true); - - bta_dm_search_cmpl(); - } + bta_dm_execute_queued_discovery_request(); } /******************************************************************************* @@ -940,24 +639,7 @@ static void bta_dm_disc_result(tBTA_DM_SVC_RES& disc_result) { * ******************************************************************************/ static void bta_dm_free_sdp_db() { - osi_free_and_reset((void**)&bta_dm_search_cb.p_sdp_db); -} - -/******************************************************************************* - * - * Function bta_dm_queue_search - * - * Description Queues search command - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_queue_search(tBTA_DM_API_SEARCH& search) { - if (bta_dm_search_cb.p_pending_search) { - log::warn("Overwrote previous device discovery inquiry scan request"); - } - bta_dm_search_cb.p_pending_search.reset(new tBTA_DM_MSG(search)); - log::info("Queued device discovery inquiry scan request"); + osi_free_and_reset((void**)&bta_dm_discovery_cb.p_sdp_db); } /******************************************************************************* @@ -972,90 +654,22 @@ static void bta_dm_queue_search(tBTA_DM_API_SEARCH& search) { static void bta_dm_queue_disc(tBTA_DM_API_DISCOVER& discovery) { log::info("bta_dm_discovery: queuing service discovery to {}", discovery.bd_addr); - bta_dm_search_cb.pending_discovery_queue.push(discovery); + bta_dm_discovery_cb.pending_discovery_queue.push(discovery); } -/******************************************************************************* - * - * Function bta_dm_execute_queued_request - * - * Description Executes queued request if one exists - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_execute_queued_request() { - if (!bta_dm_search_cb.pending_discovery_queue.empty()) { - tBTA_DM_API_DISCOVER pending_discovery = - bta_dm_search_cb.pending_discovery_queue.front(); - bta_dm_search_cb.pending_discovery_queue.pop(); - log::info("Start pending discovery"); - post_disc_evt( - BTA_DM_API_DISCOVER_EVT, - std::make_unique<tBTA_DM_MSG>(tBTA_DM_API_DISCOVER{pending_discovery})); - } else if (bta_dm_search_cb.p_pending_search) { - log::info("Start pending search"); - post_disc_evt(BTA_DM_API_SEARCH_EVT, - std::move(bta_dm_search_cb.p_pending_search)); - bta_dm_search_cb.p_pending_search.reset(); - } -} - -/******************************************************************************* - * - * Function bta_dm_is_search_request_queued - * - * Description Checks if there is a queued search request - * - * Returns bool - * - ******************************************************************************/ -bool bta_dm_is_search_request_queued() { - return bta_dm_search_cb.p_pending_search != NULL; -} - -/******************************************************************************* - * - * Function bta_dm_search_clear_queue - * - * Description Clears the queue if API search cancel is called - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_search_clear_queue() { - bta_dm_search_cb.p_pending_search.reset(); - if (bluetooth::common::InitFlags:: - IsBtmDmFlushDiscoveryQueueOnSearchCancel()) { - bta_dm_search_cb.pending_discovery_queue = {}; +static void bta_dm_execute_queued_discovery_request() { + if (bta_dm_discovery_cb.pending_discovery_queue.empty()) { + log::info("No more service discovery queued"); + return; } -} -/******************************************************************************* - * - * Function bta_dm_search_cancel_notify - * - * Description Notify application that search has been cancelled - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_search_cancel_notify() { - if (bta_dm_search_cb.p_device_search_cback) { - bta_dm_search_cb.p_device_search_cback(BTA_DM_SEARCH_CANCEL_CMPL_EVT, NULL); - } - switch (bta_dm_search_get_state()) { - case BTA_DM_SEARCH_ACTIVE: - case BTA_DM_SEARCH_CANCELLING: - if (!bta_dm_search_cb.name_discover_done) { - get_btm_client_interface().peer.BTM_CancelRemoteDeviceName(); - } - break; - case BTA_DM_SEARCH_IDLE: - case BTA_DM_DISCOVER_ACTIVE: - // Nothing to do - break; - } + tBTA_DM_API_DISCOVER pending_discovery = + bta_dm_discovery_cb.pending_discovery_queue.front(); + bta_dm_discovery_cb.pending_discovery_queue.pop(); + log::info("Start pending discovery"); + post_disc_evt( + BTA_DM_API_DISCOVER_EVT, + std::make_unique<tBTA_DM_MSG>(tBTA_DM_API_DISCOVER{pending_discovery})); } /******************************************************************************* @@ -1068,661 +682,163 @@ static void bta_dm_search_cancel_notify() { * ******************************************************************************/ static void bta_dm_find_services(const RawAddress& bd_addr) { - while (bta_dm_search_cb.service_index < BTA_MAX_SERVICE_ID) { - Uuid uuid = Uuid::kEmpty; - if (bta_dm_search_cb.services_to_search & + while (bta_dm_discovery_cb.service_index < BTA_MAX_SERVICE_ID) { + if (bta_dm_discovery_cb.services_to_search & (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK( - bta_dm_search_cb.service_index))) { - bta_dm_search_cb.p_sdp_db = - (tSDP_DISCOVERY_DB*)osi_malloc(BTA_DM_SDP_DB_SIZE); - - /* try to search all services by search based on L2CAP UUID */ - log::info("services_to_search={:08x}", - bta_dm_search_cb.services_to_search); - if (bta_dm_search_cb.services_to_search & BTA_RES_SERVICE_MASK) { - uuid = Uuid::From16Bit(bta_service_id_to_uuid_lkup_tbl[0]); - bta_dm_search_cb.services_to_search &= ~BTA_RES_SERVICE_MASK; - } else { - uuid = Uuid::From16Bit(UUID_PROTOCOL_L2CAP); - bta_dm_search_cb.services_to_search = 0; - } - - log::info("search UUID = {}", uuid.ToString()); - get_legacy_stack_sdp_api()->service.SDP_InitDiscoveryDb( - bta_dm_search_cb.p_sdp_db, BTA_DM_SDP_DB_SIZE, 1, &uuid, 0, NULL); - - memset(g_disc_raw_data_buf, 0, sizeof(g_disc_raw_data_buf)); - bta_dm_search_cb.p_sdp_db->raw_data = g_disc_raw_data_buf; - - bta_dm_search_cb.p_sdp_db->raw_size = MAX_DISC_RAW_DATA_BUF; - - if (!get_legacy_stack_sdp_api() - ->service.SDP_ServiceSearchAttributeRequest( - bd_addr, bta_dm_search_cb.p_sdp_db, &bta_dm_sdp_callback)) { - /* - * If discovery is not successful with this device, then - * proceed with the next one. - */ - osi_free_and_reset((void**)&bta_dm_search_cb.p_sdp_db); - bta_dm_search_cb.service_index = BTA_MAX_SERVICE_ID; - - } else { - if (uuid == Uuid::From16Bit(UUID_PROTOCOL_L2CAP)) { - if (!is_sdp_pbap_pce_disabled(bd_addr)) { - log::debug("SDP search for PBAP Client"); - BTA_SdpSearch(bd_addr, Uuid::From16Bit(UUID_SERVCLASS_PBAP_PCE)); - } - } - bta_dm_search_cb.service_index++; - return; - } + bta_dm_discovery_cb.service_index))) { + break; } - - bta_dm_search_cb.service_index++; + bta_dm_discovery_cb.service_index++; } /* no more services to be discovered */ - if (bta_dm_search_cb.service_index >= BTA_MAX_SERVICE_ID) { - auto msg = std::make_unique<tBTA_DM_MSG>(tBTA_DM_SVC_RES{}); - auto& disc_result = std::get<tBTA_DM_SVC_RES>(*msg); - disc_result.services = bta_dm_search_cb.services_found; - disc_result.bd_addr = bta_dm_search_cb.peer_bdaddr; - - post_disc_evt(BTA_DM_DISCOVERY_RESULT_EVT, std::move(msg)); - } -} - -/******************************************************************************* - * - * Function bta_dm_discover_next_device - * - * Description Starts discovery on the next device in Inquiry data base - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_discover_next_device(void) { - log::verbose("bta_dm_discover_next_device"); - - /* searching next device on inquiry result */ - bta_dm_search_cb.p_btm_inq_info = get_btm_client_interface().db.BTM_InqDbNext( - bta_dm_search_cb.p_btm_inq_info); - if (bta_dm_search_cb.p_btm_inq_info != NULL) { - bta_dm_search_cb.name_discover_done = false; - bta_dm_search_cb.peer_name[0] = 0; - bta_dm_discover_name( - bta_dm_search_cb.p_btm_inq_info->results.remote_bd_addr); - } else { - post_disc_evt(BTA_DM_SEARCH_CMPL_EVT, nullptr); - } -} - -/******************************************************************************* - * - * Function bta_dm_determine_discovery_transport - * - * Description Starts name and service discovery on the device - * - * Returns void - * - ******************************************************************************/ -static tBT_TRANSPORT bta_dm_determine_discovery_transport( - const RawAddress& remote_bd_addr) { - tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR; - if (bta_dm_search_cb.transport == BT_TRANSPORT_AUTO) { - tBT_DEVICE_TYPE dev_type; - tBLE_ADDR_TYPE addr_type; - - get_btm_client_interface().peer.BTM_ReadDevInfo(remote_bd_addr, &dev_type, - &addr_type); - if (dev_type == BT_DEVICE_TYPE_BLE || addr_type == BLE_ADDR_RANDOM) { - transport = BT_TRANSPORT_LE; - } else if (dev_type == BT_DEVICE_TYPE_DUMO) { - if (get_btm_client_interface().peer.BTM_IsAclConnectionUp( - remote_bd_addr, BT_TRANSPORT_BR_EDR)) { - transport = BT_TRANSPORT_BR_EDR; - } else if (get_btm_client_interface().peer.BTM_IsAclConnectionUp( - remote_bd_addr, BT_TRANSPORT_LE)) { - transport = BT_TRANSPORT_LE; - } - } - } else { - transport = bta_dm_search_cb.transport; - } - return transport; -} - -static void bta_dm_discover_name(const RawAddress& remote_bd_addr) { - const tBT_TRANSPORT transport = - bta_dm_determine_discovery_transport(remote_bd_addr); - - log::verbose("BDA: {}", remote_bd_addr); - - bta_dm_search_cb.peer_bdaddr = remote_bd_addr; - - log::verbose( - "name_discover_done = {} p_btm_inq_info 0x{} state = {}, transport={}", - bta_dm_search_cb.name_discover_done, - fmt::ptr(bta_dm_search_cb.p_btm_inq_info), bta_dm_search_get_state(), - transport); - - if (bta_dm_search_cb.p_btm_inq_info) { - log::verbose("appl_knows_rem_name {}", - bta_dm_search_cb.p_btm_inq_info->appl_knows_rem_name); - } - if (((bta_dm_search_cb.p_btm_inq_info) && - (bta_dm_search_cb.p_btm_inq_info->results.device_type == - BT_DEVICE_TYPE_BLE) && - (bta_dm_search_get_state() == BTA_DM_SEARCH_ACTIVE)) || - (transport == BT_TRANSPORT_LE && - interop_match_addr(INTEROP_DISABLE_NAME_REQUEST, - &bta_dm_search_cb.peer_bdaddr))) { - /* Do not perform RNR for LE devices at inquiry complete*/ - bta_dm_search_cb.name_discover_done = true; - } - // If we already have the name we can skip getting the name - if (BTM_IsRemoteNameKnown(remote_bd_addr, transport) && - bluetooth::common::init_flags::sdp_skip_rnr_if_known_is_enabled()) { - log::debug( - "Security record already known skipping read remote name peer:{}", - remote_bd_addr); - bta_dm_search_cb.name_discover_done = true; - } - - /* if name discovery is not done and application needs remote name */ - if ((!bta_dm_search_cb.name_discover_done) && - ((bta_dm_search_cb.p_btm_inq_info == NULL) || - (bta_dm_search_cb.p_btm_inq_info && - (!bta_dm_search_cb.p_btm_inq_info->appl_knows_rem_name)))) { - if (bta_dm_read_remote_device_name(bta_dm_search_cb.peer_bdaddr, - transport)) { - if (bta_dm_search_get_state() != BTA_DM_DISCOVER_ACTIVE) { - log::debug("Reset transport state for next discovery"); - bta_dm_search_cb.transport = BT_TRANSPORT_AUTO; - } - BTM_LogHistory(kBtmLogTag, bta_dm_search_cb.peer_bdaddr, - "Read remote name", - base::StringPrintf("Transport:%s", - bt_transport_text(transport).c_str())); - return; - } else { - log::error("Unable to start read remote device name"); - } - - /* starting name discovery failed */ - bta_dm_search_cb.name_discover_done = true; + if (bta_dm_discovery_cb.service_index >= BTA_MAX_SERVICE_ID) { + log::info("SDP - no more services to discover"); + bta_dm_disc_sm_execute(BTA_DM_DISCOVERY_RESULT_EVT, + std::make_unique<tBTA_DM_MSG>(tBTA_DM_SVC_RES{ + .bd_addr = bta_dm_discovery_cb.peer_bdaddr, + .services = bta_dm_discovery_cb.services_found, + .result = BTA_SUCCESS})); + return; } - /* Reset transport state for next discovery */ - bta_dm_search_cb.transport = BT_TRANSPORT_AUTO; - - /* name discovery is done for this device */ - if (bta_dm_search_get_state() == BTA_DM_SEARCH_ACTIVE) { - // if p_btm_inq_info is nullptr, there is no more inquiry results to - // discover name for - if (bta_dm_search_cb.p_btm_inq_info) { - bta_dm_discover_next_device(); - } else { - log::info("end of parsing inquiry result"); - } + /* try to search all services by search based on L2CAP UUID */ + log::info("services_to_search={:08x}", + bta_dm_discovery_cb.services_to_search); + Uuid uuid = Uuid::kEmpty; + if (bta_dm_discovery_cb.services_to_search & BTA_RES_SERVICE_MASK) { + uuid = Uuid::From16Bit(bta_service_id_to_uuid_lkup_tbl[0]); + bta_dm_discovery_cb.services_to_search &= ~BTA_RES_SERVICE_MASK; } else { - log::info("name discovery finished in bad state: {}", - bta_dm_state_text(bta_dm_search_get_state())); + uuid = Uuid::From16Bit(UUID_PROTOCOL_L2CAP); + bta_dm_discovery_cb.services_to_search = 0; } -} -static void bta_dm_discover_services(const RawAddress& remote_bd_addr) { - const tBT_TRANSPORT transport = - bta_dm_determine_discovery_transport(remote_bd_addr); - - log::verbose("BDA: {}, transport={}, state = {}", - ADDRESS_TO_LOGGABLE_STR(remote_bd_addr), transport, - bta_dm_search_get_state()); - - bta_dm_search_cb.peer_bdaddr = remote_bd_addr; - - /* Reset transport state for next discovery */ - bta_dm_search_cb.transport = BT_TRANSPORT_AUTO; - - bool sdp_disable = HID_HostSDPDisable(remote_bd_addr); - if (sdp_disable) - log::debug("peer:{} with HIDSDPDisable attribute.", remote_bd_addr); - - /* if application wants to discover service and HIDSDPDisable attribute is - false. - Classic mouses with this attribute should not start SDP here, because the - SDP has been done during bonding. SDP request here will interleave with - connections to the Control or Interrupt channels */ - if (!sdp_disable) { - BTM_LogHistory(kBtmLogTag, remote_bd_addr, "Discovery started ", - base::StringPrintf("Transport:%s", - bt_transport_text(transport).c_str())); - - /* initialize variables */ - bta_dm_search_cb.service_index = 0; - bta_dm_search_cb.services_found = 0; - bta_dm_search_cb.services_to_search = BTA_ALL_SERVICE_MASK; - - /* if seaching with EIR is not completed */ - if (bta_dm_search_cb.services_to_search) { - /* check whether connection already exists to the device - if connection exists, we don't have to wait for ACL - link to go down to start search on next device */ - if (transport == BT_TRANSPORT_BR_EDR) { - if (get_btm_client_interface().peer.BTM_IsAclConnectionUp( - bta_dm_search_cb.peer_bdaddr, BT_TRANSPORT_BR_EDR)) - bta_dm_search_cb.wait_disc = false; - else - bta_dm_search_cb.wait_disc = true; - } - - if (transport == BT_TRANSPORT_LE) { - if (bta_dm_search_cb.services_to_search & BTA_BLE_SERVICE_MASK) { - log::info("bta_dm_discovery: starting GATT discovery on {}", - bta_dm_search_cb.peer_bdaddr); - // set the raw data buffer here - memset(g_disc_raw_data_buf, 0, sizeof(g_disc_raw_data_buf)); - /* start GATT for service discovery */ - btm_dm_start_gatt_discovery(bta_dm_search_cb.peer_bdaddr); - return; - } - } else { - log::info("bta_dm_discovery: starting SDP discovery on {}", - bta_dm_search_cb.peer_bdaddr); - bta_dm_search_cb.sdp_results = false; - bta_dm_find_services(bta_dm_search_cb.peer_bdaddr); - return; - } - } - } - - /* service discovery is done for this device */ - auto msg = std::make_unique<tBTA_DM_MSG>(tBTA_DM_SVC_RES{}); - auto& svc_result = std::get<tBTA_DM_SVC_RES>(*msg); - - /* initialize the data structure */ - svc_result.result = BTA_SUCCESS; - svc_result.services = bta_dm_search_cb.services_found; - svc_result.bd_addr = bta_dm_search_cb.peer_bdaddr; + bta_dm_discovery_cb.p_sdp_db = + (tSDP_DISCOVERY_DB*)osi_malloc(BTA_DM_SDP_DB_SIZE); - bta_dm_search_sm_execute(BTA_DM_DISCOVERY_RESULT_EVT, std::move(msg)); -} - -/******************************************************************************* - * - * Function bta_dm_sdp_callback - * - * Description Callback from sdp with discovery status - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_sdp_callback(const RawAddress& /* bd_addr */, - tSDP_STATUS sdp_status) { - post_disc_evt(BTA_DM_SDP_RESULT_EVT, - std::make_unique<tBTA_DM_MSG>( - tBTA_DM_SDP_RESULT{.sdp_result = sdp_status})); -} + log::info("search UUID = {}", uuid.ToString()); + get_legacy_stack_sdp_api()->service.SDP_InitDiscoveryDb( + bta_dm_discovery_cb.p_sdp_db, BTA_DM_SDP_DB_SIZE, 1, &uuid, 0, NULL); -/******************************************************************************* - * - * Function bta_dm_inq_results_cb - * - * Description Inquiry results callback from BTM - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_inq_results_cb(tBTM_INQ_RESULTS* p_inq, const uint8_t* p_eir, - uint16_t eir_len) { - tBTA_DM_SEARCH result; - tBTM_INQ_INFO* p_inq_info; - uint16_t service_class; - - result.inq_res.bd_addr = p_inq->remote_bd_addr; - - // Pass the original address to GattService#onScanResult - result.inq_res.original_bda = p_inq->original_bda; - - result.inq_res.dev_class = p_inq->dev_class; - BTM_COD_SERVICE_CLASS(service_class, p_inq->dev_class); - result.inq_res.is_limited = - (service_class & BTM_COD_SERVICE_LMTD_DISCOVER) ? true : false; - result.inq_res.rssi = p_inq->rssi; - - result.inq_res.ble_addr_type = p_inq->ble_addr_type; - result.inq_res.inq_result_type = p_inq->inq_result_type; - result.inq_res.device_type = p_inq->device_type; - result.inq_res.flag = p_inq->flag; - result.inq_res.include_rsi = p_inq->include_rsi; - result.inq_res.clock_offset = p_inq->clock_offset; - - /* application will parse EIR to find out remote device name */ - result.inq_res.p_eir = const_cast<uint8_t*>(p_eir); - result.inq_res.eir_len = eir_len; - - result.inq_res.ble_evt_type = p_inq->ble_evt_type; - - p_inq_info = - get_btm_client_interface().db.BTM_InqDbRead(p_inq->remote_bd_addr); - if (p_inq_info != NULL) { - /* initialize remt_name_not_required to false so that we get the name by - * default */ - result.inq_res.remt_name_not_required = false; - } + memset(g_disc_raw_data_buf, 0, sizeof(g_disc_raw_data_buf)); + bta_dm_discovery_cb.p_sdp_db->raw_data = g_disc_raw_data_buf; - if (bta_dm_search_cb.p_device_search_cback) - bta_dm_search_cb.p_device_search_cback(BTA_DM_INQ_RES_EVT, &result); + bta_dm_discovery_cb.p_sdp_db->raw_size = MAX_DISC_RAW_DATA_BUF; - if (p_inq_info) { - /* application indicates if it knows the remote name, inside the callback - copy that to the inquiry data base*/ - if (result.inq_res.remt_name_not_required) - p_inq_info->appl_knows_rem_name = true; + if (!get_legacy_stack_sdp_api()->service.SDP_ServiceSearchAttributeRequest( + bd_addr, bta_dm_discovery_cb.p_sdp_db, &bta_dm_sdp_callback)) { + /* + * If discovery is not successful with this device, then + * proceed with the next one. + */ + osi_free_and_reset((void**)&bta_dm_discovery_cb.p_sdp_db); + bta_dm_discovery_cb.service_index = BTA_MAX_SERVICE_ID; + log::info("SDP not successful"); + bta_dm_disc_sm_execute(BTA_DM_DISCOVERY_RESULT_EVT, + std::make_unique<tBTA_DM_MSG>(tBTA_DM_SVC_RES{ + .bd_addr = bta_dm_discovery_cb.peer_bdaddr, + .services = bta_dm_discovery_cb.services_found, + .result = BTA_SUCCESS})); + return; } -} -/******************************************************************************* - * - * Function bta_dm_inq_cmpl_cb - * - * Description Inquiry complete callback from BTM - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_inq_cmpl_cb(void* /* p_result */) { - log::verbose(""); - - bta_dm_inq_cmpl(); -} - -/******************************************************************************* - * - * Function bta_dm_service_search_remname_cback - * - * Description Remote name call back from BTM during service discovery - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_service_search_remname_cback(const RawAddress& bd_addr, - DEV_CLASS /* dc */, - BD_NAME bd_name) { - tBTM_REMOTE_DEV_NAME rem_name = {}; - tBTM_STATUS btm_status; - - log::verbose("name=<{}>", reinterpret_cast<char const*>(bd_name)); - - /* if this is what we are looking for */ - if (bta_dm_search_cb.peer_bdaddr == bd_addr) { - rem_name.bd_addr = bd_addr; - bd_name_copy(rem_name.remote_bd_name, bd_name); - rem_name.status = BTM_SUCCESS; - rem_name.hci_status = HCI_SUCCESS; - bta_dm_remname_cback(&rem_name); - } else { - /* get name of device */ - btm_status = get_btm_client_interface().peer.BTM_ReadRemoteDeviceName( - bta_dm_search_cb.peer_bdaddr, bta_dm_remname_cback, - BT_TRANSPORT_BR_EDR); - if (btm_status == BTM_BUSY) { - /* wait for next chance(notification of remote name discovery done) */ - log::verbose("BTM_ReadRemoteDeviceName is busy"); - } else if (btm_status != BTM_CMD_STARTED) { - /* if failed to start getting remote name then continue */ - log::warn("BTM_ReadRemoteDeviceName returns 0x{:02X}", btm_status); - - // needed so our response is not ignored, since this corresponds to the - // actual peer_bdaddr - rem_name.bd_addr = bta_dm_search_cb.peer_bdaddr; - rem_name.remote_bd_name[0] = 0; - rem_name.status = btm_status; - rem_name.hci_status = HCI_SUCCESS; - bta_dm_remname_cback(&rem_name); + if (uuid == Uuid::From16Bit(UUID_PROTOCOL_L2CAP)) { + if (!is_sdp_pbap_pce_disabled(bd_addr)) { + log::debug("SDP search for PBAP Client"); + BTA_SdpSearch(bd_addr, Uuid::From16Bit(UUID_SERVCLASS_PBAP_PCE)); } } + bta_dm_discovery_cb.service_index++; } /******************************************************************************* * - * Function bta_dm_remname_cback + * Function bta_dm_determine_discovery_transport * - * Description Remote name complete call back from BTM + * Description Starts name and service discovery on the device * * Returns void * ******************************************************************************/ -static void bta_dm_remname_cback(const tBTM_REMOTE_DEV_NAME* p_remote_name) { - log::assert_that(p_remote_name != nullptr, - "assert failed: p_remote_name != nullptr"); - - log::info( - "Remote name request complete peer:{} btm_status:{} hci_status:{} " - "name[0]:{:c} length:{}", - p_remote_name->bd_addr, btm_status_text(p_remote_name->status), - hci_error_code_text(p_remote_name->hci_status), - p_remote_name->remote_bd_name[0], - strnlen((const char*)p_remote_name->remote_bd_name, BD_NAME_LEN)); - - if (bta_dm_search_cb.peer_bdaddr == p_remote_name->bd_addr) { - get_btm_client_interface().security.BTM_SecDeleteRmtNameNotifyCallback( - &bta_dm_service_search_remname_cback); - } else { - // if we got a different response, maybe ignore it - // we will have made a request directly from BTM_ReadRemoteDeviceName so we - // expect a dedicated response for us - if (p_remote_name->hci_status == HCI_ERR_CONNECTION_EXISTS) { - get_btm_client_interface().security.BTM_SecDeleteRmtNameNotifyCallback( - &bta_dm_service_search_remname_cback); - log::info( - "Assume command failed due to disconnection hci_status:{} peer:{}", - hci_error_code_text(p_remote_name->hci_status), - p_remote_name->bd_addr); - } else { - log::info( - "Ignored remote name response for the wrong address exp:{} act:{}", - bta_dm_search_cb.peer_bdaddr, p_remote_name->bd_addr); - return; +static tBT_TRANSPORT bta_dm_determine_discovery_transport( + const RawAddress& remote_bd_addr) { + tBT_DEVICE_TYPE dev_type; + tBLE_ADDR_TYPE addr_type; + + get_btm_client_interface().peer.BTM_ReadDevInfo(remote_bd_addr, &dev_type, + &addr_type); + if (dev_type == BT_DEVICE_TYPE_BLE || addr_type == BLE_ADDR_RANDOM) { + return BT_TRANSPORT_LE; + } else if (dev_type == BT_DEVICE_TYPE_DUMO) { + if (get_btm_client_interface().peer.BTM_IsAclConnectionUp( + remote_bd_addr, BT_TRANSPORT_BR_EDR)) { + return BT_TRANSPORT_BR_EDR; + } else if (get_btm_client_interface().peer.BTM_IsAclConnectionUp( + remote_bd_addr, BT_TRANSPORT_LE)) { + return BT_TRANSPORT_LE; } } - - /* remote name discovery is done but it could be failed */ - bta_dm_search_cb.name_discover_done = true; - bd_name_copy(bta_dm_search_cb.peer_name, p_remote_name->remote_bd_name); - - if (bta_dm_search_cb.transport == BT_TRANSPORT_LE) { - GAP_BleReadPeerPrefConnParams(bta_dm_search_cb.peer_bdaddr); - } - - auto msg = std::make_unique<tBTA_DM_MSG>(tBTA_DM_REMOTE_NAME{}); - auto& rmt_name_msg = std::get<tBTA_DM_REMOTE_NAME>(*msg); - rmt_name_msg.bd_addr = bta_dm_search_cb.peer_bdaddr; - rmt_name_msg.hci_status = p_remote_name->hci_status; - bd_name_copy(rmt_name_msg.bd_name, p_remote_name->remote_bd_name); - - post_disc_evt(BTA_DM_REMT_NAME_EVT, std::move(msg)); -} - -/******************************************************************************* - * - * Function bta_dm_get_remname - * - * Description Returns a pointer to the remote name stored in the DM - * control block if it exists, or from the BTM memory. - * - * Returns char * - Pointer to the remote device name - ******************************************************************************/ -const char* bta_dm_get_remname(void) { - const char* p_name = (const char*)bta_dm_search_cb.peer_name; - - /* If the name isn't already stored, try retrieving from BTM */ - if (*p_name == '\0') { - const char* p_temp = get_btm_client_interface().security.BTM_SecReadDevName( - bta_dm_search_cb.peer_bdaddr); - if (p_temp != NULL) p_name = (const char*)p_temp; - } - - return p_name; -} - -/******************************************************************************* - * - * Function bta_dm_observe_results_cb - * - * Description Callback for BLE Observe result - * - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_observe_results_cb(tBTM_INQ_RESULTS* p_inq, - const uint8_t* p_eir, uint16_t eir_len) { - tBTA_DM_SEARCH result; - tBTM_INQ_INFO* p_inq_info; - log::verbose("bta_dm_observe_results_cb"); - - result.inq_res.bd_addr = p_inq->remote_bd_addr; - result.inq_res.original_bda = p_inq->original_bda; - result.inq_res.rssi = p_inq->rssi; - result.inq_res.ble_addr_type = p_inq->ble_addr_type; - result.inq_res.inq_result_type = p_inq->inq_result_type; - result.inq_res.device_type = p_inq->device_type; - result.inq_res.flag = p_inq->flag; - result.inq_res.ble_evt_type = p_inq->ble_evt_type; - result.inq_res.ble_primary_phy = p_inq->ble_primary_phy; - result.inq_res.ble_secondary_phy = p_inq->ble_secondary_phy; - result.inq_res.ble_advertising_sid = p_inq->ble_advertising_sid; - result.inq_res.ble_tx_power = p_inq->ble_tx_power; - result.inq_res.ble_periodic_adv_int = p_inq->ble_periodic_adv_int; - - /* application will parse EIR to find out remote device name */ - result.inq_res.p_eir = const_cast<uint8_t*>(p_eir); - result.inq_res.eir_len = eir_len; - - p_inq_info = - get_btm_client_interface().db.BTM_InqDbRead(p_inq->remote_bd_addr); - if (p_inq_info != NULL) { - /* initialize remt_name_not_required to false so that we get the name by - * default */ - result.inq_res.remt_name_not_required = false; - } - - if (p_inq_info) { - /* application indicates if it knows the remote name, inside the callback - copy that to the inquiry data base*/ - if (result.inq_res.remt_name_not_required) - p_inq_info->appl_knows_rem_name = true; - } + return BT_TRANSPORT_BR_EDR; } -/******************************************************************************* - * - * Function bta_dm_opportunistic_observe_results_cb - * - * Description Callback for BLE Observe result - * - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_opportunistic_observe_results_cb(tBTM_INQ_RESULTS* p_inq, - const uint8_t* p_eir, - uint16_t eir_len) { - tBTA_DM_SEARCH result; - tBTM_INQ_INFO* p_inq_info; - - result.inq_res.bd_addr = p_inq->remote_bd_addr; - result.inq_res.rssi = p_inq->rssi; - result.inq_res.ble_addr_type = p_inq->ble_addr_type; - result.inq_res.inq_result_type = p_inq->inq_result_type; - result.inq_res.device_type = p_inq->device_type; - result.inq_res.flag = p_inq->flag; - result.inq_res.ble_evt_type = p_inq->ble_evt_type; - result.inq_res.ble_primary_phy = p_inq->ble_primary_phy; - result.inq_res.ble_secondary_phy = p_inq->ble_secondary_phy; - result.inq_res.ble_advertising_sid = p_inq->ble_advertising_sid; - result.inq_res.ble_tx_power = p_inq->ble_tx_power; - result.inq_res.ble_periodic_adv_int = p_inq->ble_periodic_adv_int; - - /* application will parse EIR to find out remote device name */ - result.inq_res.p_eir = const_cast<uint8_t*>(p_eir); - result.inq_res.eir_len = eir_len; - - p_inq_info = - get_btm_client_interface().db.BTM_InqDbRead(p_inq->remote_bd_addr); - if (p_inq_info != NULL) { - /* initialize remt_name_not_required to false so that we get the name by - * default */ - result.inq_res.remt_name_not_required = false; - } +/* Discovers services on a remote device */ +static void bta_dm_discover_services(tBTA_DM_API_DISCOVER& discover) { + bta_dm_gattc_register(); - if (bta_dm_search_cb.p_csis_scan_cback) - bta_dm_search_cb.p_csis_scan_cback(BTA_DM_INQ_RES_EVT, &result); + RawAddress bd_addr = discover.bd_addr; + tBT_TRANSPORT transport = (discover.transport == BT_TRANSPORT_AUTO) + ? bta_dm_determine_discovery_transport(bd_addr) + : discover.transport; - if (p_inq_info) { - /* application indicates if it knows the remote name, inside the callback - copy that to the inquiry data base*/ - if (result.inq_res.remt_name_not_required) - p_inq_info->appl_knows_rem_name = true; - } -} + log::info("starting service discovery to: {}, transport: {}", bd_addr, + bt_transport_text(transport)); -/******************************************************************************* - * - * Function bta_dm_observe_cmpl_cb - * - * Description Callback for BLE Observe complete - * - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_observe_cmpl_cb(void* p_result) { - log::verbose("bta_dm_observe_cmpl_cb"); + bta_dm_discovery_cb.service_search_cbacks = discover.cbacks; + bta_dm_discovery_cb.services_to_search = BTA_ALL_SERVICE_MASK; + bta_dm_discovery_cb.service_index = 0; + bta_dm_discovery_cb.services_found = 0; - if (bta_dm_search_cb.p_csis_scan_cback) { - auto num_resps = ((tBTM_INQUIRY_CMPL*)p_result)->num_resp; - tBTA_DM_SEARCH data{.observe_cmpl{.num_resps = num_resps}}; - bta_dm_search_cb.p_csis_scan_cback(BTA_DM_OBSERVE_CMPL_EVT, &data); - } -} + bta_dm_discovery_cb.peer_bdaddr = bd_addr; -static void bta_dm_start_scan(uint8_t duration_sec, - bool low_latency_scan = false) { - tBTM_STATUS status = get_btm_client_interface().ble.BTM_BleObserve( - true, duration_sec, bta_dm_observe_results_cb, bta_dm_observe_cmpl_cb, - low_latency_scan); - - if (status != BTM_CMD_STARTED) { - log::warn("BTM_BleObserve failed. status {}", status); - if (bta_dm_search_cb.p_csis_scan_cback) { - tBTA_DM_SEARCH data{.observe_cmpl = {.num_resps = 0}}; - bta_dm_search_cb.p_csis_scan_cback(BTA_DM_OBSERVE_CMPL_EVT, &data); - } - } -} + /* Classic mouses with this attribute should not start SDP here, because the + SDP has been done during bonding. SDP request here will interleave with + connections to the Control or Interrupt channels */ + if (HID_HostSDPDisable(bd_addr)) { + log::info("peer:{} with HIDSDPDisable attribute.", bd_addr); -void bta_dm_ble_scan(bool start, uint8_t duration_sec, - bool low_latency_scan = false) { - if (!start) { - get_btm_client_interface().ble.BTM_BleObserve(false, 0, NULL, NULL, false); + /* service discovery is done for this device */ + bta_dm_disc_sm_execute( + BTA_DM_DISCOVERY_RESULT_EVT, + std::make_unique<tBTA_DM_MSG>(tBTA_DM_SVC_RES{ + .bd_addr = bd_addr, .services = 0, .result = BTA_SUCCESS})); return; } - bta_dm_start_scan(duration_sec, low_latency_scan); -} + BTM_LogHistory( + kBtmLogTag, bd_addr, "Discovery started ", + base::StringPrintf("Transport:%s", bt_transport_text(transport).c_str())); -void bta_dm_ble_csis_observe(bool observe, tBTA_DM_SEARCH_CBACK* p_cback) { - if (!observe) { - bta_dm_search_cb.p_csis_scan_cback = NULL; - BTM_BleOpportunisticObserve(false, NULL); + if (transport == BT_TRANSPORT_LE) { + log::info("starting GATT discovery on {}", bd_addr); + /* start GATT for service discovery */ + btm_dm_start_gatt_discovery(bd_addr); return; } + // transport == BT_TRANSPORT_BR_EDR + + /* check whether connection already exists to the device + if connection exists, we don't have to wait for ACL + link to go down to start search on next device */ + if (get_btm_client_interface().peer.BTM_IsAclConnectionUp( + bd_addr, BT_TRANSPORT_BR_EDR)) + bta_dm_discovery_cb.wait_disc = false; + else + bta_dm_discovery_cb.wait_disc = true; - /* Save the callback to be called when a scan results are available */ - bta_dm_search_cb.p_csis_scan_cback = p_cback; - BTM_BleOpportunisticObserve(true, bta_dm_opportunistic_observe_results_cb); + log::info("starting SDP discovery on {}", bd_addr); + bta_dm_discovery_cb.sdp_results = false; + bta_dm_find_services(bd_addr); } #ifndef BTA_DM_GATT_CLOSE_DELAY_TOUT @@ -1740,7 +856,7 @@ void bta_dm_ble_csis_observe(bool observe, tBTA_DM_SEARCH_CBACK* p_cback) { * ******************************************************************************/ static void bta_dm_gattc_register(void) { - if (bta_dm_search_cb.client_if != BTA_GATTS_INVALID_IF) { + if (bta_dm_discovery_cb.client_if != BTA_GATTS_INVALID_IF) { // Already registered return; } @@ -1754,20 +870,20 @@ static void bta_dm_gattc_register(void) { log::info( "Registered device discovery search gatt client tGATT_IF:{}", client_id); - bta_dm_search_cb.client_if = client_id; + bta_dm_discovery_cb.client_if = client_id; } else { log::warn( "Failed to register device discovery search gatt client " "gatt_status:{} previous tGATT_IF:{}", - bta_dm_search_cb.client_if, status); - bta_dm_search_cb.client_if = BTA_GATTS_INVALID_IF; + bta_dm_discovery_cb.client_if, status); + bta_dm_discovery_cb.client_if = BTA_GATTS_INVALID_IF; } }), false); } static void gatt_close_timer_cb(void*) { - bta_dm_search_sm_execute(BTA_DM_DISC_CLOSE_TOUT_EVT, nullptr); + bta_dm_disc_sm_execute(BTA_DM_DISC_CLOSE_TOUT_EVT, nullptr); } /******************************************************************************* @@ -1780,40 +896,58 @@ static void gatt_close_timer_cb(void*) { * ******************************************************************************/ static void bta_dm_gatt_disc_complete(uint16_t conn_id, tGATT_STATUS status) { - log::verbose("conn_id = {}", conn_id); + log::verbose("conn_id = {}, service found: 0x{:08x}", conn_id, + bta_dm_discovery_cb.services_found); - auto msg = std::make_unique<tBTA_DM_MSG>(tBTA_DM_SVC_RES{}); - auto& svc_result = std::get<tBTA_DM_SVC_RES>(*msg); + std::vector<Uuid> gatt_services; - /* no more services to be discovered */ - svc_result.result = (status == GATT_SUCCESS) ? BTA_SUCCESS : BTA_FAILURE; - log::verbose("service found: 0x{:08x}", bta_dm_search_cb.services_found); - svc_result.services = bta_dm_search_cb.services_found; - svc_result.bd_addr = bta_dm_search_cb.peer_bdaddr; - svc_result.device_type |= BT_DEVICE_TYPE_BLE; + if (conn_id != GATT_INVALID_CONN_ID && status == GATT_SUCCESS) { + btgatt_db_element_t* db = NULL; + int count = 0; + get_gatt_interface().BTA_GATTC_GetGattDb(conn_id, 0x0000, 0xFFFF, &db, + &count); + if (count != 0) { + for (int i = 0; i < count; i++) { + // we process service entries only + if (db[i].type == BTGATT_DB_PRIMARY_SERVICE) { + gatt_services.push_back(db[i].uuid); + } + } + osi_free(db); + } + log::info("GATT services discovered using LE Transport, count: {}", + gatt_services.size()); + } - bta_dm_search_sm_execute(BTA_DM_DISCOVERY_RESULT_EVT, std::move(msg)); + /* no more services to be discovered */ + bta_dm_disc_sm_execute( + BTA_DM_DISCOVERY_RESULT_EVT, + std::make_unique<tBTA_DM_MSG>(tBTA_DM_SVC_RES{ + .bd_addr = bta_dm_discovery_cb.peer_bdaddr, + .services = bta_dm_discovery_cb.services_found, + .is_gatt_over_ble = true, + .gatt_uuids = std::move(gatt_services), + .result = (status == GATT_SUCCESS) ? BTA_SUCCESS : BTA_FAILURE})); if (conn_id != GATT_INVALID_CONN_ID) { - bta_dm_search_cb.pending_close_bda = bta_dm_search_cb.peer_bdaddr; + bta_dm_discovery_cb.pending_close_bda = bta_dm_discovery_cb.peer_bdaddr; // Gatt will be close immediately if bluetooth.gatt.delay_close.enabled is // set to false. If property is true / unset there will be a delay - if (bta_dm_search_cb.gatt_close_timer != nullptr) { + if (bta_dm_discovery_cb.gatt_close_timer != nullptr) { /* start a GATT channel close delay timer */ - alarm_set_on_mloop(bta_dm_search_cb.gatt_close_timer, + alarm_set_on_mloop(bta_dm_discovery_cb.gatt_close_timer, BTA_DM_GATT_CLOSE_DELAY_TOUT, gatt_close_timer_cb, 0); } else { - bta_dm_search_sm_execute(BTA_DM_DISC_CLOSE_TOUT_EVT, nullptr); + bta_dm_disc_sm_execute(BTA_DM_DISC_CLOSE_TOUT_EVT, nullptr); } } else { - bta_dm_search_cb.conn_id = GATT_INVALID_CONN_ID; + bta_dm_discovery_cb.conn_id = GATT_INVALID_CONN_ID; if (IS_FLAG_ENABLED(bta_dm_disc_stuck_in_cancelling_fix)) { log::info( "Discovery complete for invalid conn ID. Will pick up next job"); - bta_dm_search_set_state(BTA_DM_SEARCH_IDLE); - bta_dm_free_sdp_db(); - bta_dm_execute_queued_request(); + bta_dm_discovery_set_state(BTA_DM_DISCOVER_IDLE); + bta_dm_execute_queued_discovery_request(); } } } @@ -1829,11 +963,11 @@ static void bta_dm_gatt_disc_complete(uint16_t conn_id, tGATT_STATUS status) { * ******************************************************************************/ static void bta_dm_close_gatt_conn() { - if (bta_dm_search_cb.conn_id != GATT_INVALID_CONN_ID) - BTA_GATTC_Close(bta_dm_search_cb.conn_id); + if (bta_dm_discovery_cb.conn_id != GATT_INVALID_CONN_ID) + BTA_GATTC_Close(bta_dm_discovery_cb.conn_id); - bta_dm_search_cb.pending_close_bda = RawAddress::kEmpty; - bta_dm_search_cb.conn_id = GATT_INVALID_CONN_ID; + bta_dm_discovery_cb.pending_close_bda = RawAddress::kEmpty; + bta_dm_discovery_cb.conn_id = GATT_INVALID_CONN_ID; } /******************************************************************************* * @@ -1848,15 +982,13 @@ static void bta_dm_close_gatt_conn() { static void btm_dm_start_gatt_discovery(const RawAddress& bd_addr) { constexpr bool kUseOpportunistic = true; - bta_dm_search_cb.gatt_disc_active = true; - /* connection is already open */ - if (bta_dm_search_cb.pending_close_bda == bd_addr && - bta_dm_search_cb.conn_id != GATT_INVALID_CONN_ID) { - bta_dm_search_cb.pending_close_bda = RawAddress::kEmpty; - alarm_cancel(bta_dm_search_cb.gatt_close_timer); + if (bta_dm_discovery_cb.pending_close_bda == bd_addr && + bta_dm_discovery_cb.conn_id != GATT_INVALID_CONN_ID) { + bta_dm_discovery_cb.pending_close_bda = RawAddress::kEmpty; + alarm_cancel(bta_dm_discovery_cb.gatt_close_timer); get_gatt_interface().BTA_GATTC_ServiceSearchRequest( - bta_dm_search_cb.conn_id, nullptr); + bta_dm_discovery_cb.conn_id, nullptr); } else { if (get_btm_client_interface().peer.BTM_IsAclConnectionUp( bd_addr, BT_TRANSPORT_LE)) { @@ -1865,8 +997,8 @@ static void btm_dm_start_gatt_discovery(const RawAddress& bd_addr) { "transport:{} opportunistic:{:c}", bd_addr, bt_transport_text(BT_TRANSPORT_LE), (kUseOpportunistic) ? 'T' : 'F'); - get_gatt_interface().BTA_GATTC_Open(bta_dm_search_cb.client_if, bd_addr, - BTM_BLE_DIRECT_CONNECTION, + get_gatt_interface().BTA_GATTC_Open(bta_dm_discovery_cb.client_if, + bd_addr, BTM_BLE_DIRECT_CONNECTION, kUseOpportunistic); } else { log::debug( @@ -1874,8 +1006,8 @@ static void btm_dm_start_gatt_discovery(const RawAddress& bd_addr) { "transport:{} opportunistic:{:c}", bd_addr, bt_transport_text(BT_TRANSPORT_LE), (!kUseOpportunistic) ? 'T' : 'F'); - get_gatt_interface().BTA_GATTC_Open(bta_dm_search_cb.client_if, bd_addr, - BTM_BLE_DIRECT_CONNECTION, + get_gatt_interface().BTA_GATTC_Open(bta_dm_discovery_cb.client_if, + bd_addr, BTM_BLE_DIRECT_CONNECTION, !kUseOpportunistic); } } @@ -1891,9 +1023,10 @@ static void btm_dm_start_gatt_discovery(const RawAddress& bd_addr) { * ******************************************************************************/ static void bta_dm_proc_open_evt(tBTA_GATTC_OPEN* p_data) { - log::verbose("DM Search state= {} search_cb.peer_dbaddr:{} connected_bda={}", - bta_dm_search_get_state(), bta_dm_search_cb.peer_bdaddr, - p_data->remote_bda); + log::verbose( + "DM Search state= {} bta_dm_discovery_cb.peer_dbaddr:{} connected_bda={}", + bta_dm_discovery_get_state(), bta_dm_discovery_cb.peer_bdaddr, + p_data->remote_bda); log::debug("BTA_GATTC_OPEN_EVT conn_id = {} client_if={} status = {}", p_data->conn_id, p_data->client_if, p_data->status); @@ -1904,7 +1037,7 @@ static void bta_dm_proc_open_evt(tBTA_GATTC_OPEN* p_data) { p_data->conn_id, p_data->client_if, gatt_client_event_text(BTA_GATTC_OPEN_EVT).c_str())); - bta_dm_search_cb.conn_id = p_data->conn_id; + bta_dm_discovery_cb.conn_id = p_data->conn_id; if (p_data->status == GATT_SUCCESS) { get_gatt_interface().BTA_GATTC_ServiceSearchRequest(p_data->conn_id, @@ -1932,15 +1065,9 @@ static void bta_dm_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) { break; case BTA_GATTC_SEARCH_CMPL_EVT: - switch (bta_dm_search_get_state()) { - case BTA_DM_SEARCH_IDLE: - break; - case BTA_DM_SEARCH_ACTIVE: - case BTA_DM_SEARCH_CANCELLING: - case BTA_DM_DISCOVER_ACTIVE: - bta_dm_gatt_disc_complete(p_data->search_cmpl.conn_id, - p_data->search_cmpl.status); - break; + if (bta_dm_discovery_get_state() == BTA_DM_DISCOVER_ACTIVE) { + bta_dm_gatt_disc_complete(p_data->search_cmpl.conn_id, + p_data->search_cmpl.status); } disc_gatt_history_.Push(base::StringPrintf( "%-32s conn_id:%hu status:%s", "GATTC_EventCallback", @@ -1951,22 +1078,16 @@ static void bta_dm_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) { case BTA_GATTC_CLOSE_EVT: log::info("BTA_GATTC_CLOSE_EVT reason = {}", p_data->close.reason); - if (p_data->close.remote_bda == bta_dm_search_cb.peer_bdaddr) { - bta_dm_search_cb.conn_id = GATT_INVALID_CONN_ID; + if (p_data->close.remote_bda == bta_dm_discovery_cb.peer_bdaddr) { + bta_dm_discovery_cb.conn_id = GATT_INVALID_CONN_ID; } - switch (bta_dm_search_get_state()) { - case BTA_DM_SEARCH_IDLE: - case BTA_DM_SEARCH_ACTIVE: - break; - - case BTA_DM_SEARCH_CANCELLING: - case BTA_DM_DISCOVER_ACTIVE: - /* in case of disconnect before search is completed */ - if (p_data->close.remote_bda == bta_dm_search_cb.peer_bdaddr) { - bta_dm_gatt_disc_complete((uint16_t)GATT_INVALID_CONN_ID, - (tGATT_STATUS)GATT_ERROR); - } + if (bta_dm_discovery_get_state() == BTA_DM_DISCOVER_ACTIVE) { + /* in case of disconnect before search is completed */ + if (p_data->close.remote_bda == bta_dm_discovery_cb.peer_bdaddr) { + bta_dm_gatt_disc_complete((uint16_t)GATT_INVALID_CONN_ID, + (tGATT_STATUS)GATT_ERROR); + } } break; @@ -1995,20 +1116,12 @@ namespace bluetooth { namespace legacy { namespace testing { -void bta_dm_remname_cback(const tBTM_REMOTE_DEV_NAME* p) { - ::bta_dm_remname_cback(p); -} - tBT_TRANSPORT bta_dm_determine_discovery_transport(const RawAddress& bd_addr) { return ::bta_dm_determine_discovery_transport(bd_addr); } -void bta_dm_remote_name_cmpl(const tBTA_DM_REMOTE_NAME& remote_name_msg) { - ::bta_dm_remote_name_cmpl(remote_name_msg); -} - -void bta_dm_sdp_result(tBTA_DM_SDP_RESULT& sdp_event) { - ::bta_dm_sdp_result(sdp_event); +void bta_dm_sdp_result(tSDP_STATUS sdp_status) { + ::bta_dm_sdp_result(sdp_status); } } // namespace testing @@ -2016,7 +1129,6 @@ void bta_dm_sdp_result(tBTA_DM_SDP_RESULT& sdp_event) { } // namespace bluetooth namespace { -constexpr size_t kSearchStateHistorySize = 50; constexpr char kTimeFormatString[] = "%Y-%m-%d %H:%M:%S"; constexpr unsigned MillisPerSecond = 1000; @@ -2032,9 +1144,9 @@ std::string EpochMillisToString(long long time_ms) { } // namespace -struct tSEARCH_STATE_HISTORY { - const tBTA_DM_STATE state; - const tBTA_DM_EVT event; +struct tDISCOVERY_STATE_HISTORY { + const tBTA_DM_SERVICE_DISCOVERY_STATE state; + const tBTA_DM_DISC_EVT event; std::string ToString() const { return base::StringPrintf("state:%25s event:%s", bta_dm_state_text(state).c_str(), @@ -2042,52 +1154,28 @@ struct tSEARCH_STATE_HISTORY { } }; -bluetooth::common::TimestampedCircularBuffer<tSEARCH_STATE_HISTORY> - search_state_history_(kSearchStateHistorySize); +bluetooth::common::TimestampedCircularBuffer<tDISCOVERY_STATE_HISTORY> + discovery_state_history_(50 /*history size*/); -/******************************************************************************* - * - * Function bta_dm_search_sm_execute - * - * Description State machine event handling function for DM - * - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_search_sm_execute(tBTA_DM_EVT event, - std::unique_ptr<tBTA_DM_MSG> msg) { +static void bta_dm_disc_sm_execute(tBTA_DM_DISC_EVT event, + std::unique_ptr<tBTA_DM_MSG> msg) { log::info("state:{}, event:{}[0x{:x}]", - bta_dm_state_text(bta_dm_search_get_state()), + bta_dm_state_text(bta_dm_discovery_get_state()), bta_dm_event_text(event), event); - search_state_history_.Push({ - .state = bta_dm_search_get_state(), + discovery_state_history_.Push({ + .state = bta_dm_discovery_get_state(), .event = event, }); - switch (bta_dm_search_get_state()) { - case BTA_DM_SEARCH_IDLE: + switch (bta_dm_discovery_get_state()) { + case BTA_DM_DISCOVER_IDLE: switch (event) { - case BTA_DM_API_SEARCH_EVT: - bta_dm_search_set_state(BTA_DM_SEARCH_ACTIVE); - log::assert_that(std::holds_alternative<tBTA_DM_API_SEARCH>(*msg), - "bad message type: {}", msg->index()); - - bta_dm_search_start(std::get<tBTA_DM_API_SEARCH>(*msg)); - break; case BTA_DM_API_DISCOVER_EVT: - bta_dm_search_set_state(BTA_DM_DISCOVER_ACTIVE); + bta_dm_discovery_set_state(BTA_DM_DISCOVER_ACTIVE); log::assert_that(std::holds_alternative<tBTA_DM_API_DISCOVER>(*msg), "bad message type: {}", msg->index()); - bta_dm_discover(std::get<tBTA_DM_API_DISCOVER>(*msg)); - break; - case BTA_DM_API_SEARCH_CANCEL_EVT: - bta_dm_search_clear_queue(); - bta_dm_search_cancel_notify(); - break; - case BTA_DM_SDP_RESULT_EVT: - bta_dm_free_sdp_db(); + bta_dm_discover_services(std::get<tBTA_DM_API_DISCOVER>(*msg)); break; case BTA_DM_DISC_CLOSE_TOUT_EVT: bta_dm_close_gatt_conn(); @@ -2095,170 +1183,75 @@ static void bta_dm_search_sm_execute(tBTA_DM_EVT event, default: log::info("Received unexpected event {}[0x{:x}] in state {}", bta_dm_event_text(event), event, - bta_dm_state_text(bta_dm_search_get_state())); + bta_dm_state_text(bta_dm_discovery_get_state())); } break; - case BTA_DM_SEARCH_ACTIVE: - switch (event) { - case BTA_DM_REMT_NAME_EVT: - log::assert_that(std::holds_alternative<tBTA_DM_REMOTE_NAME>(*msg), - "bad message type: {}", msg->index()); - bta_dm_remote_name_cmpl(std::get<tBTA_DM_REMOTE_NAME>(*msg)); - break; - case BTA_DM_SEARCH_CMPL_EVT: - bta_dm_search_cmpl(); - break; - case BTA_DM_DISCOVERY_RESULT_EVT: - log::assert_that(std::holds_alternative<tBTA_DM_SVC_RES>(*msg), - "bad message type: {}", msg->index()); - - bta_dm_disc_result(std::get<tBTA_DM_SVC_RES>(*msg)); - break; - case BTA_DM_DISC_CLOSE_TOUT_EVT: - bta_dm_close_gatt_conn(); - break; - case BTA_DM_API_DISCOVER_EVT: - log::assert_that(std::holds_alternative<tBTA_DM_API_DISCOVER>(*msg), - "bad message type: {}", msg->index()); - - bta_dm_queue_disc(std::get<tBTA_DM_API_DISCOVER>(*msg)); - break; - case BTA_DM_API_SEARCH_CANCEL_EVT: - bta_dm_search_clear_queue(); - bta_dm_search_set_state(BTA_DM_SEARCH_CANCELLING); - bta_dm_search_cancel(); - break; - default: - log::info("Received unexpected event {}[0x{:x}] in state {}", - bta_dm_event_text(event), event, - bta_dm_state_text(bta_dm_search_get_state())); - } - break; - case BTA_DM_SEARCH_CANCELLING: - switch (event) { - case BTA_DM_API_SEARCH_EVT: - log::assert_that(std::holds_alternative<tBTA_DM_API_SEARCH>(*msg), - "bad message type: {}", msg->index()); - - bta_dm_queue_search(std::get<tBTA_DM_API_SEARCH>(*msg)); - break; - case BTA_DM_API_DISCOVER_EVT: - log::assert_that(std::holds_alternative<tBTA_DM_API_DISCOVER>(*msg), - "bad message type: {}", msg->index()); - - bta_dm_queue_disc(std::get<tBTA_DM_API_DISCOVER>(*msg)); - break; - case BTA_DM_API_SEARCH_CANCEL_EVT: - bta_dm_search_clear_queue(); - bta_dm_search_cancel_notify(); - break; - case BTA_DM_SDP_RESULT_EVT: - case BTA_DM_REMT_NAME_EVT: - case BTA_DM_SEARCH_CMPL_EVT: - case BTA_DM_DISCOVERY_RESULT_EVT: - bta_dm_search_set_state(BTA_DM_SEARCH_IDLE); - bta_dm_free_sdp_db(); - bta_dm_search_cancel_notify(); - bta_dm_execute_queued_request(); - break; - case BTA_DM_DISC_CLOSE_TOUT_EVT: - bta_dm_close_gatt_conn(); - break; - default: - log::info("Received unexpected event {}[0x{:x}] in state {}", - bta_dm_event_text(event), event, - bta_dm_state_text(bta_dm_search_get_state())); - } - break; case BTA_DM_DISCOVER_ACTIVE: switch (event) { - case BTA_DM_REMT_NAME_EVT: - log::assert_that(std::holds_alternative<tBTA_DM_REMOTE_NAME>(*msg), - "bad message type: {}", msg->index()); - - bta_dm_remote_name_cmpl(std::get<tBTA_DM_REMOTE_NAME>(*msg)); - break; - case BTA_DM_SDP_RESULT_EVT: - log::assert_that(std::holds_alternative<tBTA_DM_SDP_RESULT>(*msg), - "bad message type: {}", msg->index()); - - bta_dm_sdp_result(std::get<tBTA_DM_SDP_RESULT>(*msg)); - break; - case BTA_DM_SEARCH_CMPL_EVT: - bta_dm_search_cmpl(); - break; case BTA_DM_DISCOVERY_RESULT_EVT: log::assert_that(std::holds_alternative<tBTA_DM_SVC_RES>(*msg), "bad message type: {}", msg->index()); bta_dm_disc_result(std::get<tBTA_DM_SVC_RES>(*msg)); break; - case BTA_DM_API_SEARCH_EVT: - log::assert_that(std::holds_alternative<tBTA_DM_API_SEARCH>(*msg), - "bad message type: {}", msg->index()); - - bta_dm_queue_search(std::get<tBTA_DM_API_SEARCH>(*msg)); - break; case BTA_DM_API_DISCOVER_EVT: log::assert_that(std::holds_alternative<tBTA_DM_API_DISCOVER>(*msg), "bad message type: {}", msg->index()); bta_dm_queue_disc(std::get<tBTA_DM_API_DISCOVER>(*msg)); break; - case BTA_DM_API_SEARCH_CANCEL_EVT: - bta_dm_search_clear_queue(); - if (IS_FLAG_ENABLED( - continue_service_discovery_when_cancel_device_discovery)) { - bta_dm_search_set_state(BTA_DM_SEARCH_CANCELLING); - } - bta_dm_search_cancel_notify(); - break; case BTA_DM_DISC_CLOSE_TOUT_EVT: bta_dm_close_gatt_conn(); break; default: log::info("Received unexpected event {}[0x{:x}] in state {}", bta_dm_event_text(event), event, - bta_dm_state_text(bta_dm_search_get_state())); + bta_dm_state_text(bta_dm_discovery_get_state())); } break; } } -static void bta_dm_disc_init_search_cb(tBTA_DM_SEARCH_CB& bta_dm_search_cb) { - bta_dm_search_cb = {}; - bta_dm_search_cb.state = BTA_DM_SEARCH_IDLE; - bta_dm_search_cb.conn_id = GATT_INVALID_CONN_ID; - bta_dm_search_cb.transport = BT_TRANSPORT_AUTO; +static void bta_dm_disc_init_discovery_cb( + tBTA_DM_SERVICE_DISCOVERY_CB& bta_dm_discovery_cb) { + bta_dm_discovery_cb = {}; + bta_dm_discovery_cb.service_discovery_state = BTA_DM_DISCOVER_IDLE; + bta_dm_discovery_cb.conn_id = GATT_INVALID_CONN_ID; } static void bta_dm_disc_reset() { - alarm_free(bta_dm_search_cb.search_timer); - alarm_free(bta_dm_search_cb.gatt_close_timer); - bta_dm_search_cb.p_pending_search.reset(); - bta_dm_search_cb.pending_discovery_queue = {}; - bta_dm_disc_init_search_cb(::bta_dm_search_cb); + alarm_free(bta_dm_discovery_cb.search_timer); + alarm_free(bta_dm_discovery_cb.gatt_close_timer); + bta_dm_disc_init_discovery_cb(::bta_dm_discovery_cb); } void bta_dm_disc_start(bool delay_close_gatt) { + if (!IS_FLAG_ENABLED(separate_service_and_device_discovery)) { + bta_dm_disc_legacy::bta_dm_disc_start(delay_close_gatt); + return; + } bta_dm_disc_reset(); - bta_dm_search_cb.search_timer = alarm_new("bta_dm_search.search_timer"); - bta_dm_search_cb.gatt_close_timer = + bta_dm_discovery_cb.search_timer = alarm_new("bta_dm_search.search_timer"); + bta_dm_discovery_cb.gatt_close_timer = delay_close_gatt ? alarm_new("bta_dm_search.gatt_close_timer") : nullptr; - bta_dm_search_cb.pending_discovery_queue = {}; + bta_dm_discovery_cb.pending_discovery_queue = {}; } void bta_dm_disc_acl_down(const RawAddress& bd_addr, tBT_TRANSPORT transport) { + if (!IS_FLAG_ENABLED(separate_service_and_device_discovery)) { + bta_dm_disc_legacy::bta_dm_disc_acl_down(bd_addr, transport); + return; + } switch (transport) { case BT_TRANSPORT_BR_EDR: - if (bta_dm_search_cb.wait_disc && - bta_dm_search_cb.peer_bdaddr == bd_addr) { - bta_dm_search_cb.wait_disc = false; + if (bta_dm_discovery_cb.wait_disc && + bta_dm_discovery_cb.peer_bdaddr == bd_addr) { + bta_dm_discovery_cb.wait_disc = false; - if (bta_dm_search_cb.sdp_results) { + if (bta_dm_discovery_cb.sdp_results) { log::verbose("timer stopped"); - alarm_cancel(bta_dm_search_cb.search_timer); + alarm_cancel(bta_dm_discovery_cb.search_timer); bta_dm_disc_discover_next_device(); } } @@ -2270,22 +1263,23 @@ void bta_dm_disc_acl_down(const RawAddress& bd_addr, tBT_TRANSPORT transport) { } } -void bta_dm_disc_stop() { bta_dm_disc_reset(); } - -void bta_dm_disc_start_device_discovery(tBTA_DM_SEARCH_CBACK* p_cback) { - bta_dm_search_sm_execute( - BTA_DM_API_SEARCH_EVT, - std::make_unique<tBTA_DM_MSG>(tBTA_DM_API_SEARCH{.p_cback = p_cback})); -} - -void bta_dm_disc_stop_device_discovery() { - bta_dm_search_sm_execute(BTA_DM_API_SEARCH_CANCEL_EVT, nullptr); +void bta_dm_disc_stop() { + if (!IS_FLAG_ENABLED(separate_service_and_device_discovery)) { + bta_dm_disc_legacy::bta_dm_disc_stop(); + return; + } + bta_dm_disc_reset(); } void bta_dm_disc_start_service_discovery(service_discovery_callbacks cbacks, const RawAddress& bd_addr, tBT_TRANSPORT transport) { - bta_dm_search_sm_execute( + if (!IS_FLAG_ENABLED(separate_service_and_device_discovery)) { + bta_dm_disc_legacy::bta_dm_disc_start_service_discovery(cbacks, bd_addr, + transport); + return; + } + bta_dm_disc_sm_execute( BTA_DM_API_DISCOVER_EVT, std::make_unique<tBTA_DM_MSG>(tBTA_DM_API_DISCOVER{ .bd_addr = bd_addr, .cbacks = cbacks, .transport = transport})); @@ -2293,14 +1287,18 @@ void bta_dm_disc_start_service_discovery(service_discovery_callbacks cbacks, #define DUMPSYS_TAG "shim::legacy::bta::dm" void DumpsysBtaDmDisc(int fd) { - auto copy = search_state_history_.Pull(); - LOG_DUMPSYS(fd, " last %zu search state transitions", copy.size()); + if (!IS_FLAG_ENABLED(separate_service_and_device_discovery)) { + bta_dm_disc_legacy::DumpsysBtaDmDisc(fd); + return; + } + auto copy = discovery_state_history_.Pull(); + LOG_DUMPSYS(fd, " last %zu discovery state transitions", copy.size()); for (const auto& it : copy) { LOG_DUMPSYS(fd, " %s %s", EpochMillisToString(it.timestamp).c_str(), it.entry.ToString().c_str()); } - LOG_DUMPSYS(fd, " current bta_dm_search_state:%s", - bta_dm_state_text(bta_dm_search_get_state()).c_str()); + LOG_DUMPSYS(fd, " current bta_dm_discovery_state:%s", + bta_dm_state_text(bta_dm_discovery_get_state()).c_str()); } #undef DUMPSYS_TAG @@ -2308,51 +1306,13 @@ namespace bluetooth { namespace legacy { namespace testing { -void bta_dm_disc_init_search_cb(tBTA_DM_SEARCH_CB& bta_dm_search_cb) { - ::bta_dm_disc_init_search_cb(bta_dm_search_cb); -} -tBTA_DM_SEARCH_CB bta_dm_disc_get_search_cb() { - tBTA_DM_SEARCH_CB search_cb = {}; - ::bta_dm_disc_init_search_cb(search_cb); - return search_cb; -} -tBTA_DM_SEARCH_CB& bta_dm_disc_search_cb() { return ::bta_dm_search_cb; } -bool bta_dm_read_remote_device_name(const RawAddress& bd_addr, - tBT_TRANSPORT transport) { - return ::bta_dm_read_remote_device_name(bd_addr, transport); +tBTA_DM_SERVICE_DISCOVERY_CB& bta_dm_discovery_cb() { + return ::bta_dm_discovery_cb; } -void bta_dm_discover_next_device() { ::bta_dm_discover_next_device(); } -void bta_dm_execute_queued_request() { ::bta_dm_execute_queued_request(); } void bta_dm_find_services(const RawAddress& bd_addr) { ::bta_dm_find_services(bd_addr); } -void bta_dm_inq_cmpl() { ::bta_dm_inq_cmpl(); } -void bta_dm_inq_cmpl_cb(void* p_result) { ::bta_dm_inq_cmpl_cb(p_result); } -void bta_dm_observe_cmpl_cb(void* p_result) { - ::bta_dm_observe_cmpl_cb(p_result); -} -void bta_dm_observe_results_cb(tBTM_INQ_RESULTS* p_inq, const uint8_t* p_eir, - uint16_t eir_len) { - ::bta_dm_observe_results_cb(p_inq, p_eir, eir_len); -} -void bta_dm_opportunistic_observe_results_cb(tBTM_INQ_RESULTS* p_inq, - const uint8_t* p_eir, - uint16_t eir_len) { - ::bta_dm_opportunistic_observe_results_cb(p_inq, p_eir, eir_len); -} -void bta_dm_queue_search(tBTA_DM_API_SEARCH& search) { - ::bta_dm_queue_search(search); -} - -void bta_dm_service_search_remname_cback(const RawAddress& bd_addr, - DEV_CLASS dc, BD_NAME bd_name) { - ::bta_dm_service_search_remname_cback(bd_addr, dc, bd_name); -} - -void bta_dm_start_scan(uint8_t duration_sec, bool low_latency_scan = false) { - ::bta_dm_start_scan(duration_sec, low_latency_scan); -} void store_avrcp_profile_feature(tSDP_DISC_REC* sdp_rec) { ::store_avrcp_profile_feature(sdp_rec); diff --git a/system/bta/dm/bta_dm_disc.h b/system/bta/dm/bta_dm_disc.h index 924d1f35c2..6219846a68 100644 --- a/system/bta/dm/bta_dm_disc.h +++ b/system/bta/dm/bta_dm_disc.h @@ -35,14 +35,14 @@ void bta_dm_disc_start_service_discovery(service_discovery_callbacks cbacks, tBT_TRANSPORT transport); // Bta subsystem entrypoint and lifecycle +// Remove when separate_service_and_device_discovery rolls out void bta_dm_disc_disable_search_and_disc(); +void bta_dm_disc_disable_disc(); +void bta_dm_disc_disable_search(); // Indication that an acl has gone down and to examine the current // service discovery procedure, if any. void bta_dm_disc_acl_down(const RawAddress& bd_addr, tBT_TRANSPORT transport); -// Return most recent remote name -const char* bta_dm_get_remname(void); - // LE observe and scan interface void bta_dm_ble_scan(bool start, uint8_t duration_sec, bool low_latency_scan); void bta_dm_ble_csis_observe(bool observe, tBTA_DM_SEARCH_CBACK* p_cback); @@ -62,4 +62,4 @@ void bta_dm_disc_gatt_refresh(const RawAddress& bd_addr); void bta_dm_disc_remove_device(const RawAddress& bd_addr); // Provide data for the dumpsys procedure -void DumpsysBtaDmDisc(int fd); +void DumpsysBtaDmDisc(int fd);
\ No newline at end of file diff --git a/system/bta/dm/bta_dm_disc_int.h b/system/bta/dm/bta_dm_disc_int.h index bf3b16a23c..58fd0edff3 100644 --- a/system/bta/dm/bta_dm_disc_int.h +++ b/system/bta/dm/bta_dm_disc_int.h @@ -25,7 +25,6 @@ #include "bta/include/bta_api.h" #include "bta/sys/bta_sys.h" #include "macros.h" -#include "stack/btm/neighbor_inquiry.h" #include "stack/include/sdp_status.h" #include "stack/sdp/sdp_discovery_db.h" #include "types/bluetooth/uuid.h" @@ -33,41 +32,23 @@ #define BTA_SERVICE_ID_TO_SERVICE_MASK(id) (1 << (id)) -/* DM search events */ typedef enum : uint16_t { - /* DM search API events */ - BTA_DM_API_SEARCH_EVT, - BTA_DM_API_SEARCH_CANCEL_EVT, + /* service discovery events */ BTA_DM_API_DISCOVER_EVT, - BTA_DM_INQUIRY_CMPL_EVT, - BTA_DM_REMT_NAME_EVT, BTA_DM_SDP_RESULT_EVT, - BTA_DM_SEARCH_CMPL_EVT, BTA_DM_DISCOVERY_RESULT_EVT, BTA_DM_DISC_CLOSE_TOUT_EVT, -} tBTA_DM_EVT; +} tBTA_DM_DISC_EVT; -inline std::string bta_dm_event_text(const tBTA_DM_EVT& event) { +inline std::string bta_dm_event_text(const tBTA_DM_DISC_EVT& event) { switch (event) { - CASE_RETURN_TEXT(BTA_DM_API_SEARCH_EVT); - CASE_RETURN_TEXT(BTA_DM_API_SEARCH_CANCEL_EVT); CASE_RETURN_TEXT(BTA_DM_API_DISCOVER_EVT); - CASE_RETURN_TEXT(BTA_DM_INQUIRY_CMPL_EVT); - CASE_RETURN_TEXT(BTA_DM_REMT_NAME_EVT); CASE_RETURN_TEXT(BTA_DM_SDP_RESULT_EVT); - CASE_RETURN_TEXT(BTA_DM_SEARCH_CMPL_EVT); CASE_RETURN_TEXT(BTA_DM_DISCOVERY_RESULT_EVT); CASE_RETURN_TEXT(BTA_DM_DISC_CLOSE_TOUT_EVT); - default: - return base::StringPrintf("UNKNOWN[0x%04x]", event); } } -/* data type for BTA_DM_API_SEARCH_EVT */ -typedef struct { - tBTA_DM_SEARCH_CBACK* p_cback; -} tBTA_DM_API_SEARCH; - /* data type for BTA_DM_API_DISCOVER_EVT */ typedef struct { RawAddress bd_addr; @@ -76,105 +57,63 @@ typedef struct { } tBTA_DM_API_DISCOVER; typedef struct { -} tBTA_DM_API_DISCOVERY_CANCEL; - -typedef struct { - RawAddress bd_addr; - BD_NAME bd_name; /* Name of peer device. */ - tHCI_STATUS hci_status; -} tBTA_DM_REMOTE_NAME; - -/* data type for tBTA_DM_DISC_RESULT */ -typedef struct { - tBTA_DM_SEARCH result; -} tBTA_DM_DISC_RESULT; - -/* data type for BTA_DM_INQUIRY_CMPL_EVT */ -typedef struct { - uint8_t num; -} tBTA_DM_INQUIRY_CMPL; - -/* data type for BTA_DM_SDP_RESULT_EVT */ -typedef struct { - tSDP_RESULT sdp_result; -} tBTA_DM_SDP_RESULT; - -typedef struct { - bool enable; -} tBTA_DM_API_BLE_FEATURE; - -typedef struct { RawAddress bd_addr; /* BD address peer device. */ tBTA_SERVICE_MASK services; /* Services found on peer device. */ - tBT_DEVICE_TYPE device_type; /* device type in case it is BLE device */ + bool is_gatt_over_ble; std::vector<bluetooth::Uuid> uuids; + std::vector<bluetooth::Uuid> gatt_uuids; tBTA_STATUS result; tHCI_STATUS hci_status; } tBTA_DM_SVC_RES; -using tBTA_DM_MSG = - std::variant<tBTA_DM_API_SEARCH, tBTA_DM_API_DISCOVER, tBTA_DM_REMOTE_NAME, - tBTA_DM_DISC_RESULT, tBTA_DM_INQUIRY_CMPL, tBTA_DM_SDP_RESULT, - tBTA_DM_SVC_RES>; +using tBTA_DM_MSG = std::variant<tBTA_DM_API_DISCOVER, tBTA_DM_SVC_RES>; -/* DM search state */ typedef enum { - - BTA_DM_SEARCH_IDLE, - BTA_DM_SEARCH_ACTIVE, - BTA_DM_SEARCH_CANCELLING, + BTA_DM_DISCOVER_IDLE, BTA_DM_DISCOVER_ACTIVE +} tBTA_DM_SERVICE_DISCOVERY_STATE; -} tBTA_DM_STATE; - -inline std::string bta_dm_state_text(const tBTA_DM_STATE& state) { +inline std::string bta_dm_state_text( + const tBTA_DM_SERVICE_DISCOVERY_STATE& state) { switch (state) { - CASE_RETURN_TEXT(BTA_DM_SEARCH_IDLE); - CASE_RETURN_TEXT(BTA_DM_SEARCH_ACTIVE); - CASE_RETURN_TEXT(BTA_DM_SEARCH_CANCELLING); + CASE_RETURN_TEXT(BTA_DM_DISCOVER_IDLE); CASE_RETURN_TEXT(BTA_DM_DISCOVER_ACTIVE); - default: - return base::StringPrintf("UNKNOWN[%d]", state); } } -/* DM search control block */ typedef struct { - tBTA_DM_SEARCH_CBACK* p_device_search_cback; service_discovery_callbacks service_search_cbacks; - tBTM_INQ_INFO* p_btm_inq_info; + tGATT_IF client_if; + std::queue<tBTA_DM_API_DISCOVER> pending_discovery_queue; + + RawAddress peer_bdaddr; + /* This covers service discovery state - callers of BTA_DmDiscover. That is + * initial service discovery after bonding and + * BluetoothDevice.fetchUuidsWithSdp(). Responsible for LE GATT Service + * Discovery and SDP */ + tBTA_DM_SERVICE_DISCOVERY_STATE service_discovery_state; tBTA_SERVICE_MASK services_to_search; tBTA_SERVICE_MASK services_found; + tSDP_DISCOVERY_DB* p_sdp_db; - tBTA_DM_STATE state; - RawAddress peer_bdaddr; - bool name_discover_done; - BD_NAME peer_name; alarm_t* search_timer; uint8_t service_index; - std::unique_ptr<tBTA_DM_MSG> p_pending_search; - std::queue<tBTA_DM_API_DISCOVER> pending_discovery_queue; - bool wait_disc; bool sdp_results; - bluetooth::Uuid uuid; + bool wait_disc; uint8_t peer_scn; - tBT_TRANSPORT transport; - tBTA_DM_SEARCH_CBACK* p_csis_scan_cback; - tGATT_IF client_if; - uint8_t uuid_to_search; - bool gatt_disc_active; + uint16_t conn_id; alarm_t* gatt_close_timer; /* GATT channel close delay timer */ RawAddress pending_close_bda; /* pending GATT channel remote device address */ - -} tBTA_DM_SEARCH_CB; +} tBTA_DM_SERVICE_DISCOVERY_CB; extern const uint32_t bta_service_id_to_btm_srv_id_lkup_tbl[]; extern const uint16_t bta_service_id_to_uuid_lkup_tbl[]; namespace fmt { template <> -struct formatter<tBTA_DM_EVT> : enum_formatter<tBTA_DM_EVT> {}; +struct formatter<tBTA_DM_DISC_EVT> : enum_formatter<tBTA_DM_DISC_EVT> {}; template <> -struct formatter<tBTA_DM_STATE> : enum_formatter<tBTA_DM_STATE> {}; +struct formatter<tBTA_DM_SERVICE_DISCOVERY_STATE> + : enum_formatter<tBTA_DM_SERVICE_DISCOVERY_STATE> {}; } // namespace fmt diff --git a/system/bta/dm/bta_dm_disc_int_legacy.h b/system/bta/dm/bta_dm_disc_int_legacy.h new file mode 100644 index 0000000000..e791a8e87c --- /dev/null +++ b/system/bta/dm/bta_dm_disc_int_legacy.h @@ -0,0 +1,188 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <base/strings/stringprintf.h> +#include <bluetooth/log.h> + +#include <queue> +#include <string> + +#include "bta/include/bta_api.h" +#include "bta/sys/bta_sys.h" +#include "macros.h" +#include "stack/btm/neighbor_inquiry.h" +#include "stack/include/sdp_status.h" +#include "stack/sdp/sdp_discovery_db.h" +#include "types/bluetooth/uuid.h" +#include "types/raw_address.h" + +#define BTA_SERVICE_ID_TO_SERVICE_MASK(id) (1 << (id)) + +// TODO: Remove this file after flag separate_service_and_device_discovery rolls +// out +namespace bta_dm_disc_legacy { + +/* DM search events */ +typedef enum : uint16_t { + /* DM search API events */ + BTA_DM_API_SEARCH_EVT, + BTA_DM_API_SEARCH_CANCEL_EVT, + BTA_DM_API_DISCOVER_EVT, + BTA_DM_INQUIRY_CMPL_EVT, + BTA_DM_REMT_NAME_EVT, + BTA_DM_SDP_RESULT_EVT, + BTA_DM_SEARCH_CMPL_EVT, + BTA_DM_DISCOVERY_RESULT_EVT, + BTA_DM_DISC_CLOSE_TOUT_EVT, +} tBTA_DM_EVT; + +inline std::string bta_dm_event_text(const tBTA_DM_EVT& event) { + switch (event) { + CASE_RETURN_TEXT(BTA_DM_API_SEARCH_EVT); + CASE_RETURN_TEXT(BTA_DM_API_SEARCH_CANCEL_EVT); + CASE_RETURN_TEXT(BTA_DM_API_DISCOVER_EVT); + CASE_RETURN_TEXT(BTA_DM_INQUIRY_CMPL_EVT); + CASE_RETURN_TEXT(BTA_DM_REMT_NAME_EVT); + CASE_RETURN_TEXT(BTA_DM_SDP_RESULT_EVT); + CASE_RETURN_TEXT(BTA_DM_SEARCH_CMPL_EVT); + CASE_RETURN_TEXT(BTA_DM_DISCOVERY_RESULT_EVT); + CASE_RETURN_TEXT(BTA_DM_DISC_CLOSE_TOUT_EVT); + default: + return base::StringPrintf("UNKNOWN[0x%04x]", event); + } +} + +/* data type for BTA_DM_API_SEARCH_EVT */ +typedef struct { + tBTA_DM_SEARCH_CBACK* p_cback; +} tBTA_DM_API_SEARCH; + +/* data type for BTA_DM_API_DISCOVER_EVT */ +typedef struct { + RawAddress bd_addr; + service_discovery_callbacks cbacks; + tBT_TRANSPORT transport; +} tBTA_DM_API_DISCOVER; + +typedef struct { +} tBTA_DM_API_DISCOVERY_CANCEL; + +typedef struct { + RawAddress bd_addr; + BD_NAME bd_name; /* Name of peer device. */ + tHCI_STATUS hci_status; +} tBTA_DM_REMOTE_NAME; + +/* data type for tBTA_DM_DISC_RESULT */ +typedef struct { + tBTA_DM_SEARCH result; +} tBTA_DM_DISC_RESULT; + +/* data type for BTA_DM_INQUIRY_CMPL_EVT */ +typedef struct { + uint8_t num; +} tBTA_DM_INQUIRY_CMPL; + +/* data type for BTA_DM_SDP_RESULT_EVT */ +typedef struct { + tSDP_RESULT sdp_result; +} tBTA_DM_SDP_RESULT; + +typedef struct { + bool enable; +} tBTA_DM_API_BLE_FEATURE; + +typedef struct { + RawAddress bd_addr; /* BD address peer device. */ + tBTA_SERVICE_MASK services; /* Services found on peer device. */ + tBT_DEVICE_TYPE device_type; /* device type in case it is BLE device */ + std::vector<bluetooth::Uuid> uuids; + tBTA_STATUS result; + tHCI_STATUS hci_status; +} tBTA_DM_SVC_RES; + +using tBTA_DM_MSG = + std::variant<tBTA_DM_API_SEARCH, tBTA_DM_API_DISCOVER, tBTA_DM_REMOTE_NAME, + tBTA_DM_DISC_RESULT, tBTA_DM_INQUIRY_CMPL, tBTA_DM_SDP_RESULT, + tBTA_DM_SVC_RES>; + +/* DM search state */ +typedef enum { + + BTA_DM_SEARCH_IDLE, + BTA_DM_SEARCH_ACTIVE, + BTA_DM_SEARCH_CANCELLING, + BTA_DM_DISCOVER_ACTIVE + +} tBTA_DM_STATE; + +inline std::string bta_dm_state_text(const tBTA_DM_STATE& state) { + switch (state) { + CASE_RETURN_TEXT(BTA_DM_SEARCH_IDLE); + CASE_RETURN_TEXT(BTA_DM_SEARCH_ACTIVE); + CASE_RETURN_TEXT(BTA_DM_SEARCH_CANCELLING); + CASE_RETURN_TEXT(BTA_DM_DISCOVER_ACTIVE); + default: + return base::StringPrintf("UNKNOWN[%d]", state); + } +} + +/* DM search control block */ +typedef struct { + tBTA_DM_SEARCH_CBACK* p_device_search_cback; + service_discovery_callbacks service_search_cbacks; + tBTM_INQ_INFO* p_btm_inq_info; + tBTA_SERVICE_MASK services_to_search; + tBTA_SERVICE_MASK services_found; + tSDP_DISCOVERY_DB* p_sdp_db; + tBTA_DM_STATE state; + RawAddress peer_bdaddr; + bool name_discover_done; + BD_NAME peer_name; + alarm_t* search_timer; + uint8_t service_index; + std::unique_ptr<tBTA_DM_MSG> p_pending_search; + std::queue<tBTA_DM_API_DISCOVER> pending_discovery_queue; + bool wait_disc; + bool sdp_results; + bluetooth::Uuid uuid; + uint8_t peer_scn; + tBT_TRANSPORT transport; + tBTA_DM_SEARCH_CBACK* p_csis_scan_cback; + tGATT_IF client_if; + uint8_t uuid_to_search; + bool gatt_disc_active; + uint16_t conn_id; + alarm_t* gatt_close_timer; /* GATT channel close delay timer */ + RawAddress pending_close_bda; /* pending GATT channel remote device address */ + +} tBTA_DM_SEARCH_CB; + +extern const uint32_t bta_service_id_to_btm_srv_id_lkup_tbl[]; +extern const uint16_t bta_service_id_to_uuid_lkup_tbl[]; + +} // namespace bta_dm_disc_legacy + +namespace fmt { +template <> +struct formatter<bta_dm_disc_legacy::tBTA_DM_EVT> + : enum_formatter<bta_dm_disc_legacy::tBTA_DM_EVT> {}; +template <> +struct formatter<bta_dm_disc_legacy::tBTA_DM_STATE> + : enum_formatter<bta_dm_disc_legacy::tBTA_DM_STATE> {}; +} // namespace fmt diff --git a/system/bta/dm/bta_dm_disc_legacy.cc b/system/bta/dm/bta_dm_disc_legacy.cc new file mode 100644 index 0000000000..d1d4135f89 --- /dev/null +++ b/system/bta/dm/bta_dm_disc_legacy.cc @@ -0,0 +1,2379 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "bt_bta_dm" + +#include "bta/dm/bta_dm_disc_legacy.h" + +#include <android_bluetooth_flags.h> +#include <base/functional/bind.h> +#include <base/strings/stringprintf.h> +#include <bluetooth/log.h> +#include <stddef.h> + +#include <cstdint> +#include <string> +#include <variant> +#include <vector> + +#include "android_bluetooth_flags.h" +#include "bta/dm/bta_dm_disc_int_legacy.h" +#include "bta/include/bta_gatt_api.h" +#include "bta/include/bta_sdp_api.h" +#include "btif/include/btif_config.h" +#include "common/circular_buffer.h" +#include "common/init_flags.h" +#include "common/strings.h" +#include "device/include/interop.h" +#include "internal_include/bt_target.h" +#include "main/shim/dumpsys.h" +#include "os/logging/log_adapter.h" +#include "osi/include/allocator.h" +#include "stack/btm/btm_int_types.h" // TimestampedStringCircularBuffer +#include "stack/btm/neighbor_inquiry.h" +#include "stack/include/bt_dev_class.h" +#include "stack/include/bt_name.h" +#include "stack/include/bt_uuid16.h" +#include "stack/include/btm_client_interface.h" +#include "stack/include/btm_log_history.h" +#include "stack/include/btm_sec_api.h" // BTM_IsRemoteNameKnown +#include "stack/include/gap_api.h" // GAP_BleReadPeerPrefConnParams +#include "stack/include/hidh_api.h" +#include "stack/include/main_thread.h" +#include "stack/include/sdp_status.h" +#include "stack/sdp/sdpint.h" // is_sdp_pbap_pce_disabled +#include "storage/config_keys.h" +#include "types/raw_address.h" + +#ifdef TARGET_FLOSS +#include "stack/include/srvc_api.h" +#endif + +// TODO: Remove this file after flag separate_service_and_device_discovery rolls +// out +namespace bta_dm_disc_legacy { + +using ::bluetooth::Uuid; +using namespace ::bluetooth::legacy::stack::sdp; +using namespace ::bluetooth; + +tBTM_CONTRL_STATE bta_dm_pm_obtain_controller_state(void); + +namespace { +constexpr char kBtmLogTag[] = "SDP"; + +tBTA_DM_SEARCH_CB bta_dm_search_cb; +} // namespace + +static void bta_dm_search_sm_execute(tBTA_DM_EVT event, + std::unique_ptr<tBTA_DM_MSG> msg); +static void post_disc_evt(tBTA_DM_EVT event, std::unique_ptr<tBTA_DM_MSG> msg) { + if (do_in_main_thread(FROM_HERE, base::BindOnce(&bta_dm_search_sm_execute, + event, std::move(msg))) != + BT_STATUS_SUCCESS) { + log::error("post_disc_evt failed"); + } +} + +static void bta_dm_gatt_disc_complete(uint16_t conn_id, tGATT_STATUS status); +static void bta_dm_inq_results_cb(tBTM_INQ_RESULTS* p_inq, const uint8_t* p_eir, + uint16_t eir_len); +static void bta_dm_inq_cmpl(); +static void bta_dm_inq_cmpl_cb(void* p_result); +static void bta_dm_service_search_remname_cback(const RawAddress& bd_addr, + DEV_CLASS dc, BD_NAME bd_name); +static void bta_dm_remname_cback(const tBTM_REMOTE_DEV_NAME* p); +static void bta_dm_find_services(const RawAddress& bd_addr); +static void bta_dm_discover_next_device(void); +static void bta_dm_sdp_callback(const RawAddress& bd_addr, + tSDP_STATUS sdp_status); + +static bool bta_dm_read_remote_device_name(const RawAddress& bd_addr, + tBT_TRANSPORT transport); +static void bta_dm_discover_name(const RawAddress& remote_bd_addr); +static void bta_dm_discover_services(const RawAddress& remote_bd_addr); + +static void bta_dm_disable_search_and_disc(void); + +static void bta_dm_gattc_register(void); +static void btm_dm_start_gatt_discovery(const RawAddress& bd_addr); +static void bta_dm_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data); +static void bta_dm_search_cmpl(); +static void bta_dm_free_sdp_db(); +static void bta_dm_execute_queued_request(); +static void bta_dm_search_cancel_notify(); +static void bta_dm_close_gatt_conn(); + +TimestampedStringCircularBuffer disc_gatt_history_{50}; + +namespace { + +struct gatt_interface_t { + void (*BTA_GATTC_CancelOpen)(tGATT_IF client_if, const RawAddress& remote_bda, + bool is_direct); + void (*BTA_GATTC_Refresh)(const RawAddress& remote_bda); + void (*BTA_GATTC_GetGattDb)(uint16_t conn_id, uint16_t start_handle, + uint16_t end_handle, btgatt_db_element_t** db, + int* count); + void (*BTA_GATTC_AppRegister)(tBTA_GATTC_CBACK* p_client_cb, + BtaAppRegisterCallback cb, bool eatt_support); + void (*BTA_GATTC_Close)(uint16_t conn_id); + void (*BTA_GATTC_ServiceSearchRequest)(uint16_t conn_id, + const bluetooth::Uuid* p_srvc_uuid); + void (*BTA_GATTC_Open)(tGATT_IF client_if, const RawAddress& remote_bda, + tBTM_BLE_CONN_TYPE connection_type, + bool opportunistic); +} default_gatt_interface = { + .BTA_GATTC_CancelOpen = + [](tGATT_IF client_if, const RawAddress& remote_bda, bool is_direct) { + disc_gatt_history_.Push(base::StringPrintf( + "%-32s bd_addr:%s client_if:%hu is_direct:%c", "GATTC_CancelOpen", + ADDRESS_TO_LOGGABLE_CSTR(remote_bda), client_if, + (is_direct) ? 'T' : 'F')); + BTA_GATTC_CancelOpen(client_if, remote_bda, is_direct); + }, + .BTA_GATTC_Refresh = + [](const RawAddress& remote_bda) { + disc_gatt_history_.Push( + base::StringPrintf("%-32s bd_addr:%s", "GATTC_Refresh", + ADDRESS_TO_LOGGABLE_CSTR(remote_bda))); + BTA_GATTC_Refresh(remote_bda); + }, + .BTA_GATTC_GetGattDb = + [](uint16_t conn_id, uint16_t start_handle, uint16_t end_handle, + btgatt_db_element_t** db, int* count) { + disc_gatt_history_.Push(base::StringPrintf( + "%-32s conn_id:%hu start_handle:%hu end:handle:%hu", + "GATTC_GetGattDb", conn_id, start_handle, end_handle)); + BTA_GATTC_GetGattDb(conn_id, start_handle, end_handle, db, count); + }, + .BTA_GATTC_AppRegister = + [](tBTA_GATTC_CBACK* p_client_cb, BtaAppRegisterCallback cb, + bool eatt_support) { + disc_gatt_history_.Push( + base::StringPrintf("%-32s eatt_support:%c", "GATTC_AppRegister", + (eatt_support) ? 'T' : 'F')); + BTA_GATTC_AppRegister(p_client_cb, cb, eatt_support); + }, + .BTA_GATTC_Close = + [](uint16_t conn_id) { + disc_gatt_history_.Push( + base::StringPrintf("%-32s conn_id:%hu", "GATTC_Close", conn_id)); + BTA_GATTC_Close(conn_id); + }, + .BTA_GATTC_ServiceSearchRequest = + [](uint16_t conn_id, const bluetooth::Uuid* p_srvc_uuid) { + disc_gatt_history_.Push(base::StringPrintf( + "%-32s conn_id:%hu", "GATTC_ServiceSearchRequest", conn_id)); + BTA_GATTC_ServiceSearchRequest(conn_id, p_srvc_uuid); + }, + .BTA_GATTC_Open = + [](tGATT_IF client_if, const RawAddress& remote_bda, + tBTM_BLE_CONN_TYPE connection_type, bool opportunistic) { + disc_gatt_history_.Push(base::StringPrintf( + "%-32s bd_addr:%s client_if:%hu type:0x%x opportunistic:%c", + "GATTC_Open", ADDRESS_TO_LOGGABLE_CSTR(remote_bda), client_if, + connection_type, (opportunistic) ? 'T' : 'F')); + BTA_GATTC_Open(client_if, remote_bda, connection_type, opportunistic); + }, +}; + +gatt_interface_t* gatt_interface = &default_gatt_interface; + +gatt_interface_t& get_gatt_interface() { return *gatt_interface; } + +} // namespace + +void bta_dm_disc_disable_search_and_disc() { bta_dm_disable_search_and_disc(); } + +void bta_dm_disc_gatt_cancel_open(const RawAddress& bd_addr) { + get_gatt_interface().BTA_GATTC_CancelOpen(0, bd_addr, false); +} + +void bta_dm_disc_gatt_refresh(const RawAddress& bd_addr) { + get_gatt_interface().BTA_GATTC_Refresh(bd_addr); +} + +void bta_dm_disc_remove_device(const RawAddress& bd_addr) { + if (bta_dm_search_cb.state == BTA_DM_DISCOVER_ACTIVE && + bta_dm_search_cb.peer_bdaddr == bd_addr) { + log::info( + "Device removed while service discovery was pending, conclude the " + "service disvovery"); + bta_dm_gatt_disc_complete((uint16_t)GATT_INVALID_CONN_ID, + (tGATT_STATUS)GATT_ERROR); + } +} + +void bta_dm_disc_discover_next_device() { bta_dm_discover_next_device(); } + +void bta_dm_disc_gattc_register() { bta_dm_gattc_register(); } + +static void bta_dm_observe_results_cb(tBTM_INQ_RESULTS* p_inq, + const uint8_t* p_eir, uint16_t eir_len); +static void bta_dm_observe_cmpl_cb(void* p_result); + +const uint16_t bta_service_id_to_uuid_lkup_tbl[BTA_MAX_SERVICE_ID] = { + UUID_SERVCLASS_PNP_INFORMATION, /* Reserved */ + UUID_SERVCLASS_SERIAL_PORT, /* BTA_SPP_SERVICE_ID */ + UUID_SERVCLASS_DIALUP_NETWORKING, /* BTA_DUN_SERVICE_ID */ + UUID_SERVCLASS_AUDIO_SOURCE, /* BTA_A2DP_SOURCE_SERVICE_ID */ + UUID_SERVCLASS_LAN_ACCESS_USING_PPP, /* BTA_LAP_SERVICE_ID */ + UUID_SERVCLASS_HEADSET, /* BTA_HSP_HS_SERVICE_ID */ + UUID_SERVCLASS_HF_HANDSFREE, /* BTA_HFP_HS_SERVICE_ID */ + UUID_SERVCLASS_OBEX_OBJECT_PUSH, /* BTA_OPP_SERVICE_ID */ + UUID_SERVCLASS_OBEX_FILE_TRANSFER, /* BTA_FTP_SERVICE_ID */ + UUID_SERVCLASS_CORDLESS_TELEPHONY, /* BTA_CTP_SERVICE_ID */ + UUID_SERVCLASS_INTERCOM, /* BTA_ICP_SERVICE_ID */ + UUID_SERVCLASS_IRMC_SYNC, /* BTA_SYNC_SERVICE_ID */ + UUID_SERVCLASS_DIRECT_PRINTING, /* BTA_BPP_SERVICE_ID */ + UUID_SERVCLASS_IMAGING_RESPONDER, /* BTA_BIP_SERVICE_ID */ + UUID_SERVCLASS_PANU, /* BTA_PANU_SERVICE_ID */ + UUID_SERVCLASS_NAP, /* BTA_NAP_SERVICE_ID */ + UUID_SERVCLASS_GN, /* BTA_GN_SERVICE_ID */ + UUID_SERVCLASS_SAP, /* BTA_SAP_SERVICE_ID */ + UUID_SERVCLASS_AUDIO_SINK, /* BTA_A2DP_SERVICE_ID */ + UUID_SERVCLASS_AV_REMOTE_CONTROL, /* BTA_AVRCP_SERVICE_ID */ + UUID_SERVCLASS_HUMAN_INTERFACE, /* BTA_HID_SERVICE_ID */ + UUID_SERVCLASS_VIDEO_SINK, /* BTA_VDP_SERVICE_ID */ + UUID_SERVCLASS_PBAP_PSE, /* BTA_PBAP_SERVICE_ID */ + UUID_SERVCLASS_HEADSET_AUDIO_GATEWAY, /* BTA_HSP_SERVICE_ID */ + UUID_SERVCLASS_AG_HANDSFREE, /* BTA_HFP_SERVICE_ID */ + UUID_SERVCLASS_MESSAGE_ACCESS, /* BTA_MAP_SERVICE_ID */ + UUID_SERVCLASS_MESSAGE_NOTIFICATION, /* BTA_MN_SERVICE_ID */ + UUID_SERVCLASS_HDP_PROFILE, /* BTA_HDP_SERVICE_ID */ + UUID_SERVCLASS_PBAP_PCE, /* BTA_PCE_SERVICE_ID */ + UUID_PROTOCOL_ATT /* BTA_GATT_SERVICE_ID */ +}; + +#define MAX_DISC_RAW_DATA_BUF (4096) +static uint8_t g_disc_raw_data_buf[MAX_DISC_RAW_DATA_BUF]; + +static void bta_dm_search_set_state(tBTA_DM_STATE state) { + bta_dm_search_cb.state = state; +} +static tBTA_DM_STATE bta_dm_search_get_state() { + return bta_dm_search_cb.state; +} + +/******************************************************************************* + * + * Function bta_dm_search_start + * + * Description Starts an inquiry + * + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_search_start(tBTA_DM_API_SEARCH& search) { + bta_dm_gattc_register(); + + get_btm_client_interface().db.BTM_ClearInqDb(nullptr); + /* save search params */ + bta_dm_search_cb.p_device_search_cback = search.p_cback; + + const tBTM_STATUS btm_status = + BTM_StartInquiry(bta_dm_inq_results_cb, bta_dm_inq_cmpl_cb); + switch (btm_status) { + case BTM_CMD_STARTED: + // Completion callback will be executed when controller inquiry + // timer pops or is cancelled by the user + break; + default: + log::warn("Unable to start device discovery search btm_status:{}", + btm_status_text(btm_status)); + // Not started so completion callback is executed now + bta_dm_inq_cmpl(); + break; + } +} + +/******************************************************************************* + * + * Function bta_dm_search_cancel + * + * Description Cancels an ongoing search for devices + * + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_search_cancel() { + if (BTM_IsInquiryActive()) { + BTM_CancelInquiry(); + bta_dm_search_cancel_notify(); + bta_dm_search_cmpl(); + } + /* If no Service Search going on then issue cancel remote name in case it is + active */ + else if (!bta_dm_search_cb.name_discover_done) { + get_btm_client_interface().peer.BTM_CancelRemoteDeviceName(); +#ifndef TARGET_FLOSS + /* bta_dm_search_cmpl is called when receiving the remote name cancel evt */ + if (!IS_FLAG_ENABLED( + bta_dm_defer_device_discovery_state_change_until_rnr_complete)) { + bta_dm_search_cmpl(); + } +#endif + } else { + bta_dm_inq_cmpl(); + } +} + +/******************************************************************************* + * + * Function bta_dm_discover + * + * Description Discovers services on a remote device + * + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_discover(tBTA_DM_API_DISCOVER& discover) { + bta_dm_gattc_register(); + + bta_dm_search_cb.service_search_cbacks = discover.cbacks; + bta_dm_search_cb.services_to_search = BTA_ALL_SERVICE_MASK; + bta_dm_search_cb.service_index = 0; + bta_dm_search_cb.services_found = 0; + bta_dm_search_cb.peer_name[0] = 0; + bta_dm_search_cb.p_btm_inq_info = + get_btm_client_interface().db.BTM_InqDbRead(discover.bd_addr); + bta_dm_search_cb.transport = discover.transport; + + bta_dm_search_cb.name_discover_done = false; + + log::info( + "bta_dm_discovery: starting service discovery to {} , transport: {}", + discover.bd_addr, bt_transport_text(discover.transport)); + bta_dm_discover_services(discover.bd_addr); +} + +/******************************************************************************* + * + * Function bta_dm_disable_search_and_disc + * + * Description Cancels an ongoing search or discovery for devices in case + * of a Bluetooth disable + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_disable_search_and_disc(void) { + switch (bta_dm_search_get_state()) { + case BTA_DM_SEARCH_IDLE: + break; + case BTA_DM_SEARCH_ACTIVE: + case BTA_DM_SEARCH_CANCELLING: + case BTA_DM_DISCOVER_ACTIVE: + default: + log::debug( + "Search state machine is not idle so issuing search cancel current " + "state:{}", + bta_dm_state_text(bta_dm_search_get_state())); + bta_dm_search_cancel(); + } +} + +/******************************************************************************* + * + * Function bta_dm_read_remote_device_name + * + * Description Initiate to get remote device name + * + * Returns true if started to get remote name + * + ******************************************************************************/ +static bool bta_dm_read_remote_device_name(const RawAddress& bd_addr, + tBT_TRANSPORT transport) { + tBTM_STATUS btm_status; + + log::verbose(""); + + bta_dm_search_cb.peer_bdaddr = bd_addr; + bta_dm_search_cb.peer_name[0] = 0; + + btm_status = get_btm_client_interface().peer.BTM_ReadRemoteDeviceName( + bta_dm_search_cb.peer_bdaddr, bta_dm_remname_cback, transport); + + if (btm_status == BTM_CMD_STARTED) { + log::verbose("BTM_ReadRemoteDeviceName is started"); + + return (true); + } else if (btm_status == BTM_BUSY) { + log::verbose("BTM_ReadRemoteDeviceName is busy"); + + /* Remote name discovery is on going now so BTM cannot notify through + * "bta_dm_remname_cback" */ + /* adding callback to get notified that current reading remote name done */ + + get_btm_client_interface().security.BTM_SecAddRmtNameNotifyCallback( + &bta_dm_service_search_remname_cback); + + return (true); + } else { + log::warn("BTM_ReadRemoteDeviceName returns 0x{:02X}", btm_status); + + return (false); + } +} + +/******************************************************************************* + * + * Function bta_dm_inq_cmpl + * + * Description Process the inquiry complete event from BTM + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_inq_cmpl() { + if (bta_dm_search_get_state() == BTA_DM_SEARCH_CANCELLING) { + bta_dm_search_set_state(BTA_DM_SEARCH_IDLE); + bta_dm_execute_queued_request(); + return; + } + + if (bta_dm_search_get_state() != BTA_DM_SEARCH_ACTIVE) { + return; + } + + log::verbose("bta_dm_inq_cmpl"); + + bta_dm_search_cb.p_btm_inq_info = + get_btm_client_interface().db.BTM_InqDbFirst(); + if (bta_dm_search_cb.p_btm_inq_info != NULL) { + /* start name discovery from the first device on inquiry result + */ + bta_dm_search_cb.name_discover_done = false; + bta_dm_search_cb.peer_name[0] = 0; + bta_dm_discover_name( + bta_dm_search_cb.p_btm_inq_info->results.remote_bd_addr); + } else { + bta_dm_search_cmpl(); + } +} + +static void bta_dm_remote_name_cmpl( + const tBTA_DM_REMOTE_NAME& remote_name_msg) { + BTM_LogHistory(kBtmLogTag, remote_name_msg.bd_addr, "Remote name completed", + base::StringPrintf( + "status:%s state:%s name:\"%s\"", + hci_status_code_text(remote_name_msg.hci_status).c_str(), + bta_dm_state_text(bta_dm_search_get_state()).c_str(), + PRIVATE_NAME(remote_name_msg.bd_name))); + + tBTM_INQ_INFO* p_btm_inq_info = + get_btm_client_interface().db.BTM_InqDbRead(remote_name_msg.bd_addr); + if (!bd_name_is_empty(remote_name_msg.bd_name) && p_btm_inq_info) { + p_btm_inq_info->appl_knows_rem_name = true; + } + + // Callback with this property + if (bta_dm_search_cb.p_device_search_cback != nullptr || + bta_dm_search_cb.service_search_cbacks.on_name_read != nullptr) { + // Both device and service search callbacks end up sending event to java. + // It's enough to send callback to just one of them. + if (bta_dm_search_cb.p_device_search_cback != nullptr) { + tBTA_DM_SEARCH search_data = { + .name_res = {.bd_addr = remote_name_msg.bd_addr, .bd_name = {}}, + }; + if (remote_name_msg.hci_status == HCI_SUCCESS) { + bd_name_copy(search_data.name_res.bd_name, remote_name_msg.bd_name); + } + bta_dm_search_cb.p_device_search_cback(BTA_DM_NAME_READ_EVT, + &search_data); + } else if (bta_dm_search_cb.service_search_cbacks.on_name_read != nullptr) { + bta_dm_search_cb.service_search_cbacks.on_name_read( + remote_name_msg.bd_addr, remote_name_msg.hci_status, + remote_name_msg.bd_name); + } + } else { + log::warn("Received remote name complete without callback"); + } + + switch (bta_dm_search_get_state()) { + case BTA_DM_SEARCH_ACTIVE: + bta_dm_discover_name(bta_dm_search_cb.peer_bdaddr); + break; + case BTA_DM_DISCOVER_ACTIVE: + /* TODO: Get rid of this case when Name and Service discovery state + * machines are separated */ + bta_dm_discover_name(remote_name_msg.bd_addr); + break; + case BTA_DM_SEARCH_IDLE: + case BTA_DM_SEARCH_CANCELLING: + log::warn("Received remote name request in state:{}", + bta_dm_state_text(bta_dm_search_get_state())); + break; + } +} + +static void store_avrcp_profile_feature(tSDP_DISC_REC* sdp_rec) { + tSDP_DISC_ATTR* p_attr = + get_legacy_stack_sdp_api()->record.SDP_FindAttributeInRec( + sdp_rec, ATTR_ID_SUPPORTED_FEATURES); + if (p_attr == NULL) { + return; + } + + uint16_t avrcp_features = p_attr->attr_value.v.u16; + if (avrcp_features == 0) { + return; + } + + if (btif_config_set_bin(sdp_rec->remote_bd_addr.ToString().c_str(), + BTIF_STORAGE_KEY_AV_REM_CTRL_FEATURES, + (const uint8_t*)&avrcp_features, + sizeof(avrcp_features))) { + log::info("Saving avrcp_features: 0x{:x}", avrcp_features); + } else { + log::info("Failed to store avrcp_features 0x{:x} for {}", avrcp_features, + sdp_rec->remote_bd_addr); + } +} + +static void bta_dm_store_audio_profiles_version() { + struct AudioProfile { + const uint16_t servclass_uuid; + const uint16_t btprofile_uuid; + const char* profile_key; + void (*store_audio_profile_feature)(tSDP_DISC_REC*); + }; + + std::array<AudioProfile, 1> audio_profiles = {{ + { + .servclass_uuid = UUID_SERVCLASS_AV_REMOTE_CONTROL, + .btprofile_uuid = UUID_SERVCLASS_AV_REMOTE_CONTROL, + .profile_key = BTIF_STORAGE_KEY_AVRCP_CONTROLLER_VERSION, + .store_audio_profile_feature = store_avrcp_profile_feature, + }, + }}; + + for (const auto& audio_profile : audio_profiles) { + tSDP_DISC_REC* sdp_rec = get_legacy_stack_sdp_api()->db.SDP_FindServiceInDb( + bta_dm_search_cb.p_sdp_db, audio_profile.servclass_uuid, NULL); + if (sdp_rec == NULL) continue; + + if (get_legacy_stack_sdp_api()->record.SDP_FindAttributeInRec( + sdp_rec, ATTR_ID_BT_PROFILE_DESC_LIST) == NULL) + continue; + + uint16_t profile_version = 0; + /* get profile version (if failure, version parameter is not updated) */ + get_legacy_stack_sdp_api()->record.SDP_FindProfileVersionInRec( + sdp_rec, audio_profile.btprofile_uuid, &profile_version); + if (profile_version != 0) { + if (btif_config_set_bin(sdp_rec->remote_bd_addr.ToString().c_str(), + audio_profile.profile_key, + (const uint8_t*)&profile_version, + sizeof(profile_version))) { + } else { + log::info("Failed to store peer profile version for {}", + sdp_rec->remote_bd_addr); + } + } + audio_profile.store_audio_profile_feature(sdp_rec); + } +} + +/******************************************************************************* + * + * Function bta_dm_sdp_result + * + * Description Process the discovery result from sdp + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_sdp_result(tBTA_DM_SDP_RESULT& sdp_event) { + tSDP_DISC_REC* p_sdp_rec = NULL; + bool scn_found = false; + uint16_t service = 0xFFFF; + tSDP_PROTOCOL_ELEM pe; + + std::vector<Uuid> uuid_list; + + const tSDP_RESULT sdp_result = sdp_event.sdp_result; + + if ((sdp_event.sdp_result == SDP_SUCCESS) || + (sdp_event.sdp_result == SDP_NO_RECS_MATCH) || + (sdp_event.sdp_result == SDP_DB_FULL)) { + log::verbose("sdp_result::0x{:x}", sdp_event.sdp_result); + do { + p_sdp_rec = NULL; + if (bta_dm_search_cb.service_index == (BTA_USER_SERVICE_ID + 1)) { + if (p_sdp_rec && + get_legacy_stack_sdp_api()->record.SDP_FindProtocolListElemInRec( + p_sdp_rec, UUID_PROTOCOL_RFCOMM, &pe)) { + bta_dm_search_cb.peer_scn = (uint8_t)pe.params[0]; + scn_found = true; + } + } else { + service = + bta_service_id_to_uuid_lkup_tbl[bta_dm_search_cb.service_index - 1]; + p_sdp_rec = get_legacy_stack_sdp_api()->db.SDP_FindServiceInDb( + bta_dm_search_cb.p_sdp_db, service, p_sdp_rec); + } + /* finished with BR/EDR services, now we check the result for GATT based + * service UUID */ + if (bta_dm_search_cb.service_index == BTA_MAX_SERVICE_ID) { + /* all GATT based services */ + + std::vector<Uuid> gatt_uuids; + + do { + /* find a service record, report it */ + p_sdp_rec = get_legacy_stack_sdp_api()->db.SDP_FindServiceInDb( + bta_dm_search_cb.p_sdp_db, 0, p_sdp_rec); + if (p_sdp_rec) { + Uuid service_uuid; + if (get_legacy_stack_sdp_api()->record.SDP_FindServiceUUIDInRec( + p_sdp_rec, &service_uuid)) { + gatt_uuids.push_back(service_uuid); + } + } + } while (p_sdp_rec); + + if (!gatt_uuids.empty()) { + log::info("GATT services discovered using SDP"); + + // send all result back to app + BD_NAME bd_name; + bd_name_from_char_pointer(bd_name, bta_dm_get_remname()); + + bta_dm_search_cb.service_search_cbacks.on_gatt_results( + bta_dm_search_cb.peer_bdaddr, bd_name, gatt_uuids, + /* transport_le */ false); + } + } else { + if ((p_sdp_rec != NULL)) { + if (service != UUID_SERVCLASS_PNP_INFORMATION) { + bta_dm_search_cb.services_found |= + (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK( + bta_dm_search_cb.service_index - 1)); + uint16_t tmp_svc = + bta_service_id_to_uuid_lkup_tbl[bta_dm_search_cb.service_index - + 1]; + /* Add to the list of UUIDs */ + uuid_list.push_back(Uuid::From16Bit(tmp_svc)); + } + } + } + + if (bta_dm_search_cb.services_to_search == 0) { + bta_dm_search_cb.service_index++; + } else /* regular one service per search or PNP search */ + break; + + } while (bta_dm_search_cb.service_index <= BTA_MAX_SERVICE_ID); + + log::verbose("services_found = {:04x}", bta_dm_search_cb.services_found); + + /* Collect the 128-bit services here and put them into the list */ + p_sdp_rec = NULL; + do { + /* find a service record, report it */ + p_sdp_rec = get_legacy_stack_sdp_api()->db.SDP_FindServiceInDb_128bit( + bta_dm_search_cb.p_sdp_db, p_sdp_rec); + if (p_sdp_rec) { + // SDP_FindServiceUUIDInRec_128bit is used only once, refactor? + Uuid temp_uuid; + if (get_legacy_stack_sdp_api()->record.SDP_FindServiceUUIDInRec_128bit( + p_sdp_rec, &temp_uuid)) { + uuid_list.push_back(temp_uuid); + } + } + } while (p_sdp_rec); + + if (bluetooth::common::init_flags:: + dynamic_avrcp_version_enhancement_is_enabled() && + bta_dm_search_cb.services_to_search == 0) { + bta_dm_store_audio_profiles_version(); + } + +#if TARGET_FLOSS + tSDP_DI_GET_RECORD di_record; + if (get_legacy_stack_sdp_api()->device_id.SDP_GetDiRecord( + 1, &di_record, bta_dm_search_cb.p_sdp_db) == SDP_SUCCESS) { + bta_dm_search_cb.service_search_cbacks.on_did_received( + bta_dm_search_cb.peer_bdaddr, di_record.rec.vendor_id_source, + di_record.rec.vendor, di_record.rec.product, di_record.rec.version); + } +#endif + + /* if there are more services to search for */ + if (bta_dm_search_cb.services_to_search) { + /* Free up the p_sdp_db before checking the next one */ + bta_dm_free_sdp_db(); + bta_dm_find_services(bta_dm_search_cb.peer_bdaddr); + } else { + /* callbacks */ + /* start next bd_addr if necessary */ + + get_btm_client_interface().security.BTM_SecDeleteRmtNameNotifyCallback( + &bta_dm_service_search_remname_cback); + + BTM_LogHistory( + kBtmLogTag, bta_dm_search_cb.peer_bdaddr, "Discovery completed", + base::StringPrintf("Result:%s services_found:0x%x service_index:0x%d", + sdp_result_text(sdp_result).c_str(), + bta_dm_search_cb.services_found, + bta_dm_search_cb.service_index)); + + auto msg = std::make_unique<tBTA_DM_MSG>(tBTA_DM_SVC_RES{}); + auto& disc_result = std::get<tBTA_DM_SVC_RES>(*msg); + + disc_result.result = BTA_SUCCESS; + disc_result.uuids = std::move(uuid_list); + // Copy the raw_data to the discovery result structure + if (bta_dm_search_cb.p_sdp_db != NULL && + bta_dm_search_cb.p_sdp_db->raw_used != 0 && + bta_dm_search_cb.p_sdp_db->raw_data != NULL) { + log::verbose("raw_data used = 0x{:x} raw_data_ptr = 0x{}", + bta_dm_search_cb.p_sdp_db->raw_used, + fmt::ptr(bta_dm_search_cb.p_sdp_db->raw_data)); + + bta_dm_search_cb.p_sdp_db->raw_data = + NULL; // no need to free this - it is a global assigned. + bta_dm_search_cb.p_sdp_db->raw_used = 0; + bta_dm_search_cb.p_sdp_db->raw_size = 0; + } else { + log::verbose("raw data size is 0 or raw_data is null!!"); + } + /* Done with p_sdp_db. Free it */ + bta_dm_free_sdp_db(); + disc_result.services = bta_dm_search_cb.services_found; + + // Piggy back the SCN over result field + if (scn_found) { + disc_result.result = + static_cast<tBTA_STATUS>((3 + bta_dm_search_cb.peer_scn)); + disc_result.services |= BTA_USER_SERVICE_MASK; + + log::verbose("Piggy back the SCN over result field SCN={}", + bta_dm_search_cb.peer_scn); + } + disc_result.bd_addr = bta_dm_search_cb.peer_bdaddr; + + bta_dm_search_sm_execute(BTA_DM_DISCOVERY_RESULT_EVT, std::move(msg)); + } + } else { + BTM_LogHistory( + kBtmLogTag, bta_dm_search_cb.peer_bdaddr, "Discovery failed", + base::StringPrintf("Result:%s", sdp_result_text(sdp_result).c_str())); + log::error("SDP connection failed {}", sdp_status_text(sdp_result)); + if (sdp_event.sdp_result == SDP_CONN_FAILED) + bta_dm_search_cb.wait_disc = false; + + /* not able to connect go to next device */ + if (bta_dm_search_cb.p_sdp_db) + osi_free_and_reset((void**)&bta_dm_search_cb.p_sdp_db); + + get_btm_client_interface().security.BTM_SecDeleteRmtNameNotifyCallback( + &bta_dm_service_search_remname_cback); + + auto msg = std::make_unique<tBTA_DM_MSG>(tBTA_DM_SVC_RES{}); + auto& disc_result = std::get<tBTA_DM_SVC_RES>(*msg); + + disc_result.result = BTA_FAILURE; + disc_result.services = bta_dm_search_cb.services_found; + disc_result.bd_addr = bta_dm_search_cb.peer_bdaddr; + + bta_dm_search_sm_execute(BTA_DM_DISCOVERY_RESULT_EVT, std::move(msg)); + } +} + +/** Callback of peer's DIS reply. This is only called for floss */ +#if TARGET_FLOSS +static void bta_dm_read_dis_cmpl(const RawAddress& addr, + tDIS_VALUE* p_dis_value) { + if (!p_dis_value) { + log::warn("read DIS failed"); + } else { + bta_dm_search_cb.service_search_cbacks.on_did_received( + addr, p_dis_value->pnp_id.vendor_id_src, p_dis_value->pnp_id.vendor_id, + p_dis_value->pnp_id.product_id, p_dis_value->pnp_id.product_version); + } + + bta_dm_execute_queued_request(); +} +#endif + +/******************************************************************************* + * + * Function bta_dm_search_cmpl + * + * Description Sends event to application + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_search_cmpl() { + bta_dm_search_set_state(BTA_DM_SEARCH_IDLE); + + uint16_t conn_id = bta_dm_search_cb.conn_id; + + std::vector<Uuid> gatt_services; + + bool send_gatt_results = + bluetooth::common::init_flags:: + always_send_services_if_gatt_disc_done_is_enabled() + ? bta_dm_search_cb.gatt_disc_active + : false; + + /* no BLE connection, i.e. Classic service discovery end */ + if (conn_id == GATT_INVALID_CONN_ID) { + if (bta_dm_search_cb.gatt_disc_active) { + log::warn( + "GATT active but no BLE connection, likely disconnected midway " + "through"); + } else { + log::info("No BLE connection, processing classic results"); + } + } else { + btgatt_db_element_t* db = NULL; + int count = 0; + get_gatt_interface().BTA_GATTC_GetGattDb(conn_id, 0x0000, 0xFFFF, &db, + &count); + if (count != 0) { + for (int i = 0; i < count; i++) { + // we process service entries only + if (db[i].type == BTGATT_DB_PRIMARY_SERVICE) { + gatt_services.push_back(db[i].uuid); + } + } + osi_free(db); + log::info( + "GATT services discovered using LE Transport, will always send to " + "upper layer"); + send_gatt_results = true; + } else { + log::warn("Empty GATT database - no BLE services discovered"); + } + } + + // send all result back to app + if (send_gatt_results) { + if (bta_dm_search_cb.service_search_cbacks.on_gatt_results != nullptr) { + log::info("Sending GATT results to upper layer"); + + BD_NAME bd_name; + bd_name_from_char_pointer(bd_name, bta_dm_get_remname()); + bta_dm_search_cb.service_search_cbacks.on_gatt_results( + bta_dm_search_cb.peer_bdaddr, bd_name, gatt_services, + /* transport_le */ true); + } else { + log::warn("on_gatt_results is nullptr!"); + } + } + + if (bta_dm_search_cb.p_device_search_cback) { + bta_dm_search_cb.p_device_search_cback(BTA_DM_DISC_CMPL_EVT, nullptr); + } + bta_dm_search_cb.gatt_disc_active = false; + +#if TARGET_FLOSS + if (conn_id != GATT_INVALID_CONN_ID && + DIS_ReadDISInfo(bta_dm_search_cb.peer_bdaddr, bta_dm_read_dis_cmpl, + DIS_ATTR_PNP_ID_BIT)) { + return; + } +#endif + + bta_dm_execute_queued_request(); +} + +/******************************************************************************* + * + * Function bta_dm_disc_result + * + * Description Service discovery result when discovering services on a + * device + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_disc_result(tBTA_DM_SVC_RES& disc_result) { + log::verbose(""); + + /* disc_res.device_type is set only when GATT discovery is finished in + * bta_dm_gatt_disc_complete */ + bool is_gatt_over_ble = ((disc_result.device_type & BT_DEVICE_TYPE_BLE) != 0); + + /* if any BR/EDR service discovery has been done, report the event */ + if (!is_gatt_over_ble) { + auto& r = disc_result; + bta_dm_search_cb.service_search_cbacks.on_service_discovery_results( + r.bd_addr, r.services, r.uuids, r.result, r.hci_status); + } + + /* Services were discovered while device search is in progress. + * Don't execute bta_dm_search_cmpl, as it would also finish the device + * search. It will be executed later when device search is finished. */ + if (bta_dm_search_get_state() != BTA_DM_SEARCH_ACTIVE) { + get_gatt_interface().BTA_GATTC_CancelOpen(0, bta_dm_search_cb.peer_bdaddr, + true); + + bta_dm_search_cmpl(); + } +} + +/******************************************************************************* + * + * Function bta_dm_free_sdp_db + * + * Description Frees SDP data base + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_free_sdp_db() { + osi_free_and_reset((void**)&bta_dm_search_cb.p_sdp_db); +} + +/******************************************************************************* + * + * Function bta_dm_queue_search + * + * Description Queues search command + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_queue_search(tBTA_DM_API_SEARCH& search) { + if (bta_dm_search_cb.p_pending_search) { + log::warn("Overwrote previous device discovery inquiry scan request"); + } + bta_dm_search_cb.p_pending_search.reset(new tBTA_DM_MSG(search)); + log::info("Queued device discovery inquiry scan request"); +} + +/******************************************************************************* + * + * Function bta_dm_queue_disc + * + * Description Queues discovery command + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_queue_disc(tBTA_DM_API_DISCOVER& discovery) { + log::info("bta_dm_discovery: queuing service discovery to {}", + discovery.bd_addr); + bta_dm_search_cb.pending_discovery_queue.push(discovery); +} + +/******************************************************************************* + * + * Function bta_dm_execute_queued_request + * + * Description Executes queued request if one exists + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_execute_queued_request() { + if (!bta_dm_search_cb.pending_discovery_queue.empty()) { + tBTA_DM_API_DISCOVER pending_discovery = + bta_dm_search_cb.pending_discovery_queue.front(); + bta_dm_search_cb.pending_discovery_queue.pop(); + log::info("Start pending discovery"); + post_disc_evt( + BTA_DM_API_DISCOVER_EVT, + std::make_unique<tBTA_DM_MSG>(tBTA_DM_API_DISCOVER{pending_discovery})); + } else if (bta_dm_search_cb.p_pending_search) { + log::info("Start pending search"); + post_disc_evt(BTA_DM_API_SEARCH_EVT, + std::move(bta_dm_search_cb.p_pending_search)); + bta_dm_search_cb.p_pending_search.reset(); + } +} + +/******************************************************************************* + * + * Function bta_dm_is_search_request_queued + * + * Description Checks if there is a queued search request + * + * Returns bool + * + ******************************************************************************/ +bool bta_dm_is_search_request_queued() { + return bta_dm_search_cb.p_pending_search != NULL; +} + +/******************************************************************************* + * + * Function bta_dm_search_clear_queue + * + * Description Clears the queue if API search cancel is called + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_search_clear_queue() { + bta_dm_search_cb.p_pending_search.reset(); + if (bluetooth::common::InitFlags:: + IsBtmDmFlushDiscoveryQueueOnSearchCancel()) { + bta_dm_search_cb.pending_discovery_queue = {}; + } +} + +/******************************************************************************* + * + * Function bta_dm_search_cancel_notify + * + * Description Notify application that search has been cancelled + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_search_cancel_notify() { + if (bta_dm_search_cb.p_device_search_cback) { + bta_dm_search_cb.p_device_search_cback(BTA_DM_SEARCH_CANCEL_CMPL_EVT, NULL); + } + switch (bta_dm_search_get_state()) { + case BTA_DM_SEARCH_ACTIVE: + case BTA_DM_SEARCH_CANCELLING: + if (!bta_dm_search_cb.name_discover_done) { + get_btm_client_interface().peer.BTM_CancelRemoteDeviceName(); + } + break; + case BTA_DM_SEARCH_IDLE: + case BTA_DM_DISCOVER_ACTIVE: + // Nothing to do + break; + } +} + +/******************************************************************************* + * + * Function bta_dm_find_services + * + * Description Starts discovery on a device + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_find_services(const RawAddress& bd_addr) { + while (bta_dm_search_cb.service_index < BTA_MAX_SERVICE_ID) { + Uuid uuid = Uuid::kEmpty; + if (bta_dm_search_cb.services_to_search & + (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK( + bta_dm_search_cb.service_index))) { + bta_dm_search_cb.p_sdp_db = + (tSDP_DISCOVERY_DB*)osi_malloc(BTA_DM_SDP_DB_SIZE); + + /* try to search all services by search based on L2CAP UUID */ + log::info("services_to_search={:08x}", + bta_dm_search_cb.services_to_search); + if (bta_dm_search_cb.services_to_search & BTA_RES_SERVICE_MASK) { + uuid = Uuid::From16Bit(bta_service_id_to_uuid_lkup_tbl[0]); + bta_dm_search_cb.services_to_search &= ~BTA_RES_SERVICE_MASK; + } else { + uuid = Uuid::From16Bit(UUID_PROTOCOL_L2CAP); + bta_dm_search_cb.services_to_search = 0; + } + + log::info("search UUID = {}", uuid.ToString()); + get_legacy_stack_sdp_api()->service.SDP_InitDiscoveryDb( + bta_dm_search_cb.p_sdp_db, BTA_DM_SDP_DB_SIZE, 1, &uuid, 0, NULL); + + memset(g_disc_raw_data_buf, 0, sizeof(g_disc_raw_data_buf)); + bta_dm_search_cb.p_sdp_db->raw_data = g_disc_raw_data_buf; + + bta_dm_search_cb.p_sdp_db->raw_size = MAX_DISC_RAW_DATA_BUF; + + if (!get_legacy_stack_sdp_api() + ->service.SDP_ServiceSearchAttributeRequest( + bd_addr, bta_dm_search_cb.p_sdp_db, &bta_dm_sdp_callback)) { + /* + * If discovery is not successful with this device, then + * proceed with the next one. + */ + osi_free_and_reset((void**)&bta_dm_search_cb.p_sdp_db); + bta_dm_search_cb.service_index = BTA_MAX_SERVICE_ID; + + } else { + if (uuid == Uuid::From16Bit(UUID_PROTOCOL_L2CAP)) { + if (!is_sdp_pbap_pce_disabled(bd_addr)) { + log::debug("SDP search for PBAP Client"); + BTA_SdpSearch(bd_addr, Uuid::From16Bit(UUID_SERVCLASS_PBAP_PCE)); + } + } + bta_dm_search_cb.service_index++; + return; + } + } + + bta_dm_search_cb.service_index++; + } + + /* no more services to be discovered */ + if (bta_dm_search_cb.service_index >= BTA_MAX_SERVICE_ID) { + auto msg = std::make_unique<tBTA_DM_MSG>(tBTA_DM_SVC_RES{}); + auto& disc_result = std::get<tBTA_DM_SVC_RES>(*msg); + disc_result.services = bta_dm_search_cb.services_found; + disc_result.bd_addr = bta_dm_search_cb.peer_bdaddr; + + post_disc_evt(BTA_DM_DISCOVERY_RESULT_EVT, std::move(msg)); + } +} + +/******************************************************************************* + * + * Function bta_dm_discover_next_device + * + * Description Starts discovery on the next device in Inquiry data base + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_discover_next_device(void) { + log::verbose("bta_dm_discover_next_device"); + + /* searching next device on inquiry result */ + bta_dm_search_cb.p_btm_inq_info = get_btm_client_interface().db.BTM_InqDbNext( + bta_dm_search_cb.p_btm_inq_info); + if (bta_dm_search_cb.p_btm_inq_info != NULL) { + bta_dm_search_cb.name_discover_done = false; + bta_dm_search_cb.peer_name[0] = 0; + bta_dm_discover_name( + bta_dm_search_cb.p_btm_inq_info->results.remote_bd_addr); + } else { + post_disc_evt(BTA_DM_SEARCH_CMPL_EVT, nullptr); + } +} + +/******************************************************************************* + * + * Function bta_dm_determine_discovery_transport + * + * Description Starts name and service discovery on the device + * + * Returns void + * + ******************************************************************************/ +static tBT_TRANSPORT bta_dm_determine_discovery_transport( + const RawAddress& remote_bd_addr) { + tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR; + if (bta_dm_search_cb.transport == BT_TRANSPORT_AUTO) { + tBT_DEVICE_TYPE dev_type; + tBLE_ADDR_TYPE addr_type; + + get_btm_client_interface().peer.BTM_ReadDevInfo(remote_bd_addr, &dev_type, + &addr_type); + if (dev_type == BT_DEVICE_TYPE_BLE || addr_type == BLE_ADDR_RANDOM) { + transport = BT_TRANSPORT_LE; + } else if (dev_type == BT_DEVICE_TYPE_DUMO) { + if (get_btm_client_interface().peer.BTM_IsAclConnectionUp( + remote_bd_addr, BT_TRANSPORT_BR_EDR)) { + transport = BT_TRANSPORT_BR_EDR; + } else if (get_btm_client_interface().peer.BTM_IsAclConnectionUp( + remote_bd_addr, BT_TRANSPORT_LE)) { + transport = BT_TRANSPORT_LE; + } + } + } else { + transport = bta_dm_search_cb.transport; + } + return transport; +} + +static void bta_dm_discover_name(const RawAddress& remote_bd_addr) { + const tBT_TRANSPORT transport = + bta_dm_determine_discovery_transport(remote_bd_addr); + + log::verbose("BDA: {}", remote_bd_addr); + + bta_dm_search_cb.peer_bdaddr = remote_bd_addr; + + log::verbose( + "name_discover_done = {} p_btm_inq_info 0x{} state = {}, transport={}", + bta_dm_search_cb.name_discover_done, + fmt::ptr(bta_dm_search_cb.p_btm_inq_info), bta_dm_search_get_state(), + transport); + + if (bta_dm_search_cb.p_btm_inq_info) { + log::verbose("appl_knows_rem_name {}", + bta_dm_search_cb.p_btm_inq_info->appl_knows_rem_name); + } + if (((bta_dm_search_cb.p_btm_inq_info) && + (bta_dm_search_cb.p_btm_inq_info->results.device_type == + BT_DEVICE_TYPE_BLE) && + (bta_dm_search_get_state() == BTA_DM_SEARCH_ACTIVE)) || + (transport == BT_TRANSPORT_LE && + interop_match_addr(INTEROP_DISABLE_NAME_REQUEST, + &bta_dm_search_cb.peer_bdaddr))) { + /* Do not perform RNR for LE devices at inquiry complete*/ + bta_dm_search_cb.name_discover_done = true; + } + // If we already have the name we can skip getting the name + if (BTM_IsRemoteNameKnown(remote_bd_addr, transport) && + bluetooth::common::init_flags::sdp_skip_rnr_if_known_is_enabled()) { + log::debug( + "Security record already known skipping read remote name peer:{}", + remote_bd_addr); + bta_dm_search_cb.name_discover_done = true; + } + + /* if name discovery is not done and application needs remote name */ + if ((!bta_dm_search_cb.name_discover_done) && + ((bta_dm_search_cb.p_btm_inq_info == NULL) || + (bta_dm_search_cb.p_btm_inq_info && + (!bta_dm_search_cb.p_btm_inq_info->appl_knows_rem_name)))) { + if (bta_dm_read_remote_device_name(bta_dm_search_cb.peer_bdaddr, + transport)) { + if (bta_dm_search_get_state() != BTA_DM_DISCOVER_ACTIVE) { + log::debug("Reset transport state for next discovery"); + bta_dm_search_cb.transport = BT_TRANSPORT_AUTO; + } + BTM_LogHistory(kBtmLogTag, bta_dm_search_cb.peer_bdaddr, + "Read remote name", + base::StringPrintf("Transport:%s", + bt_transport_text(transport).c_str())); + return; + } else { + log::error("Unable to start read remote device name"); + } + + /* starting name discovery failed */ + bta_dm_search_cb.name_discover_done = true; + } + + /* Reset transport state for next discovery */ + bta_dm_search_cb.transport = BT_TRANSPORT_AUTO; + + /* name discovery is done for this device */ + if (bta_dm_search_get_state() == BTA_DM_SEARCH_ACTIVE) { + // if p_btm_inq_info is nullptr, there is no more inquiry results to + // discover name for + if (bta_dm_search_cb.p_btm_inq_info) { + bta_dm_discover_next_device(); + } else { + log::info("end of parsing inquiry result"); + } + } else { + log::info("name discovery finished in bad state: {}", + bta_dm_state_text(bta_dm_search_get_state())); + } +} + +static void bta_dm_discover_services(const RawAddress& remote_bd_addr) { + const tBT_TRANSPORT transport = + bta_dm_determine_discovery_transport(remote_bd_addr); + + log::verbose("BDA: {}, transport={}, state = {}", remote_bd_addr, transport, + bta_dm_search_get_state()); + + bta_dm_search_cb.peer_bdaddr = remote_bd_addr; + + /* Reset transport state for next discovery */ + bta_dm_search_cb.transport = BT_TRANSPORT_AUTO; + + bool sdp_disable = HID_HostSDPDisable(remote_bd_addr); + if (sdp_disable) + log::debug("peer:{} with HIDSDPDisable attribute.", remote_bd_addr); + + /* if application wants to discover service and HIDSDPDisable attribute is + false. + Classic mouses with this attribute should not start SDP here, because the + SDP has been done during bonding. SDP request here will interleave with + connections to the Control or Interrupt channels */ + if (!sdp_disable) { + BTM_LogHistory(kBtmLogTag, remote_bd_addr, "Discovery started ", + base::StringPrintf("Transport:%s", + bt_transport_text(transport).c_str())); + + /* initialize variables */ + bta_dm_search_cb.service_index = 0; + bta_dm_search_cb.services_found = 0; + bta_dm_search_cb.services_to_search = BTA_ALL_SERVICE_MASK; + + /* if seaching with EIR is not completed */ + if (bta_dm_search_cb.services_to_search) { + /* check whether connection already exists to the device + if connection exists, we don't have to wait for ACL + link to go down to start search on next device */ + if (transport == BT_TRANSPORT_BR_EDR) { + if (get_btm_client_interface().peer.BTM_IsAclConnectionUp( + bta_dm_search_cb.peer_bdaddr, BT_TRANSPORT_BR_EDR)) + bta_dm_search_cb.wait_disc = false; + else + bta_dm_search_cb.wait_disc = true; + } + + if (transport == BT_TRANSPORT_LE) { + if (bta_dm_search_cb.services_to_search & BTA_BLE_SERVICE_MASK) { + log::info("bta_dm_discovery: starting GATT discovery on {}", + bta_dm_search_cb.peer_bdaddr); + // set the raw data buffer here + memset(g_disc_raw_data_buf, 0, sizeof(g_disc_raw_data_buf)); + /* start GATT for service discovery */ + btm_dm_start_gatt_discovery(bta_dm_search_cb.peer_bdaddr); + return; + } + } else { + log::info("bta_dm_discovery: starting SDP discovery on {}", + bta_dm_search_cb.peer_bdaddr); + bta_dm_search_cb.sdp_results = false; + bta_dm_find_services(bta_dm_search_cb.peer_bdaddr); + return; + } + } + } + + /* service discovery is done for this device */ + auto msg = std::make_unique<tBTA_DM_MSG>(tBTA_DM_SVC_RES{}); + auto& svc_result = std::get<tBTA_DM_SVC_RES>(*msg); + + /* initialize the data structure */ + svc_result.result = BTA_SUCCESS; + svc_result.services = bta_dm_search_cb.services_found; + svc_result.bd_addr = bta_dm_search_cb.peer_bdaddr; + + bta_dm_search_sm_execute(BTA_DM_DISCOVERY_RESULT_EVT, std::move(msg)); +} + +/******************************************************************************* + * + * Function bta_dm_sdp_callback + * + * Description Callback from sdp with discovery status + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_sdp_callback(const RawAddress& /* bd_addr */, + tSDP_STATUS sdp_status) { + post_disc_evt(BTA_DM_SDP_RESULT_EVT, + std::make_unique<tBTA_DM_MSG>( + tBTA_DM_SDP_RESULT{.sdp_result = sdp_status})); +} + +/******************************************************************************* + * + * Function bta_dm_inq_results_cb + * + * Description Inquiry results callback from BTM + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_inq_results_cb(tBTM_INQ_RESULTS* p_inq, const uint8_t* p_eir, + uint16_t eir_len) { + tBTA_DM_SEARCH result; + tBTM_INQ_INFO* p_inq_info; + uint16_t service_class; + + result.inq_res.bd_addr = p_inq->remote_bd_addr; + + // Pass the original address to GattService#onScanResult + result.inq_res.original_bda = p_inq->original_bda; + + result.inq_res.dev_class = p_inq->dev_class; + BTM_COD_SERVICE_CLASS(service_class, p_inq->dev_class); + result.inq_res.is_limited = + (service_class & BTM_COD_SERVICE_LMTD_DISCOVER) ? true : false; + result.inq_res.rssi = p_inq->rssi; + + result.inq_res.ble_addr_type = p_inq->ble_addr_type; + result.inq_res.inq_result_type = p_inq->inq_result_type; + result.inq_res.device_type = p_inq->device_type; + result.inq_res.flag = p_inq->flag; + result.inq_res.include_rsi = p_inq->include_rsi; + result.inq_res.clock_offset = p_inq->clock_offset; + + /* application will parse EIR to find out remote device name */ + result.inq_res.p_eir = const_cast<uint8_t*>(p_eir); + result.inq_res.eir_len = eir_len; + + result.inq_res.ble_evt_type = p_inq->ble_evt_type; + + p_inq_info = + get_btm_client_interface().db.BTM_InqDbRead(p_inq->remote_bd_addr); + if (p_inq_info != NULL) { + /* initialize remt_name_not_required to false so that we get the name by + * default */ + result.inq_res.remt_name_not_required = false; + } + + if (bta_dm_search_cb.p_device_search_cback) + bta_dm_search_cb.p_device_search_cback(BTA_DM_INQ_RES_EVT, &result); + + if (p_inq_info) { + /* application indicates if it knows the remote name, inside the callback + copy that to the inquiry data base*/ + if (result.inq_res.remt_name_not_required) + p_inq_info->appl_knows_rem_name = true; + } +} + +/******************************************************************************* + * + * Function bta_dm_inq_cmpl_cb + * + * Description Inquiry complete callback from BTM + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_inq_cmpl_cb(void* /* p_result */) { + log::verbose(""); + + bta_dm_inq_cmpl(); +} + +/******************************************************************************* + * + * Function bta_dm_service_search_remname_cback + * + * Description Remote name call back from BTM during service discovery + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_service_search_remname_cback(const RawAddress& bd_addr, + DEV_CLASS /* dc */, + BD_NAME bd_name) { + tBTM_REMOTE_DEV_NAME rem_name = {}; + tBTM_STATUS btm_status; + + log::verbose("name=<{}>", reinterpret_cast<char const*>(bd_name)); + + /* if this is what we are looking for */ + if (bta_dm_search_cb.peer_bdaddr == bd_addr) { + rem_name.bd_addr = bd_addr; + bd_name_copy(rem_name.remote_bd_name, bd_name); + rem_name.status = BTM_SUCCESS; + rem_name.hci_status = HCI_SUCCESS; + bta_dm_remname_cback(&rem_name); + } else { + /* get name of device */ + btm_status = get_btm_client_interface().peer.BTM_ReadRemoteDeviceName( + bta_dm_search_cb.peer_bdaddr, bta_dm_remname_cback, + BT_TRANSPORT_BR_EDR); + if (btm_status == BTM_BUSY) { + /* wait for next chance(notification of remote name discovery done) */ + log::verbose("BTM_ReadRemoteDeviceName is busy"); + } else if (btm_status != BTM_CMD_STARTED) { + /* if failed to start getting remote name then continue */ + log::warn("BTM_ReadRemoteDeviceName returns 0x{:02X}", btm_status); + + // needed so our response is not ignored, since this corresponds to the + // actual peer_bdaddr + rem_name.bd_addr = bta_dm_search_cb.peer_bdaddr; + rem_name.remote_bd_name[0] = 0; + rem_name.status = btm_status; + rem_name.hci_status = HCI_SUCCESS; + bta_dm_remname_cback(&rem_name); + } + } +} + +/******************************************************************************* + * + * Function bta_dm_remname_cback + * + * Description Remote name complete call back from BTM + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_remname_cback(const tBTM_REMOTE_DEV_NAME* p_remote_name) { + log::assert_that(p_remote_name != nullptr, + "assert failed: p_remote_name != nullptr"); + + log::info( + "Remote name request complete peer:{} btm_status:{} hci_status:{} " + "name[0]:{:c} length:{}", + p_remote_name->bd_addr, btm_status_text(p_remote_name->status), + hci_error_code_text(p_remote_name->hci_status), + p_remote_name->remote_bd_name[0], + strnlen((const char*)p_remote_name->remote_bd_name, BD_NAME_LEN)); + + if (bta_dm_search_cb.peer_bdaddr == p_remote_name->bd_addr) { + get_btm_client_interface().security.BTM_SecDeleteRmtNameNotifyCallback( + &bta_dm_service_search_remname_cback); + } else { + // if we got a different response, maybe ignore it + // we will have made a request directly from BTM_ReadRemoteDeviceName so we + // expect a dedicated response for us + if (p_remote_name->hci_status == HCI_ERR_CONNECTION_EXISTS) { + get_btm_client_interface().security.BTM_SecDeleteRmtNameNotifyCallback( + &bta_dm_service_search_remname_cback); + log::info( + "Assume command failed due to disconnection hci_status:{} peer:{}", + hci_error_code_text(p_remote_name->hci_status), + p_remote_name->bd_addr); + } else { + log::info( + "Ignored remote name response for the wrong address exp:{} act:{}", + bta_dm_search_cb.peer_bdaddr, p_remote_name->bd_addr); + return; + } + } + + /* remote name discovery is done but it could be failed */ + bta_dm_search_cb.name_discover_done = true; + bd_name_copy(bta_dm_search_cb.peer_name, p_remote_name->remote_bd_name); + + if (bta_dm_search_cb.transport == BT_TRANSPORT_LE) { + GAP_BleReadPeerPrefConnParams(bta_dm_search_cb.peer_bdaddr); + } + + auto msg = std::make_unique<tBTA_DM_MSG>(tBTA_DM_REMOTE_NAME{}); + auto& rmt_name_msg = std::get<tBTA_DM_REMOTE_NAME>(*msg); + rmt_name_msg.bd_addr = bta_dm_search_cb.peer_bdaddr; + rmt_name_msg.hci_status = p_remote_name->hci_status; + bd_name_copy(rmt_name_msg.bd_name, p_remote_name->remote_bd_name); + + post_disc_evt(BTA_DM_REMT_NAME_EVT, std::move(msg)); +} + +/******************************************************************************* + * + * Function bta_dm_get_remname + * + * Description Returns a pointer to the remote name stored in the DM + * control block if it exists, or from the BTM memory. + * + * Returns char * - Pointer to the remote device name + ******************************************************************************/ +const char* bta_dm_get_remname(void) { + const char* p_name = (const char*)bta_dm_search_cb.peer_name; + + /* If the name isn't already stored, try retrieving from BTM */ + if (*p_name == '\0') { + const char* p_temp = get_btm_client_interface().security.BTM_SecReadDevName( + bta_dm_search_cb.peer_bdaddr); + if (p_temp != NULL) p_name = (const char*)p_temp; + } + + return p_name; +} + +/******************************************************************************* + * + * Function bta_dm_observe_results_cb + * + * Description Callback for BLE Observe result + * + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_observe_results_cb(tBTM_INQ_RESULTS* p_inq, + const uint8_t* p_eir, uint16_t eir_len) { + tBTA_DM_SEARCH result; + tBTM_INQ_INFO* p_inq_info; + log::verbose("bta_dm_observe_results_cb"); + + result.inq_res.bd_addr = p_inq->remote_bd_addr; + result.inq_res.original_bda = p_inq->original_bda; + result.inq_res.rssi = p_inq->rssi; + result.inq_res.ble_addr_type = p_inq->ble_addr_type; + result.inq_res.inq_result_type = p_inq->inq_result_type; + result.inq_res.device_type = p_inq->device_type; + result.inq_res.flag = p_inq->flag; + result.inq_res.ble_evt_type = p_inq->ble_evt_type; + result.inq_res.ble_primary_phy = p_inq->ble_primary_phy; + result.inq_res.ble_secondary_phy = p_inq->ble_secondary_phy; + result.inq_res.ble_advertising_sid = p_inq->ble_advertising_sid; + result.inq_res.ble_tx_power = p_inq->ble_tx_power; + result.inq_res.ble_periodic_adv_int = p_inq->ble_periodic_adv_int; + + /* application will parse EIR to find out remote device name */ + result.inq_res.p_eir = const_cast<uint8_t*>(p_eir); + result.inq_res.eir_len = eir_len; + + p_inq_info = + get_btm_client_interface().db.BTM_InqDbRead(p_inq->remote_bd_addr); + if (p_inq_info != NULL) { + /* initialize remt_name_not_required to false so that we get the name by + * default */ + result.inq_res.remt_name_not_required = false; + } + + if (p_inq_info) { + /* application indicates if it knows the remote name, inside the callback + copy that to the inquiry data base*/ + if (result.inq_res.remt_name_not_required) + p_inq_info->appl_knows_rem_name = true; + } +} + +/******************************************************************************* + * + * Function bta_dm_opportunistic_observe_results_cb + * + * Description Callback for BLE Observe result + * + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_opportunistic_observe_results_cb(tBTM_INQ_RESULTS* p_inq, + const uint8_t* p_eir, + uint16_t eir_len) { + tBTA_DM_SEARCH result; + tBTM_INQ_INFO* p_inq_info; + + result.inq_res.bd_addr = p_inq->remote_bd_addr; + result.inq_res.rssi = p_inq->rssi; + result.inq_res.ble_addr_type = p_inq->ble_addr_type; + result.inq_res.inq_result_type = p_inq->inq_result_type; + result.inq_res.device_type = p_inq->device_type; + result.inq_res.flag = p_inq->flag; + result.inq_res.ble_evt_type = p_inq->ble_evt_type; + result.inq_res.ble_primary_phy = p_inq->ble_primary_phy; + result.inq_res.ble_secondary_phy = p_inq->ble_secondary_phy; + result.inq_res.ble_advertising_sid = p_inq->ble_advertising_sid; + result.inq_res.ble_tx_power = p_inq->ble_tx_power; + result.inq_res.ble_periodic_adv_int = p_inq->ble_periodic_adv_int; + + /* application will parse EIR to find out remote device name */ + result.inq_res.p_eir = const_cast<uint8_t*>(p_eir); + result.inq_res.eir_len = eir_len; + + p_inq_info = + get_btm_client_interface().db.BTM_InqDbRead(p_inq->remote_bd_addr); + if (p_inq_info != NULL) { + /* initialize remt_name_not_required to false so that we get the name by + * default */ + result.inq_res.remt_name_not_required = false; + } + + if (bta_dm_search_cb.p_csis_scan_cback) + bta_dm_search_cb.p_csis_scan_cback(BTA_DM_INQ_RES_EVT, &result); + + if (p_inq_info) { + /* application indicates if it knows the remote name, inside the callback + copy that to the inquiry data base*/ + if (result.inq_res.remt_name_not_required) + p_inq_info->appl_knows_rem_name = true; + } +} + +/******************************************************************************* + * + * Function bta_dm_observe_cmpl_cb + * + * Description Callback for BLE Observe complete + * + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_observe_cmpl_cb(void* p_result) { + log::verbose("bta_dm_observe_cmpl_cb"); + + if (bta_dm_search_cb.p_csis_scan_cback) { + auto num_resps = ((tBTM_INQUIRY_CMPL*)p_result)->num_resp; + tBTA_DM_SEARCH data{.observe_cmpl{.num_resps = num_resps}}; + bta_dm_search_cb.p_csis_scan_cback(BTA_DM_OBSERVE_CMPL_EVT, &data); + } +} + +static void bta_dm_start_scan(uint8_t duration_sec, + bool low_latency_scan = false) { + tBTM_STATUS status = get_btm_client_interface().ble.BTM_BleObserve( + true, duration_sec, bta_dm_observe_results_cb, bta_dm_observe_cmpl_cb, + low_latency_scan); + + if (status != BTM_CMD_STARTED) { + log::warn("BTM_BleObserve failed. status {}", status); + if (bta_dm_search_cb.p_csis_scan_cback) { + tBTA_DM_SEARCH data{.observe_cmpl = {.num_resps = 0}}; + bta_dm_search_cb.p_csis_scan_cback(BTA_DM_OBSERVE_CMPL_EVT, &data); + } + } +} + +void bta_dm_ble_scan(bool start, uint8_t duration_sec, + bool low_latency_scan = false) { + if (!start) { + get_btm_client_interface().ble.BTM_BleObserve(false, 0, NULL, NULL, false); + return; + } + + bta_dm_start_scan(duration_sec, low_latency_scan); +} + +void bta_dm_ble_csis_observe(bool observe, tBTA_DM_SEARCH_CBACK* p_cback) { + if (!observe) { + bta_dm_search_cb.p_csis_scan_cback = NULL; + BTM_BleOpportunisticObserve(false, NULL); + return; + } + + /* Save the callback to be called when a scan results are available */ + bta_dm_search_cb.p_csis_scan_cback = p_cback; + BTM_BleOpportunisticObserve(true, bta_dm_opportunistic_observe_results_cb); +} + +#ifndef BTA_DM_GATT_CLOSE_DELAY_TOUT +#define BTA_DM_GATT_CLOSE_DELAY_TOUT 1000 +#endif + +/******************************************************************************* + * + * Function bta_dm_gattc_register + * + * Description Register with GATTC in DM if BLE is needed. + * + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_gattc_register(void) { + if (bta_dm_search_cb.client_if != BTA_GATTS_INVALID_IF) { + // Already registered + return; + } + get_gatt_interface().BTA_GATTC_AppRegister( + bta_dm_gattc_callback, base::Bind([](uint8_t client_id, uint8_t status) { + tGATT_STATUS gatt_status = static_cast<tGATT_STATUS>(status); + disc_gatt_history_.Push(base::StringPrintf( + "%-32s client_id:%hu status:%s", "GATTC_RegisteredCallback", + client_id, gatt_status_text(gatt_status).c_str())); + if (static_cast<tGATT_STATUS>(status) == GATT_SUCCESS) { + log::info( + "Registered device discovery search gatt client tGATT_IF:{}", + client_id); + bta_dm_search_cb.client_if = client_id; + } else { + log::warn( + "Failed to register device discovery search gatt client " + "gatt_status:{} previous tGATT_IF:{}", + bta_dm_search_cb.client_if, status); + bta_dm_search_cb.client_if = BTA_GATTS_INVALID_IF; + } + }), + false); +} + +static void gatt_close_timer_cb(void*) { + bta_dm_search_sm_execute(BTA_DM_DISC_CLOSE_TOUT_EVT, nullptr); +} + +/******************************************************************************* + * + * Function bta_dm_gatt_disc_complete + * + * Description This function process the GATT service search complete. + * + * Parameters: + * + ******************************************************************************/ +static void bta_dm_gatt_disc_complete(uint16_t conn_id, tGATT_STATUS status) { + log::verbose("conn_id = {}", conn_id); + + auto msg = std::make_unique<tBTA_DM_MSG>(tBTA_DM_SVC_RES{}); + auto& svc_result = std::get<tBTA_DM_SVC_RES>(*msg); + + /* no more services to be discovered */ + svc_result.result = (status == GATT_SUCCESS) ? BTA_SUCCESS : BTA_FAILURE; + log::verbose("service found: 0x{:08x}", bta_dm_search_cb.services_found); + svc_result.services = bta_dm_search_cb.services_found; + svc_result.bd_addr = bta_dm_search_cb.peer_bdaddr; + svc_result.device_type |= BT_DEVICE_TYPE_BLE; + + bta_dm_search_sm_execute(BTA_DM_DISCOVERY_RESULT_EVT, std::move(msg)); + + if (conn_id != GATT_INVALID_CONN_ID) { + bta_dm_search_cb.pending_close_bda = bta_dm_search_cb.peer_bdaddr; + // Gatt will be close immediately if bluetooth.gatt.delay_close.enabled is + // set to false. If property is true / unset there will be a delay + if (bta_dm_search_cb.gatt_close_timer != nullptr) { + /* start a GATT channel close delay timer */ + alarm_set_on_mloop(bta_dm_search_cb.gatt_close_timer, + BTA_DM_GATT_CLOSE_DELAY_TOUT, gatt_close_timer_cb, 0); + } else { + bta_dm_search_sm_execute(BTA_DM_DISC_CLOSE_TOUT_EVT, nullptr); + } + } else { + bta_dm_search_cb.conn_id = GATT_INVALID_CONN_ID; + + if (IS_FLAG_ENABLED(bta_dm_disc_stuck_in_cancelling_fix)) { + log::info( + "Discovery complete for invalid conn ID. Will pick up next job"); + bta_dm_search_set_state(BTA_DM_SEARCH_IDLE); + bta_dm_free_sdp_db(); + bta_dm_execute_queued_request(); + } + } +} + +/******************************************************************************* + * + * Function bta_dm_close_gatt_conn + * + * Description This function close the GATT connection after delay + *timeout. + * + * Parameters: + * + ******************************************************************************/ +static void bta_dm_close_gatt_conn() { + if (bta_dm_search_cb.conn_id != GATT_INVALID_CONN_ID) + BTA_GATTC_Close(bta_dm_search_cb.conn_id); + + bta_dm_search_cb.pending_close_bda = RawAddress::kEmpty; + bta_dm_search_cb.conn_id = GATT_INVALID_CONN_ID; +} +/******************************************************************************* + * + * Function btm_dm_start_gatt_discovery + * + * Description This is GATT initiate the service search by open a GATT + * connection first. + * + * Parameters: + * + ******************************************************************************/ +static void btm_dm_start_gatt_discovery(const RawAddress& bd_addr) { + constexpr bool kUseOpportunistic = true; + + bta_dm_search_cb.gatt_disc_active = true; + + /* connection is already open */ + if (bta_dm_search_cb.pending_close_bda == bd_addr && + bta_dm_search_cb.conn_id != GATT_INVALID_CONN_ID) { + bta_dm_search_cb.pending_close_bda = RawAddress::kEmpty; + alarm_cancel(bta_dm_search_cb.gatt_close_timer); + get_gatt_interface().BTA_GATTC_ServiceSearchRequest( + bta_dm_search_cb.conn_id, nullptr); + } else { + if (get_btm_client_interface().peer.BTM_IsAclConnectionUp( + bd_addr, BT_TRANSPORT_LE)) { + log::debug( + "Use existing gatt client connection for discovery peer:{} " + "transport:{} opportunistic:{:c}", + bd_addr, bt_transport_text(BT_TRANSPORT_LE), + (kUseOpportunistic) ? 'T' : 'F'); + get_gatt_interface().BTA_GATTC_Open(bta_dm_search_cb.client_if, bd_addr, + BTM_BLE_DIRECT_CONNECTION, + kUseOpportunistic); + } else { + log::debug( + "Opening new gatt client connection for discovery peer:{} " + "transport:{} opportunistic:{:c}", + bd_addr, bt_transport_text(BT_TRANSPORT_LE), + (!kUseOpportunistic) ? 'T' : 'F'); + get_gatt_interface().BTA_GATTC_Open(bta_dm_search_cb.client_if, bd_addr, + BTM_BLE_DIRECT_CONNECTION, + !kUseOpportunistic); + } + } +} + +/******************************************************************************* + * + * Function bta_dm_proc_open_evt + * + * Description process BTA_GATTC_OPEN_EVT in DM. + * + * Parameters: + * + ******************************************************************************/ +static void bta_dm_proc_open_evt(tBTA_GATTC_OPEN* p_data) { + log::verbose("DM Search state= {} search_cb.peer_dbaddr:{} connected_bda={}", + bta_dm_search_get_state(), bta_dm_search_cb.peer_bdaddr, + p_data->remote_bda); + + log::debug("BTA_GATTC_OPEN_EVT conn_id = {} client_if={} status = {}", + p_data->conn_id, p_data->client_if, p_data->status); + + disc_gatt_history_.Push(base::StringPrintf( + "%-32s bd_addr:%s conn_id:%hu client_if:%hu event:%s", + "GATTC_EventCallback", ADDRESS_TO_LOGGABLE_CSTR(p_data->remote_bda), + p_data->conn_id, p_data->client_if, + gatt_client_event_text(BTA_GATTC_OPEN_EVT).c_str())); + + bta_dm_search_cb.conn_id = p_data->conn_id; + + if (p_data->status == GATT_SUCCESS) { + get_gatt_interface().BTA_GATTC_ServiceSearchRequest(p_data->conn_id, + nullptr); + } else { + bta_dm_gatt_disc_complete(GATT_INVALID_CONN_ID, p_data->status); + } +} + +/******************************************************************************* + * + * Function bta_dm_gattc_callback + * + * Description This is GATT client callback function used in DM. + * + * Parameters: + * + ******************************************************************************/ +static void bta_dm_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) { + log::verbose("bta_dm_gattc_callback event = {}", event); + + switch (event) { + case BTA_GATTC_OPEN_EVT: + bta_dm_proc_open_evt(&p_data->open); + break; + + case BTA_GATTC_SEARCH_CMPL_EVT: + switch (bta_dm_search_get_state()) { + case BTA_DM_SEARCH_IDLE: + break; + case BTA_DM_SEARCH_ACTIVE: + case BTA_DM_SEARCH_CANCELLING: + case BTA_DM_DISCOVER_ACTIVE: + bta_dm_gatt_disc_complete(p_data->search_cmpl.conn_id, + p_data->search_cmpl.status); + break; + } + disc_gatt_history_.Push(base::StringPrintf( + "%-32s conn_id:%hu status:%s", "GATTC_EventCallback", + p_data->search_cmpl.conn_id, + gatt_status_text(p_data->search_cmpl.status).c_str())); + break; + + case BTA_GATTC_CLOSE_EVT: + log::info("BTA_GATTC_CLOSE_EVT reason = {}", p_data->close.reason); + + if (p_data->close.remote_bda == bta_dm_search_cb.peer_bdaddr) { + bta_dm_search_cb.conn_id = GATT_INVALID_CONN_ID; + } + + switch (bta_dm_search_get_state()) { + case BTA_DM_SEARCH_IDLE: + case BTA_DM_SEARCH_ACTIVE: + break; + + case BTA_DM_SEARCH_CANCELLING: + case BTA_DM_DISCOVER_ACTIVE: + /* in case of disconnect before search is completed */ + if (p_data->close.remote_bda == bta_dm_search_cb.peer_bdaddr) { + bta_dm_gatt_disc_complete((uint16_t)GATT_INVALID_CONN_ID, + (tGATT_STATUS)GATT_ERROR); + } + } + break; + + case BTA_GATTC_ACL_EVT: + case BTA_GATTC_CANCEL_OPEN_EVT: + case BTA_GATTC_CFG_MTU_EVT: + case BTA_GATTC_CONGEST_EVT: + case BTA_GATTC_CONN_UPDATE_EVT: + case BTA_GATTC_DEREG_EVT: + case BTA_GATTC_ENC_CMPL_CB_EVT: + case BTA_GATTC_EXEC_EVT: + case BTA_GATTC_NOTIF_EVT: + case BTA_GATTC_PHY_UPDATE_EVT: + case BTA_GATTC_SEARCH_RES_EVT: + case BTA_GATTC_SRVC_CHG_EVT: + case BTA_GATTC_SRVC_DISC_DONE_EVT: + case BTA_GATTC_SUBRATE_CHG_EVT: + disc_gatt_history_.Push( + base::StringPrintf("%-32s event:%s", "GATTC_EventCallback", + gatt_client_event_text(event).c_str())); + break; + } +} + +namespace bluetooth { +namespace legacy { +namespace testing { + +void bta_dm_remname_cback(const tBTM_REMOTE_DEV_NAME* p) { + ::bta_dm_disc_legacy::bta_dm_remname_cback(p); +} + +tBT_TRANSPORT bta_dm_determine_discovery_transport(const RawAddress& bd_addr) { + return ::bta_dm_disc_legacy::bta_dm_determine_discovery_transport(bd_addr); +} + +void bta_dm_remote_name_cmpl(const tBTA_DM_REMOTE_NAME& remote_name_msg) { + ::bta_dm_disc_legacy::bta_dm_remote_name_cmpl(remote_name_msg); +} + +void bta_dm_sdp_result(tBTA_DM_SDP_RESULT& sdp_event) { + ::bta_dm_disc_legacy::bta_dm_sdp_result(sdp_event); +} + +} // namespace testing +} // namespace legacy +} // namespace bluetooth + +namespace { +constexpr size_t kSearchStateHistorySize = 50; +constexpr char kTimeFormatString[] = "%Y-%m-%d %H:%M:%S"; + +constexpr unsigned MillisPerSecond = 1000; +std::string EpochMillisToString(long long time_ms) { + time_t time_sec = time_ms / MillisPerSecond; + struct tm tm; + localtime_r(&time_sec, &tm); + std::string s = ::bluetooth::common::StringFormatTime(kTimeFormatString, tm); + return base::StringPrintf( + "%s.%03u", s.c_str(), + static_cast<unsigned int>(time_ms % MillisPerSecond)); +} + +} // namespace + +struct tSEARCH_STATE_HISTORY { + const tBTA_DM_STATE state; + const tBTA_DM_EVT event; + std::string ToString() const { + return base::StringPrintf("state:%25s event:%s", + bta_dm_state_text(state).c_str(), + bta_dm_event_text(event).c_str()); + } +}; + +::bluetooth::common::TimestampedCircularBuffer<tSEARCH_STATE_HISTORY> + search_state_history_(kSearchStateHistorySize); + +/******************************************************************************* + * + * Function bta_dm_search_sm_execute + * + * Description State machine event handling function for DM + * + * + * Returns void + * + ******************************************************************************/ +static void bta_dm_search_sm_execute(tBTA_DM_EVT event, + std::unique_ptr<tBTA_DM_MSG> msg) { + log::info("state:{}, event:{}[0x{:x}]", + bta_dm_state_text(bta_dm_search_get_state()), + bta_dm_event_text(event), event); + search_state_history_.Push({ + .state = bta_dm_search_get_state(), + .event = event, + }); + + switch (bta_dm_search_get_state()) { + case BTA_DM_SEARCH_IDLE: + switch (event) { + case BTA_DM_API_SEARCH_EVT: + bta_dm_search_set_state(BTA_DM_SEARCH_ACTIVE); + log::assert_that(std::holds_alternative<tBTA_DM_API_SEARCH>(*msg), + "bad message type: {}", msg->index()); + + bta_dm_search_start(std::get<tBTA_DM_API_SEARCH>(*msg)); + break; + case BTA_DM_API_DISCOVER_EVT: + bta_dm_search_set_state(BTA_DM_DISCOVER_ACTIVE); + log::assert_that(std::holds_alternative<tBTA_DM_API_DISCOVER>(*msg), + "bad message type: {}", msg->index()); + + bta_dm_discover(std::get<tBTA_DM_API_DISCOVER>(*msg)); + break; + case BTA_DM_API_SEARCH_CANCEL_EVT: + bta_dm_search_clear_queue(); + bta_dm_search_cancel_notify(); + break; + case BTA_DM_SDP_RESULT_EVT: + bta_dm_free_sdp_db(); + break; + case BTA_DM_DISC_CLOSE_TOUT_EVT: + bta_dm_close_gatt_conn(); + break; + default: + log::info("Received unexpected event {}[0x{:x}] in state {}", + bta_dm_event_text(event), event, + bta_dm_state_text(bta_dm_search_get_state())); + } + break; + case BTA_DM_SEARCH_ACTIVE: + switch (event) { + case BTA_DM_REMT_NAME_EVT: + log::assert_that(std::holds_alternative<tBTA_DM_REMOTE_NAME>(*msg), + "bad message type: {}", msg->index()); + + bta_dm_remote_name_cmpl(std::get<tBTA_DM_REMOTE_NAME>(*msg)); + break; + case BTA_DM_SEARCH_CMPL_EVT: + bta_dm_search_cmpl(); + break; + case BTA_DM_DISCOVERY_RESULT_EVT: + log::assert_that(std::holds_alternative<tBTA_DM_SVC_RES>(*msg), + "bad message type: {}", msg->index()); + + bta_dm_disc_result(std::get<tBTA_DM_SVC_RES>(*msg)); + break; + case BTA_DM_DISC_CLOSE_TOUT_EVT: + bta_dm_close_gatt_conn(); + break; + case BTA_DM_API_DISCOVER_EVT: + log::assert_that(std::holds_alternative<tBTA_DM_API_DISCOVER>(*msg), + "bad message type: {}", msg->index()); + + bta_dm_queue_disc(std::get<tBTA_DM_API_DISCOVER>(*msg)); + break; + case BTA_DM_API_SEARCH_CANCEL_EVT: + bta_dm_search_clear_queue(); + bta_dm_search_set_state(BTA_DM_SEARCH_CANCELLING); + bta_dm_search_cancel(); + break; + default: + log::info("Received unexpected event {}[0x{:x}] in state {}", + bta_dm_event_text(event), event, + bta_dm_state_text(bta_dm_search_get_state())); + } + break; + case BTA_DM_SEARCH_CANCELLING: + switch (event) { + case BTA_DM_API_SEARCH_EVT: + log::assert_that(std::holds_alternative<tBTA_DM_API_SEARCH>(*msg), + "bad message type: {}", msg->index()); + + bta_dm_queue_search(std::get<tBTA_DM_API_SEARCH>(*msg)); + break; + case BTA_DM_API_DISCOVER_EVT: + log::assert_that(std::holds_alternative<tBTA_DM_API_DISCOVER>(*msg), + "bad message type: {}", msg->index()); + + bta_dm_queue_disc(std::get<tBTA_DM_API_DISCOVER>(*msg)); + break; + case BTA_DM_API_SEARCH_CANCEL_EVT: + bta_dm_search_clear_queue(); + bta_dm_search_cancel_notify(); + break; + case BTA_DM_SDP_RESULT_EVT: + case BTA_DM_REMT_NAME_EVT: + case BTA_DM_SEARCH_CMPL_EVT: + case BTA_DM_DISCOVERY_RESULT_EVT: + bta_dm_search_set_state(BTA_DM_SEARCH_IDLE); + bta_dm_free_sdp_db(); + bta_dm_search_cancel_notify(); + bta_dm_execute_queued_request(); + break; + case BTA_DM_DISC_CLOSE_TOUT_EVT: + bta_dm_close_gatt_conn(); + break; + default: + log::info("Received unexpected event {}[0x{:x}] in state {}", + bta_dm_event_text(event), event, + bta_dm_state_text(bta_dm_search_get_state())); + } + break; + case BTA_DM_DISCOVER_ACTIVE: + switch (event) { + case BTA_DM_REMT_NAME_EVT: + log::assert_that(std::holds_alternative<tBTA_DM_REMOTE_NAME>(*msg), + "bad message type: {}", msg->index()); + + bta_dm_remote_name_cmpl(std::get<tBTA_DM_REMOTE_NAME>(*msg)); + break; + case BTA_DM_SDP_RESULT_EVT: + log::assert_that(std::holds_alternative<tBTA_DM_SDP_RESULT>(*msg), + "bad message type: {}", msg->index()); + + bta_dm_sdp_result(std::get<tBTA_DM_SDP_RESULT>(*msg)); + break; + case BTA_DM_SEARCH_CMPL_EVT: + bta_dm_search_cmpl(); + break; + case BTA_DM_DISCOVERY_RESULT_EVT: + log::assert_that(std::holds_alternative<tBTA_DM_SVC_RES>(*msg), + "bad message type: {}", msg->index()); + + bta_dm_disc_result(std::get<tBTA_DM_SVC_RES>(*msg)); + break; + case BTA_DM_API_SEARCH_EVT: + log::assert_that(std::holds_alternative<tBTA_DM_API_SEARCH>(*msg), + "bad message type: {}", msg->index()); + + bta_dm_queue_search(std::get<tBTA_DM_API_SEARCH>(*msg)); + break; + case BTA_DM_API_DISCOVER_EVT: + log::assert_that(std::holds_alternative<tBTA_DM_API_DISCOVER>(*msg), + "bad message type: {}", msg->index()); + + bta_dm_queue_disc(std::get<tBTA_DM_API_DISCOVER>(*msg)); + break; + case BTA_DM_API_SEARCH_CANCEL_EVT: + bta_dm_search_clear_queue(); + if (IS_FLAG_ENABLED( + continue_service_discovery_when_cancel_device_discovery)) { + bta_dm_search_set_state(BTA_DM_SEARCH_CANCELLING); + } + bta_dm_search_cancel_notify(); + break; + case BTA_DM_DISC_CLOSE_TOUT_EVT: + bta_dm_close_gatt_conn(); + break; + default: + log::info("Received unexpected event {}[0x{:x}] in state {}", + bta_dm_event_text(event), event, + bta_dm_state_text(bta_dm_search_get_state())); + } + break; + } +} + +static void bta_dm_disc_init_search_cb(tBTA_DM_SEARCH_CB& bta_dm_search_cb) { + bta_dm_search_cb = {}; + bta_dm_search_cb.state = BTA_DM_SEARCH_IDLE; + bta_dm_search_cb.conn_id = GATT_INVALID_CONN_ID; + bta_dm_search_cb.transport = BT_TRANSPORT_AUTO; +} + +static void bta_dm_disc_reset() { + alarm_free(bta_dm_search_cb.search_timer); + alarm_free(bta_dm_search_cb.gatt_close_timer); + bta_dm_search_cb.p_pending_search.reset(); + bta_dm_search_cb.pending_discovery_queue = {}; + bta_dm_disc_init_search_cb(bta_dm_search_cb); +} + +void bta_dm_disc_start(bool delay_close_gatt) { + bta_dm_disc_reset(); + bta_dm_search_cb.search_timer = alarm_new("bta_dm_search.search_timer"); + bta_dm_search_cb.gatt_close_timer = + delay_close_gatt ? alarm_new("bta_dm_search.gatt_close_timer") : nullptr; + bta_dm_search_cb.pending_discovery_queue = {}; +} + +void bta_dm_disc_acl_down(const RawAddress& bd_addr, tBT_TRANSPORT transport) { + switch (transport) { + case BT_TRANSPORT_BR_EDR: + if (bta_dm_search_cb.wait_disc && + bta_dm_search_cb.peer_bdaddr == bd_addr) { + bta_dm_search_cb.wait_disc = false; + + if (bta_dm_search_cb.sdp_results) { + log::verbose("timer stopped"); + alarm_cancel(bta_dm_search_cb.search_timer); + bta_dm_disc_discover_next_device(); + } + } + break; + + case BT_TRANSPORT_LE: + default: + break; + } +} + +void bta_dm_disc_stop() { bta_dm_disc_reset(); } + +void bta_dm_disc_start_device_discovery(tBTA_DM_SEARCH_CBACK* p_cback) { + bta_dm_search_sm_execute( + BTA_DM_API_SEARCH_EVT, + std::make_unique<tBTA_DM_MSG>(tBTA_DM_API_SEARCH{.p_cback = p_cback})); +} + +void bta_dm_disc_stop_device_discovery() { + bta_dm_search_sm_execute(BTA_DM_API_SEARCH_CANCEL_EVT, nullptr); +} + +void bta_dm_disc_start_service_discovery(service_discovery_callbacks cbacks, + const RawAddress& bd_addr, + tBT_TRANSPORT transport) { + bta_dm_search_sm_execute( + BTA_DM_API_DISCOVER_EVT, + std::make_unique<tBTA_DM_MSG>(tBTA_DM_API_DISCOVER{ + .bd_addr = bd_addr, .cbacks = cbacks, .transport = transport})); +} + +#define DUMPSYS_TAG "shim::legacy::bta::dm" +void DumpsysBtaDmDisc(int fd) { + auto copy = search_state_history_.Pull(); + LOG_DUMPSYS(fd, " last %zu search state transitions", copy.size()); + for (const auto& it : copy) { + LOG_DUMPSYS(fd, " %s %s", EpochMillisToString(it.timestamp).c_str(), + it.entry.ToString().c_str()); + } + LOG_DUMPSYS(fd, " current bta_dm_search_state:%s", + bta_dm_state_text(bta_dm_search_get_state()).c_str()); +} +#undef DUMPSYS_TAG + +namespace bluetooth { +namespace legacy { +namespace testing { + +void bta_dm_disc_init_search_cb(tBTA_DM_SEARCH_CB& bta_dm_search_cb) { + ::bta_dm_disc_legacy::bta_dm_disc_init_search_cb(bta_dm_search_cb); +} +tBTA_DM_SEARCH_CB bta_dm_disc_get_search_cb() { + tBTA_DM_SEARCH_CB search_cb = {}; + ::bta_dm_disc_legacy::bta_dm_disc_init_search_cb(search_cb); + return search_cb; +} +tBTA_DM_SEARCH_CB& bta_dm_disc_search_cb() { + return ::bta_dm_disc_legacy::bta_dm_search_cb; +} +bool bta_dm_read_remote_device_name(const RawAddress& bd_addr, + tBT_TRANSPORT transport) { + return ::bta_dm_disc_legacy::bta_dm_read_remote_device_name(bd_addr, + transport); +} +void bta_dm_discover_next_device() { + ::bta_dm_disc_legacy::bta_dm_discover_next_device(); +} + +void bta_dm_execute_queued_request() { + ::bta_dm_disc_legacy::bta_dm_execute_queued_request(); +} +void bta_dm_find_services(const RawAddress& bd_addr) { + ::bta_dm_disc_legacy::bta_dm_find_services(bd_addr); +} +void bta_dm_inq_cmpl() { ::bta_dm_disc_legacy::bta_dm_inq_cmpl(); } +void bta_dm_inq_cmpl_cb(void* p_result) { + ::bta_dm_disc_legacy::bta_dm_inq_cmpl_cb(p_result); +} +void bta_dm_observe_cmpl_cb(void* p_result) { + ::bta_dm_disc_legacy::bta_dm_observe_cmpl_cb(p_result); +} +void bta_dm_observe_results_cb(tBTM_INQ_RESULTS* p_inq, const uint8_t* p_eir, + uint16_t eir_len) { + ::bta_dm_disc_legacy::bta_dm_observe_results_cb(p_inq, p_eir, eir_len); +} +void bta_dm_opportunistic_observe_results_cb(tBTM_INQ_RESULTS* p_inq, + const uint8_t* p_eir, + uint16_t eir_len) { + ::bta_dm_disc_legacy::bta_dm_opportunistic_observe_results_cb(p_inq, p_eir, + eir_len); +} +void bta_dm_queue_search(tBTA_DM_API_SEARCH& search) { + ::bta_dm_disc_legacy::bta_dm_queue_search(search); +} + +void bta_dm_service_search_remname_cback(const RawAddress& bd_addr, + DEV_CLASS dc, BD_NAME bd_name) { + ::bta_dm_disc_legacy::bta_dm_service_search_remname_cback(bd_addr, dc, + bd_name); +} + +void bta_dm_start_scan(uint8_t duration_sec, bool low_latency_scan = false) { + ::bta_dm_disc_legacy::bta_dm_start_scan(duration_sec, low_latency_scan); +} + +void store_avrcp_profile_feature(tSDP_DISC_REC* sdp_rec) { + ::bta_dm_disc_legacy::store_avrcp_profile_feature(sdp_rec); +} + +} // namespace testing +} // namespace legacy +} // namespace bluetooth + +} // namespace bta_dm_disc_legacy diff --git a/system/bta/dm/bta_dm_disc_legacy.h b/system/bta/dm/bta_dm_disc_legacy.h new file mode 100644 index 0000000000..c6ae6eb57d --- /dev/null +++ b/system/bta/dm/bta_dm_disc_legacy.h @@ -0,0 +1,71 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "bta/include/bta_api.h" // tBTA_DM_SEARCH_CBACK +#include "stack/include/bt_hdr.h" +#include "types/bt_transport.h" +#include "types/raw_address.h" + +// TODO: Remove this file after flag separate_service_and_device_discovery rolls +// out +namespace bta_dm_disc_legacy { + +// Bta module start and stop entry points +void bta_dm_disc_start(bool delay_close_gatt); +void bta_dm_disc_stop(); + +// Bta device discovery start and stop entry points +void bta_dm_disc_start_device_discovery(tBTA_DM_SEARCH_CBACK*); +void bta_dm_disc_stop_device_discovery(); + +// Bta service discovery start and stop entry points +void bta_dm_disc_start_service_discovery(service_discovery_callbacks cbacks, + const RawAddress& bd_addr, + tBT_TRANSPORT transport); + +// Bta subsystem entrypoint and lifecycle +void bta_dm_disc_disable_search_and_disc(); +// Indication that an acl has gone down and to examine the current +// service discovery procedure, if any. +void bta_dm_disc_acl_down(const RawAddress& bd_addr, tBT_TRANSPORT transport); + +// Return most recent remote name +const char* bta_dm_get_remname(void); + +// LE observe and scan interface +void bta_dm_ble_scan(bool start, uint8_t duration_sec, bool low_latency_scan); +void bta_dm_ble_csis_observe(bool observe, tBTA_DM_SEARCH_CBACK* p_cback); + +// Checks if there is a device discovery request queued +bool bta_dm_is_search_request_queued(); + +// Proceed to execute service discovery on next device in queue +void bta_dm_disc_discover_next_device(); + +// GATT service discovery +void bta_dm_disc_gattc_register(); +void bta_dm_disc_gatt_cancel_open(const RawAddress& bd_addr); +void bta_dm_disc_gatt_refresh(const RawAddress& bd_addr); + +// Stop service discovery procedure, if any, for removed device +void bta_dm_disc_remove_device(const RawAddress& bd_addr); + +// Provide data for the dumpsys procedure +void DumpsysBtaDmDisc(int fd); + +} // namespace bta_dm_disc_legacy diff --git a/system/bta/dm/bta_dm_main.cc b/system/bta/dm/bta_dm_main.cc index 1b3e7444a9..966fb85d57 100644 --- a/system/bta/dm/bta_dm_main.cc +++ b/system/bta/dm/bta_dm_main.cc @@ -24,6 +24,7 @@ #include <base/strings/stringprintf.h> #include <stddef.h> +#include "bta/dm/bta_dm_device_search.h" #include "bta/dm/bta_dm_disc.h" #include "bta/dm/bta_dm_gatt_client.h" #include "bta/dm/bta_dm_int.h" @@ -40,6 +41,7 @@ tBTA_DM_SEC_CB bta_dm_sec_cb; void DumpsysBtaDm(int fd) { LOG_DUMPSYS_TITLE(fd, DUMPSYS_TAG); DumpsysBtaDmDisc(fd); + DumpsysBtaDmSearch(fd); DumpsysBtaDmGattClient(fd); } #undef DUMPSYS_TAG diff --git a/system/bta/dm/bta_dm_sec.cc b/system/bta/dm/bta_dm_sec.cc index 829dfaa54e..2234f4426d 100644 --- a/system/bta/dm/bta_dm_sec.cc +++ b/system/bta/dm/bta_dm_sec.cc @@ -721,9 +721,7 @@ static uint8_t bta_dm_ble_smp_cback(tBTM_LE_EVT event, const RawAddress& bda, case BTM_LE_NC_REQ_EVT: sec_event.key_notif.bd_addr = bda; - // TODO: get rid of this - bd_name_from_char_pointer(sec_event.key_notif.bd_name, - bta_dm_get_remname()); + bd_name_clear(sec_event.key_notif.bd_name); sec_event.key_notif.passkey = p_data->key_notif; bta_dm_sec_cb.p_sec_cback(BTA_DM_BLE_NC_REQ_EVT, &sec_event); break; @@ -820,7 +818,7 @@ void bta_dm_encrypt_cback(const RawAddress* bd_addr, tBT_TRANSPORT transport, } log::debug("Encrypted:{:c}, peer:{} transport:{} status:{} callback:{:c}", - result == BTM_SUCCESS ? 'T' : 'F', (*bd_addr), + result == BTM_SUCCESS ? 'T' : 'F', *bd_addr, bt_transport_text(transport), btm_status_text(result), (p_callback) ? 'T' : 'F'); diff --git a/system/bta/gatt/bta_gattc_act.cc b/system/bta/gatt/bta_gattc_act.cc index d6994c9622..f25c6ad4aa 100644 --- a/system/bta/gatt/bta_gattc_act.cc +++ b/system/bta/gatt/bta_gattc_act.cc @@ -361,15 +361,16 @@ void bta_gattc_open_fail(tBTA_GATTC_CLCB* p_clcb, if (IS_FLAG_ENABLED(enumerate_gatt_errors) && p_data->int_conn.reason == GATT_CONN_TIMEOUT) { log::warn( - "Connection timed out after 30 seconds. conn_id={}. Return " + "Connection timed out after 30 seconds. conn_id=0x{:x}. Return " "GATT_CONNECTION_TIMEOUT({})", - loghex(p_clcb->bta_conn_id), GATT_CONNECTION_TIMEOUT); + p_clcb->bta_conn_id, GATT_CONNECTION_TIMEOUT); bta_gattc_send_open_cback(p_clcb->p_rcb, GATT_CONNECTION_TIMEOUT, p_clcb->bda, p_clcb->bta_conn_id, p_clcb->transport, 0); } else { - log::warn("Cannot establish Connection. conn_id={}. Return GATT_ERROR({})", - loghex(p_clcb->bta_conn_id), GATT_ERROR); + log::warn( + "Cannot establish Connection. conn_id=0x{:x}. Return GATT_ERROR({})", + p_clcb->bta_conn_id, GATT_ERROR); bta_gattc_send_open_cback(p_clcb->p_rcb, GATT_ERROR, p_clcb->bda, p_clcb->bta_conn_id, p_clcb->transport, 0); } @@ -517,7 +518,7 @@ void bta_gattc_conn(tBTA_GATTC_CLCB* p_clcb, const tBTA_GATTC_DATA* p_data) { log::verbose("server cache state={}", p_clcb->p_srcb->state); if (p_data != NULL) { - log::verbose("conn_id={}", loghex(p_data->hdr.layer_specific)); + log::verbose("conn_id=0x{:x}", p_data->hdr.layer_specific); p_clcb->bta_conn_id = p_data->int_conn.hdr.layer_specific; GATT_GetConnectionInfor(p_data->hdr.layer_specific, &gatt_if, p_clcb->bda, @@ -569,9 +570,7 @@ void bta_gattc_conn(tBTA_GATTC_CLCB* p_clcb, const tBTA_GATTC_DATA* p_data) { p_clcb->p_srcb->state = BTA_GATTC_SERV_DISC; /* set true to read database hash before service discovery */ - if (bta_gattc_is_robust_caching_enabled()) { - p_clcb->p_srcb->srvc_hdl_db_hash = true; - } + p_clcb->p_srcb->srvc_hdl_db_hash = true; /* cache load failure, start discovery */ bta_gattc_start_discover(p_clcb, NULL); @@ -589,9 +588,7 @@ void bta_gattc_conn(tBTA_GATTC_CLCB* p_clcb, const tBTA_GATTC_DATA* p_data) { p_clcb->p_srcb->srvc_hdl_chg = false; /* set true to read database hash before service discovery */ - if (bta_gattc_is_robust_caching_enabled()) { - p_clcb->p_srcb->srvc_hdl_db_hash = true; - } + p_clcb->p_srcb->srvc_hdl_db_hash = true; /* start discovery */ bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL); @@ -622,8 +619,8 @@ void bta_gattc_close_fail(tBTA_GATTC_CLCB* p_clcb, cb_data.close.reason = BTA_GATT_CONN_NONE; cb_data.close.status = GATT_ERROR; - log::warn("conn_id={}. Returns GATT_ERROR({}).", - loghex(cb_data.close.conn_id), GATT_ERROR); + log::warn("conn_id=0x{:x}. Returns GATT_ERROR({}).", cb_data.close.conn_id, + GATT_ERROR); (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CLOSE_EVT, &cb_data); } @@ -707,12 +704,18 @@ void bta_gattc_reset_discover_st(tBTA_GATTC_SERV* p_srcb, tGATT_STATUS status) { /** close a GATTC connection while in discovery state */ void bta_gattc_disc_close(tBTA_GATTC_CLCB* p_clcb, const tBTA_GATTC_DATA* p_data) { - log::verbose("Discovery cancel conn_id={}", loghex(p_clcb->bta_conn_id)); - - if (p_clcb->disc_active) + log::verbose("Discovery cancel conn_id=0x{:x}", p_clcb->bta_conn_id); + + if (p_clcb->disc_active || + (IS_FLAG_ENABLED(gatt_rediscover_on_canceled) && + (p_clcb->request_during_discovery == + BTA_GATTC_DISCOVER_REQ_READ_DB_HASH || + p_clcb->request_during_discovery == + BTA_GATTC_DISCOVER_REQ_READ_DB_HASH_FOR_SVC_CHG))) { bta_gattc_reset_discover_st(p_clcb->p_srcb, GATT_ERROR); - else + } else { p_clcb->state = BTA_GATTC_CONN_ST; + } // This function only gets called as the result of a BTA_GATTC_API_CLOSE_EVT // while in the BTA_GATTC_DISCOVER_ST state. Once the state changes, the @@ -823,8 +826,8 @@ static void bta_gattc_continue_with_version_and_cache_known( /** Start a discovery on server */ void bta_gattc_start_discover(tBTA_GATTC_CLCB* p_clcb, const tBTA_GATTC_DATA* /* p_data */) { - log::verbose("conn_id:{} p_clcb->p_srcb->state:{}", - loghex(p_clcb->bta_conn_id), p_clcb->p_srcb->state); + log::verbose("conn_id:0x{:x} p_clcb->p_srcb->state:{}", p_clcb->bta_conn_id, + p_clcb->p_srcb->state); if (((p_clcb->p_q_cmd == NULL || p_clcb->auto_update == BTA_GATTC_REQ_WAITING) && @@ -919,11 +922,10 @@ void bta_gattc_continue_with_version_and_cache_known( } /* read db hash if db hash characteristic exists */ - if (bta_gattc_is_robust_caching_enabled() && - p_clcb->p_srcb->srvc_hdl_db_hash && + if (p_clcb->p_srcb->srvc_hdl_db_hash && bta_gattc_read_db_hash(p_clcb, is_svc_chg)) { - log::info("pending service discovery, read db hash first conn_id:{}", - loghex(p_clcb->bta_conn_id)); + log::info("pending service discovery, read db hash first conn_id:0x{:x}", + p_clcb->bta_conn_id); p_clcb->p_srcb->srvc_hdl_db_hash = false; return; } @@ -935,7 +937,7 @@ void bta_gattc_disc_cmpl(tBTA_GATTC_CLCB* p_clcb, const tBTA_GATTC_DATA* /* p_data */) { const tBTA_GATTC_DATA* p_q_cmd = p_clcb->p_q_cmd; - log::verbose("conn_id={}", loghex(p_clcb->bta_conn_id)); + log::verbose("conn_id=0x{:x}", p_clcb->bta_conn_id); if (p_clcb->transport == BT_TRANSPORT_LE) { L2CA_LockBleConnParamsForServiceDiscovery(p_clcb->p_srcb->server_bda, @@ -1114,7 +1116,7 @@ void bta_gattc_confirm(tBTA_GATTC_CLCB* p_clcb, const tBTA_GATTC_DATA* p_data) { if (GATTC_SendHandleValueConfirm(p_data->api_confirm.hdr.layer_specific, cid) != GATT_SUCCESS) { - log::error("to cid={} failed", loghex(cid)); + log::error("to cid=0x{:x} failed", cid); } else { /* if over BR_EDR, inform PM for mode change */ if (p_clcb->transport == BT_TRANSPORT_BR_EDR) { @@ -1309,8 +1311,7 @@ void bta_gattc_op_cmpl(tBTA_GATTC_CLCB* p_clcb, const tBTA_GATTC_DATA* p_data) { // If receive DATABASE_OUT_OF_SYNC error code, bta_gattc should start service // discovery immediately - if (bta_gattc_is_robust_caching_enabled() && - p_data->op_cmpl.status == GATT_DATABASE_OUT_OF_SYNC) { + if (p_data->op_cmpl.status == GATT_DATABASE_OUT_OF_SYNC) { log::info("DATABASE_OUT_OF_SYNC, re-discover service"); p_clcb->auto_update = BTA_GATTC_REQ_WAITING; /* request read db hash first */ @@ -1323,9 +1324,7 @@ void bta_gattc_op_cmpl(tBTA_GATTC_CLCB* p_clcb, const tBTA_GATTC_DATA* p_data) { p_clcb->auto_update = BTA_GATTC_REQ_WAITING; /* request read db hash first */ - if (bta_gattc_is_robust_caching_enabled()) { - p_clcb->p_srcb->srvc_hdl_db_hash = true; - } + p_clcb->p_srcb->srvc_hdl_db_hash = true; bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL); return; @@ -1338,7 +1337,7 @@ void bta_gattc_op_cmpl(tBTA_GATTC_CLCB* p_clcb, const tBTA_GATTC_DATA* p_data) { void bta_gattc_search(tBTA_GATTC_CLCB* p_clcb, const tBTA_GATTC_DATA* p_data) { tGATT_STATUS status = GATT_INTERNAL_ERROR; tBTA_GATTC cb_data; - log::verbose("conn_id={}", loghex(p_clcb->bta_conn_id)); + log::verbose("conn_id=0x{:x}", p_clcb->bta_conn_id); if (p_clcb->p_srcb && !p_clcb->p_srcb->gatt_database.IsEmpty()) { status = GATT_SUCCESS; /* search the local cache of a server device */ @@ -1496,8 +1495,8 @@ static bool bta_gattc_process_srvc_chg_ind(uint16_t conn_id, uint16_t s_handle = ((uint16_t)(*(p)) + (((uint16_t)(*(p + 1))) << 8)); uint16_t e_handle = ((uint16_t)(*(p + 2)) + (((uint16_t)(*(p + 3))) << 8)); - log::error("service changed s_handle={}, e_handle={}", loghex(s_handle), - loghex(e_handle)); + log::error("service changed s_handle=0x{:x}, e_handle=0x{:x}", s_handle, + e_handle); /* mark service handle change pending */ p_srcb->srvc_hdl_chg = true; @@ -1523,9 +1522,7 @@ static bool bta_gattc_process_srvc_chg_ind(uint16_t conn_id, /* if connection available, refresh cache by doing discovery now */ if (p_clcb) { /* request read db hash first */ - if (bta_gattc_is_robust_caching_enabled()) { - p_srcb->srvc_hdl_db_hash = true; - } + p_srcb->srvc_hdl_db_hash = true; bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL); } } @@ -1645,7 +1642,7 @@ static void bta_gattc_cmpl_cback(uint16_t conn_id, tGATTC_OPTYPE op, /* for all other operation, not expected if w/o connection */ tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id); if (!p_clcb) { - log::error("unknown conn_id={} ignore data", loghex(conn_id)); + log::error("unknown conn_id=0x{:x} ignore data", conn_id); return; } diff --git a/system/bta/gatt/bta_gattc_cache.cc b/system/bta/gatt/bta_gattc_cache.cc index d88052647a..037c1bc995 100644 --- a/system/bta/gatt/bta_gattc_cache.cc +++ b/system/bta/gatt/bta_gattc_cache.cc @@ -137,12 +137,6 @@ RobustCachingSupport GetRobustCachingSupport(const tBTA_GATTC_CLCB* p_clcb, log::debug("GetRobustCachingSupport {}", p_clcb->bda.ToRedactedStringForLogging()); - // If the feature is disabled, then we never support it - if (!bta_gattc_is_robust_caching_enabled()) { - log::debug("robust caching is disabled, so UNSUPPORTED"); - return RobustCachingSupport::UNSUPPORTED; - } - // An empty database means that discovery hasn't taken place yet, so // we can't infer anything from that if (!db.IsEmpty()) { @@ -231,7 +225,7 @@ static void bta_gattc_explore_next_service(uint16_t conn_id, tBTA_GATTC_SERV* p_srvc_cb) { tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id); if (!p_clcb) { - log::error("unknown conn_id={}", loghex(conn_id)); + log::error("unknown conn_id=0x{:x}", conn_id); return; } @@ -290,7 +284,7 @@ static void bta_gattc_explore_srvc_finished(uint16_t conn_id, tBTA_GATTC_SERV* p_srvc_cb) { tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id); if (!p_clcb) { - log::error("unknown conn_id={}", loghex(conn_id)); + log::error("unknown conn_id=0x{:x}", conn_id); return; } @@ -305,31 +299,22 @@ static void bta_gattc_explore_srvc_finished(uint16_t conn_id, /* save cache to NV */ p_clcb->p_srcb->state = BTA_GATTC_SERV_SAVE; - // If robust caching is not enabled, use original design - if (!bta_gattc_is_robust_caching_enabled()) { - if (btm_sec_is_a_bonded_dev(p_srvc_cb->server_bda)) { - bta_gattc_cache_write(p_clcb->p_srcb->server_bda, - p_clcb->p_srcb->gatt_database); - } - } else { - // If robust caching is enabled, do something optimized - Octet16 hash = p_clcb->p_srcb->gatt_database.Hash(); - bool success = bta_gattc_hash_write(hash, p_clcb->p_srcb->gatt_database); - - // If the device is trusted, link the addr file to hash file - if (success && btm_sec_is_a_bonded_dev(p_srvc_cb->server_bda)) { - log::debug("Linking db hash to address {}", - p_clcb->p_srcb->server_bda.ToRedactedStringForLogging()); - bta_gattc_cache_link(p_clcb->p_srcb->server_bda, hash); - } + // If robust caching is enabled, do something optimized + Octet16 hash = p_clcb->p_srcb->gatt_database.Hash(); + bool success = bta_gattc_hash_write(hash, p_clcb->p_srcb->gatt_database); - // After success, reset the count. - log::debug( - "service discovery succeed, reset count to zero, conn_id=0x{:04x}", - conn_id); - p_srvc_cb->srvc_disc_count = 0; + // If the device is trusted, link the addr file to hash file + if (success && btm_sec_is_a_bonded_dev(p_srvc_cb->server_bda)) { + log::debug("Linking db hash to address {}", + p_clcb->p_srcb->server_bda.ToRedactedStringForLogging()); + bta_gattc_cache_link(p_clcb->p_srcb->server_bda, hash); } + // After success, reset the count. + log::debug("service discovery succeed, reset count to zero, conn_id=0x{:04x}", + conn_id); + p_srvc_cb->srvc_disc_count = 0; + bta_gattc_reset_discover_st(p_clcb->p_srcb, GATT_SUCCESS); } @@ -397,14 +382,14 @@ void bta_gattc_sdp_callback(const RawAddress& /* bd_addr */, uint16_t end_handle = (uint16_t)pe.params[1]; #if (BTA_GATT_DEBUG == TRUE) - log::verbose("Found ATT service uuid={}, s_handle={}, e_handle={}", - service_uuid, loghex(start_handle), loghex(end_handle)); + log::verbose("Found ATT service uuid={}, s_handle=0x{:x}, e_handle=0x{:x}", + service_uuid, start_handle, end_handle); #endif if (!GATT_HANDLE_IS_VALID(start_handle) || !GATT_HANDLE_IS_VALID(end_handle)) { - log::error("invalid start_handle={}, end_handle={}", loghex(start_handle), - loghex(end_handle)); + log::error("invalid start_handle=0x{:x}, end_handle=0x{:x}", start_handle, + end_handle); p_sdp_rec = get_legacy_stack_sdp_api()->db.SDP_FindServiceInDb( cb_data->p_sdp_db, 0, p_sdp_rec); continue; @@ -472,16 +457,12 @@ void bta_gattc_op_cmpl_during_discovery(tBTA_GATTC_CLCB* p_clcb, bta_gattc_read_ext_prop_desc_cmpl(p_clcb, &p_data->op_cmpl); break; case BTA_GATTC_DISCOVER_REQ_READ_DB_HASH: - case BTA_GATTC_DISCOVER_REQ_READ_DB_HASH_FOR_SVC_CHG: - if (bta_gattc_is_robust_caching_enabled()) { - bool is_svc_chg = (p_clcb->request_during_discovery == - BTA_GATTC_DISCOVER_REQ_READ_DB_HASH_FOR_SVC_CHG); - bta_gattc_read_db_hash_cmpl(p_clcb, &p_data->op_cmpl, is_svc_chg); - } else { - // it is not possible here if flag is off, but just in case - p_clcb->request_during_discovery = BTA_GATTC_DISCOVER_REQ_NONE; - } + case BTA_GATTC_DISCOVER_REQ_READ_DB_HASH_FOR_SVC_CHG: { + bool is_svc_chg = (p_clcb->request_during_discovery == + BTA_GATTC_DISCOVER_REQ_READ_DB_HASH_FOR_SVC_CHG); + bta_gattc_read_db_hash_cmpl(p_clcb, &p_data->op_cmpl, is_svc_chg); break; + } case BTA_GATTC_DISCOVER_REQ_NONE: default: break; @@ -538,8 +519,7 @@ void bta_gattc_disc_cmpl_cback(uint16_t conn_id, tGATT_DISC_TYPE disc_type, if (status == GATT_SUCCESS) p_clcb->status = status; // if db out of sync is received, try to start service discovery if possible - if (bta_gattc_is_robust_caching_enabled() && - status == GATT_DATABASE_OUT_OF_SYNC) { + if (status == GATT_DATABASE_OUT_OF_SYNC) { if (p_srvc_cb && p_srvc_cb->srvc_disc_count < BTA_GATTC_DISCOVER_RETRY_COUNT) { p_srvc_cb->srvc_disc_count++; @@ -852,7 +832,7 @@ static void bta_gattc_read_ext_prop_desc_cmpl( } if (status != GATT_SUCCESS) { - log::warn("Discovery on server failed: {}", loghex(status)); + log::warn("Discovery on server failed: 0x{:x}", status); bta_gattc_reset_discover_st(p_clcb->p_srcb, GATT_ERROR); return; } @@ -1045,7 +1025,7 @@ void bta_gattc_get_gatt_db(uint16_t conn_id, uint16_t start_handle, log::info(""); if (p_clcb == NULL) { - log::error("Unknown conn_id={}", loghex(conn_id)); + log::error("Unknown conn_id=0x{:x}", conn_id); return; } diff --git a/system/bta/gatt/bta_gattc_int.h b/system/bta/gatt/bta_gattc_int.h index aa82640aa8..214852e6f4 100644 --- a/system/bta/gatt/bta_gattc_int.h +++ b/system/bta/gatt/bta_gattc_int.h @@ -471,7 +471,6 @@ void bta_gattc_clear_notif_registration(tBTA_GATTC_SERV* p_srcb, uint16_t conn_id, uint16_t start_handle, uint16_t end_handle); tBTA_GATTC_SERV* bta_gattc_find_srvr_cache(const RawAddress& bda); -bool bta_gattc_is_robust_caching_enabled(); /* discovery functions */ void bta_gattc_disc_res_cback(uint16_t conn_id, tGATT_DISC_TYPE disc_type, diff --git a/system/bta/gatt/bta_gattc_utils.cc b/system/bta/gatt/bta_gattc_utils.cc index 365cd7ba67..f7a3f38eb8 100644 --- a/system/bta/gatt/bta_gattc_utils.cc +++ b/system/bta/gatt/bta_gattc_utils.cc @@ -798,19 +798,6 @@ tBTA_GATTC_CLCB* bta_gattc_find_int_disconn_clcb(tBTA_GATTC_DATA* p_msg) { return p_clcb; } -/******************************************************************************* - * - * Function bta_gattc_is_robust_caching_enabled - * - * Description check if robust caching is enabled - * - * Returns true if enabled; otherwise false - * - ******************************************************************************/ -bool bta_gattc_is_robust_caching_enabled() { - return bluetooth::common::init_flags::gatt_robust_caching_client_is_enabled(); -} - void bta_gatt_client_dump(int fd) { std::stringstream stream; int entry_count = 0; @@ -907,4 +894,4 @@ void bta_gatt_client_dump(int fd) { dprintf(fd, "BTA_GATTC_CB state %s \n%s\n", bta_gattc_state_text(bta_gattc_cb.state).c_str(), stream.str().c_str()); -}
\ No newline at end of file +} diff --git a/system/bta/gatt/bta_gatts_act.cc b/system/bta/gatt/bta_gatts_act.cc index f2ad439b64..5ef5d59bad 100644 --- a/system/bta/gatt/bta_gatts_act.cc +++ b/system/bta/gatt/bta_gatts_act.cc @@ -393,8 +393,8 @@ void bta_gatts_indicate_handle(tBTA_GATTS_CB* p_cb, tBTA_GATTS_DATA* p_msg) { bta_sys_idle(BTA_ID_GATTS, BTA_ALL_APP_ID, remote_bda); } } else { - log::error("Unknown connection_id={} fail sending notification", - loghex(p_msg->api_indicate.hdr.layer_specific)); + log::error("Unknown connection_id=0x{:x} fail sending notification", + p_msg->api_indicate.hdr.layer_specific); } if ((status != GATT_SUCCESS || !p_msg->api_indicate.need_confirm) && @@ -405,8 +405,8 @@ void bta_gatts_indicate_handle(tBTA_GATTS_CB* p_cb, tBTA_GATTS_DATA* p_msg) { (*p_rcb->p_cback)(BTA_GATTS_CONF_EVT, &cb_data); } } else { - log::error("Not an registered servce attribute ID: {}", - loghex(p_msg->api_indicate.attr_id)); + log::error("Not an registered servce attribute ID: 0x{:x}", + p_msg->api_indicate.attr_id); } } @@ -525,7 +525,7 @@ void bta_gatts_close(tBTA_GATTS_CB* /* p_cb */, tBTA_GATTS_DATA* p_msg) { (*p_rcb->p_cback)(BTA_GATTS_CLOSE_EVT, &bta_gatts); } } else { - log::error("Unknown connection_id={}", loghex(p_msg->hdr.layer_specific)); + log::error("Unknown connection_id=0x{:x}", p_msg->hdr.layer_specific); } } @@ -552,8 +552,8 @@ static void bta_gatts_send_request_cback(uint16_t conn_id, uint32_t trans_id, &transport)) { p_rcb = bta_gatts_find_app_rcb_by_app_if(gatt_if); - log::verbose("conn_id={}, trans_id={}, req_type={}", loghex(conn_id), - trans_id, req_type); + log::verbose("conn_id=0x{:x}, trans_id={}, req_type={}", conn_id, trans_id, + req_type); if (p_rcb && p_rcb->p_cback) { /* if over BR_EDR, inform PM for mode change */ @@ -571,7 +571,7 @@ static void bta_gatts_send_request_cback(uint16_t conn_id, uint32_t trans_id, log::error("connection request on gatt_if={} is not interested", gatt_if); } } else { - log::error("request received on unknown conn_id={}", loghex(conn_id)); + log::error("request received on unknown conn_id=0x{:x}", conn_id); } } @@ -592,8 +592,8 @@ static void bta_gatts_conn_cback(tGATT_IF gatt_if, const RawAddress& bdaddr, uint8_t evt = connected ? BTA_GATTS_CONNECT_EVT : BTA_GATTS_DISCONNECT_EVT; tBTA_GATTS_RCB* p_reg; - log::verbose("bda={} gatt_if= {}, conn_id={} connected={}", bdaddr, gatt_if, - loghex(conn_id), connected); + log::verbose("bda={} gatt_if= {}, conn_id=0x{:x} connected={}", bdaddr, + gatt_if, conn_id, connected); if (connected) btif_debug_conn_state(bdaddr, BTIF_DEBUG_CONNECTED, GATT_CONN_OK); diff --git a/system/bta/gatt/database.cc b/system/bta/gatt/database.cc index 60a23961da..a7548d23e0 100644 --- a/system/bta/gatt/database.cc +++ b/system/bta/gatt/database.cc @@ -170,8 +170,8 @@ Database Database::Deserialize(const std::vector<StoredAttribute>& nv_attr, if (current_service_it == result.services.end() || !HandleInRange(*current_service_it, attr.handle)) { - log::error("Can't find service for attribute with handle: {}", - loghex(attr.handle)); + log::error("Can't find service for attribute with handle: 0x{:x}", + attr.handle); *success = false; return result; } diff --git a/system/bta/gatt/database_builder.cc b/system/bta/gatt/database_builder.cc index bf29e4efed..624a24682a 100644 --- a/system/bta/gatt/database_builder.cc +++ b/system/bta/gatt/database_builder.cc @@ -102,9 +102,9 @@ void DatabaseBuilder::AddCharacteristic(uint16_t handle, uint16_t value_handle, if (service->end_handle < value_handle) log::warn( - "Remote device violates spec: value_handle={} is after service " - "end_handle={}", - loghex(value_handle), loghex(service->end_handle)); + "Remote device violates spec: value_handle=0x{:x} is after service " + "end_handle=0x{:x}", + value_handle, service->end_handle); service->characteristics.emplace_back(Characteristic{ .declaration_handle = handle, diff --git a/system/bta/has/has_client.cc b/system/bta/has/has_client.cc index 904fd8b200..229fc49d3a 100644 --- a/system/bta/has/has_client.cc +++ b/system/bta/has/has_client.cc @@ -187,7 +187,7 @@ class HasClientImpl : public HasClient { void AddFromStorage(const RawAddress& address, uint8_t features, uint16_t is_acceptlisted) { - log::debug("{}, features={}, isAcceptlisted={}", address, loghex(features), + log::debug("{}, features=0x{:x}, isAcceptlisted={}", address, features, is_acceptlisted); /* Notify upper layer about the device */ @@ -1008,11 +1008,11 @@ class HasClientImpl : public HasClient { void OnGattWriteCcc(uint16_t conn_id, tGATT_STATUS status, uint16_t handle, void* user_data) { - log::debug("handle={}", loghex(handle)); + log::debug("handle=0x{:x}", handle); auto device = GetDevice(conn_id); if (!device) { - log::error("unknown conn_id={}", loghex(conn_id)); + log::error("unknown conn_id=0x{:x}", conn_id); BtaGattQueue::Clean(conn_id); return; } @@ -1035,8 +1035,8 @@ class HasClientImpl : public HasClient { (handle == device->cp_ccc_handle)) { /* Both of these CCC are mandatory */ if (enabling_ntf && (status != GATT_SUCCESS)) { - log::error("Failed to register for notifications on handle={}", - loghex(handle)); + log::error("Failed to register for notifications on handle=0x{:x}", + handle); BTA_GATTC_Close(conn_id); return; } @@ -1047,7 +1047,7 @@ class HasClientImpl : public HasClient { const uint8_t* value) { auto device = GetDevice(conn_id); if (!device) { - log::warn("Skipping unknown device, conn_id={}", loghex(conn_id)); + log::warn("Skipping unknown device, conn_id=0x{:x}", conn_id); return; } @@ -1103,8 +1103,8 @@ class HasClientImpl : public HasClient { } if (len != 1) { - log::error("Invalid features value length={} at handle={}", len, - loghex(handle)); + log::error("Invalid features value length={} at handle=0x{:x}", len, + handle); BTA_GATTC_Close(device->conn_id); return; } @@ -1486,8 +1486,8 @@ class HasClientImpl : public HasClient { } if (len != 1) { - log::error("Invalid preset value length={} at handle={}", len, - loghex(handle)); + log::error("Invalid preset value length={} at handle=0x{:x}", len, + handle); BTA_GATTC_Close(device->conn_id); return; } @@ -1889,12 +1889,12 @@ class HasClientImpl : public HasClient { auto device = std::find_if(devices_.begin(), devices_.end(), HasDevice::MatchAddress(evt.remote_bda)); if (device == devices_.end()) { - log::warn("Skipping unknown device disconnect, conn_id={}", - loghex(evt.conn_id)); + log::warn("Skipping unknown device disconnect, conn_id=0x{:x}", + evt.conn_id); return; } - log::debug("device={}: reason={}", device->addr, - loghex(static_cast<int>(evt.reason))); + log::debug("device={}: reason=0x{:x}", device->addr, + static_cast<int>(evt.reason)); /* Don't notify disconnect state for background connection that failed */ if (device->is_connecting_actively || device->isGattServiceValid()) @@ -1914,7 +1914,7 @@ class HasClientImpl : public HasClient { void OnGattServiceSearchComplete(const tBTA_GATTC_SEARCH_CMPL& evt) { auto device = GetDevice(evt.conn_id); if (!device) { - log::warn("Skipping unknown device, conn_id={}", loghex(evt.conn_id)); + log::warn("Skipping unknown device, conn_id=0x{:x}", evt.conn_id); return; } @@ -2066,8 +2066,9 @@ class HasClientImpl : public HasClient { tGATT_STATUS register_status = BTA_GATTC_RegisterForNotifications(gatt_if_, address, value_handle); log::debug( - "BTA_GATTC_RegisterForNotifications, status={} value={} ccc={}", - loghex(+register_status), loghex(value_handle), loghex(ccc_handle)); + "BTA_GATTC_RegisterForNotifications, status=0x{:x} value=0x{:x} " + "ccc=0x{:x}", + register_status, value_handle, ccc_handle); if (register_status != GATT_SUCCESS) return; } diff --git a/system/bta/hearing_aid/hearing_aid.cc b/system/bta/hearing_aid/hearing_aid.cc index 6546e546a5..4475528095 100644 --- a/system/bta/hearing_aid/hearing_aid.cc +++ b/system/bta/hearing_aid/hearing_aid.cc @@ -229,8 +229,8 @@ static void write_rpt_ctl_cfg_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, const uint8_t* value, void* data) { if (status != GATT_SUCCESS) { - log::error("handle= {}, conn_id={}, status= {}, length={}", handle, conn_id, - loghex(static_cast<uint8_t>(status)), len); + log::error("handle= {}, conn_id={}, status= 0x{:x}, length={}", handle, + conn_id, static_cast<uint8_t>(status), len); } } @@ -449,7 +449,7 @@ class HearingAidImpl : public HearingAid { bool droppable = std::chrono::duration_cast<std::chrono::seconds>(duration).count() >= DROP_FREQUENCY_THRESHOLD; - log::info("IsBelowDropFrequency {}", droppable ? "true" : "false"); + log::info("IsBelowDropFrequency {}", droppable); return droppable; } @@ -466,8 +466,8 @@ class HearingAidImpl : public HearingAid { } void AddFromStorage(const HearingDevice& dev_info, bool is_acceptlisted) { - log::debug("{}, hiSyncId={}, isAcceptlisted={}", dev_info.address, - loghex(dev_info.hi_sync_id), is_acceptlisted); + log::debug("{}, hiSyncId=0x{:x}, isAcceptlisted={}", dev_info.address, + dev_info.hi_sync_id, is_acceptlisted); if (is_acceptlisted) { hearingDevices.Add(dev_info); @@ -581,7 +581,7 @@ class HearingAidImpl : public HearingAid { void OnConnectionUpdateComplete(uint16_t conn_id, tBTA_GATTC* p_data) { HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id); if (!hearingDevice) { - log::debug("Skipping unknown device, conn_id={}", loghex(conn_id)); + log::debug("Skipping unknown device, conn_id=0x{:x}", conn_id); return; } @@ -634,9 +634,9 @@ class HearingAidImpl : public HearingAid { send_state_change(hearingDevice, conn_update); } else { log::info( - "error status={}, conn_id={},device={}, " + "error status=0x{:x}, conn_id={},device={}, " "connection_update_status={}", - loghex(static_cast<uint8_t>(p_data->conn_update.status)), conn_id, + static_cast<uint8_t>(p_data->conn_update.status), conn_id, hearingDevice->address, hearingDevice->connection_update_status); if (hearingDevice->connection_update_status == STARTED) { // Redo this connection interval change. @@ -728,7 +728,7 @@ class HearingAidImpl : public HearingAid { tGATT_STATUS status) { HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id); if (!hearingDevice) { - log::debug("Skipping unknown device, conn_id={}", loghex(conn_id)); + log::debug("Skipping unknown device, conn_id=0x{:x}", conn_id); return; } if (status != GATT_SUCCESS) { @@ -790,7 +790,7 @@ class HearingAidImpl : public HearingAid { void OnServiceSearchComplete(uint16_t conn_id, tGATT_STATUS status) { HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id); if (!hearingDevice) { - log::debug("Skipping unknown device, conn_id={}", loghex(conn_id)); + log::debug("Skipping unknown device, conn_id=0x{:x}", conn_id); return; } @@ -812,12 +812,12 @@ class HearingAidImpl : public HearingAid { const gatt::Service* service = nullptr; for (const gatt::Service& tmp : *services) { if (tmp.uuid == Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER)) { - log::info("Found UUID_SERVCLASS_GATT_SERVER, handle={}", - loghex(tmp.handle)); + log::info("Found UUID_SERVCLASS_GATT_SERVER, handle=0x{:x}", + tmp.handle); const gatt::Service* service_changed_service = &tmp; find_server_changed_ccc_handle(conn_id, service_changed_service); } else if (tmp.uuid == HEARING_AID_UUID) { - log::info("Found Hearing Aid service, handle={}", loghex(tmp.handle)); + log::info("Found Hearing Aid service, handle=0x{:x}", tmp.handle); service = &tmp; } } @@ -835,8 +835,8 @@ class HearingAidImpl : public HearingAid { hearingDevice->address, &hearingDevice->capabilities, &hearingDevice->hi_sync_id, &hearingDevice->render_delay, &hearingDevice->preparation_delay, &hearingDevice->codecs)) { - log::debug("Reading read only properties {}", - loghex(charac.value_handle)); + log::debug("Reading read only properties 0x{:x}", + charac.value_handle); BtaGattQueue::ReadCharacteristic( conn_id, charac.value_handle, HearingAidImpl::OnReadOnlyPropertiesReadStatic, nullptr); @@ -854,8 +854,8 @@ class HearingAidImpl : public HearingAid { continue; } - log::info("audio_status_handle={}, ccc={}", loghex(charac.value_handle), - loghex(hearingDevice->audio_status_ccc_handle)); + log::info("audio_status_handle=0x{:x}, ccc=0x{:x}", charac.value_handle, + hearingDevice->audio_status_ccc_handle); } else if (charac.uuid == VOLUME_UUID) { hearingDevice->volume_handle = charac.value_handle; } else if (charac.uuid == LE_PSM_UUID) { @@ -874,8 +874,8 @@ class HearingAidImpl : public HearingAid { void ReadPSM(HearingDevice* hearingDevice) { if (hearingDevice->read_psm_handle) { - log::info("Reading PSM {}, device={}", - loghex(hearingDevice->read_psm_handle), hearingDevice->address); + log::info("Reading PSM 0x{:x}, device={}", hearingDevice->read_psm_handle, + hearingDevice->address); BtaGattQueue::ReadCharacteristic( hearingDevice->conn_id, hearingDevice->read_psm_handle, HearingAidImpl::OnPsmReadStatic, nullptr); @@ -886,13 +886,13 @@ class HearingAidImpl : public HearingAid { uint8_t* value) { HearingDevice* device = hearingDevices.FindByConnId(conn_id); if (!device) { - log::info("Skipping unknown device, conn_id={}", loghex(conn_id)); + log::info("Skipping unknown device, conn_id=0x{:x}", conn_id); return; } if (device->audio_status_handle != handle) { - log::info("Mismatched handle, {}!={}", - loghex(device->audio_status_handle), loghex(handle)); + log::info("Mismatched handle, 0x{:x}!=0x{:x}", + device->audio_status_handle, handle); return; } @@ -902,7 +902,7 @@ class HearingAidImpl : public HearingAid { } if (value[0] != 0) { - log::info("Invalid returned status. data={}", loghex(value[0])); + log::info("Invalid returned status. data=0x{:x}", value[0]); return; } @@ -916,7 +916,7 @@ class HearingAidImpl : public HearingAid { void* data) { HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id); if (!hearingDevice) { - log::debug("unknown conn_id={}", loghex(conn_id)); + log::debug("unknown conn_id=0x{:x}", conn_id); return; } @@ -928,13 +928,13 @@ class HearingAidImpl : public HearingAid { STREAM_TO_UINT8(version, p); if (version != 0x01) { - log::warn("Unknown version: {}", loghex(version)); + log::warn("Unknown version: 0x{:x}", version); return; } // version 0x01 of read only properties: if (len < 17) { - log::warn("Read only properties too short: {}", loghex(len)); + log::warn("Read only properties too short: 0x{:x}", len); return; } uint8_t capabilities; @@ -943,30 +943,29 @@ class HearingAidImpl : public HearingAid { bool side = capabilities & CAPABILITY_SIDE; bool standalone = capabilities & CAPABILITY_BINAURAL; bool csis_capable = capabilities & CAPABILITY_CSIS; - log::debug("capabilities: {}, {}, CSIS {}", (side ? "right" : "left"), - (standalone ? "binaural" : "monaural"), - (csis_capable ? "capable" : "not capable")); + log::debug("capabilities: {}, {}, CSIS {}", side ? "right" : "left", + standalone ? "binaural" : "monaural", + csis_capable ? "capable" : "not capable"); if (capabilities & CAPABILITY_RESERVED) { log::warn("reserved capabilities are set"); } STREAM_TO_UINT64(hearingDevice->hi_sync_id, p); - log::debug("hiSyncId: {}", loghex(hearingDevice->hi_sync_id)); + log::debug("hiSyncId: 0x{:x}", hearingDevice->hi_sync_id); uint8_t feature_map; STREAM_TO_UINT8(feature_map, p); STREAM_TO_UINT16(hearingDevice->render_delay, p); - log::debug("render delay: {}", loghex(hearingDevice->render_delay)); + log::debug("render delay: 0x{:x}", hearingDevice->render_delay); STREAM_TO_UINT16(hearingDevice->preparation_delay, p); - log::debug("preparation delay: {}", - loghex(hearingDevice->preparation_delay)); + log::debug("preparation delay: 0x{:x}", hearingDevice->preparation_delay); uint16_t codecs; STREAM_TO_UINT16(codecs, p); hearingDevice->codecs = codecs; - log::debug("supported codecs: {}", loghex(codecs)); + log::debug("supported codecs: 0x{:x}", codecs); if (codecs & (1 << CODEC_G722_16KHZ)) log::info("\tG722@16kHz"); if (codecs & (1 << CODEC_G722_24KHZ)) log::info("\tG722@24kHz"); @@ -1027,7 +1026,7 @@ class HearingAidImpl : public HearingAid { uint16_t len, uint8_t* value, void* data) { HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id); if (!hearingDevice) { - log::debug("Skipping unknown read event, conn_id={}", loghex(conn_id)); + log::debug("Skipping unknown read event, conn_id=0x{:x}", conn_id); return; } @@ -1042,7 +1041,7 @@ class HearingAidImpl : public HearingAid { } uint16_t psm = *((uint16_t*)value); - log::debug("read psm:{}", loghex(psm)); + log::debug("read psm:0x{:x}", psm); if (hearingDevice->gap_handle == GAP_INVALID_HANDLE && BTM_IsEncrypted(hearingDevice->address, BT_TRANSPORT_LE)) { @@ -1107,17 +1106,17 @@ class HearingAidImpl : public HearingAid { hearingDevice->first_connection = false; } - log::info("audio_status_handle={}, audio_status_ccc_handle={}", - loghex(hearingDevice->audio_status_handle), - loghex(hearingDevice->audio_status_ccc_handle)); + log::info("audio_status_handle=0x{:x}, audio_status_ccc_handle=0x{:x}", + hearingDevice->audio_status_handle, + hearingDevice->audio_status_ccc_handle); /* Register and enable the Audio Status Notification */ tGATT_STATUS register_status; register_status = BTA_GATTC_RegisterForNotifications( gatt_if, address, hearingDevice->audio_status_handle); if (register_status != GATT_SUCCESS) { - log::error("BTA_GATTC_RegisterForNotifications failed, status={}", - loghex(static_cast<uint8_t>(register_status))); + log::error("BTA_GATTC_RegisterForNotifications failed, status=0x{:x}", + static_cast<uint8_t>(register_status)); return; } std::vector<uint8_t> value(2); @@ -1140,9 +1139,9 @@ class HearingAidImpl : public HearingAid { hearingDevice->connecting_actively = false; hearingDevice->accepting_audio = true; - log::info("address={}, hi_sync_id={}, codec_in_use={}, audio_running={}", - address, loghex(hearingDevice->hi_sync_id), loghex(codec_in_use), - audio_running); + log::info( + "address={}, hi_sync_id=0x{:x}, codec_in_use=0x{:x}, audio_running={}", + address, hearingDevice->hi_sync_id, codec_in_use, audio_running); StartSendingAudio(*hearingDevice); @@ -1291,10 +1290,9 @@ class HearingAidImpl : public HearingAid { } else { start[4] = GetOtherSideStreamStatus(device); log::info( - "send Start cmd, volume={}, audio type={}, device={}, other side " - "streaming={}", - loghex(start[3]), loghex(start[2]), device->address, - loghex(start[4])); + "send Start cmd, volume=0x{:x}, audio type=0x{:x}, device={}, other " + "side streaming=0x{:x}", + start[3], start[2], device->address, start[4]); device->command_acked = false; BtaGattQueue::WriteCharacteristic( device->conn_id, device->audio_control_point_handle, start, @@ -1307,8 +1305,8 @@ class HearingAidImpl : public HearingAid { uint16_t len, const uint8_t* value, void* data) { if (status != GATT_SUCCESS) { - log::error("handle={}, conn_id={}, status={}", handle, conn_id, - loghex(static_cast<uint8_t>(status))); + log::error("handle={}, conn_id={}, status=0x{:x}", handle, conn_id, + static_cast<uint8_t>(status)); return; } if (!instance) { @@ -1321,7 +1319,7 @@ class HearingAidImpl : public HearingAid { void StartAudioCtrlCallback(uint16_t conn_id) { HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id); if (!hearingDevice) { - log::error("Skipping unknown device, conn_id={}", loghex(conn_id)); + log::error("Skipping unknown device, conn_id=0x{:x}", conn_id); return; } log::info("device: {}", hearingDevice->address); @@ -1571,12 +1569,12 @@ class HearingAidImpl : public HearingAid { p++; memcpy(p, encoded_data, packet_size); - log::debug("{} : {}", hearingAid->address, base::HexEncode(p, packet_size)); + log::debug("{} : packet_size={}", hearingAid->address, packet_size); uint16_t result = GAP_ConnWriteData(hearingAid->gap_handle, audio_packet); if (result != BT_PASS) { - log::error("Error sending data: {}", loghex(result)); + log::error("Error sending data: 0x{:x}", result); } } @@ -1801,11 +1799,10 @@ class HearingAidImpl : public HearingAid { RawAddress remote_bda) { HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id); if (!hearingDevice) { - log::debug("Skipping unknown device disconnect, conn_id={}", - loghex(conn_id)); + log::debug("Skipping unknown device disconnect, conn_id=0x{:x}", conn_id); return; } - log::debug("conn_id={}, remote_bda={}", loghex(conn_id), remote_bda); + log::debug("conn_id=0x{:x}, remote_bda={}", conn_id, remote_bda); // Inform the other side (if any) of this disconnection std::vector<uint8_t> inform_disconn_state( @@ -1931,7 +1928,7 @@ class HearingAidImpl : public HearingAid { const gatt::Service* service) { HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id); if (!hearingDevice) { - log::debug("Skipping unknown device, conn_id={}", loghex(conn_id)); + log::debug("Skipping unknown device, conn_id=0x{:x}", conn_id); return; } for (const gatt::Characteristic& charac : service->characteristics) { @@ -1942,8 +1939,8 @@ class HearingAidImpl : public HearingAid { log::error("cannot find service changed CCC descriptor"); continue; } - log::info("service_changed_ccc={}", - loghex(hearingDevice->service_changed_ccc_handle)); + log::info("service_changed_ccc=0x{:x}", + hearingDevice->service_changed_ccc_handle); break; } } @@ -1976,8 +1973,8 @@ class HearingAidImpl : public HearingAid { return; } // Send the data packet - log::info("Send State Change. device={}, status={}", device->address, - loghex(payload[1])); + log::info("Send State Change. device={}, status=0x{:x}", device->address, + payload[1]); BtaGattQueue::WriteCharacteristic( device->conn_id, device->audio_control_point_handle, payload, GATT_WRITE_NO_RSP, nullptr, nullptr); diff --git a/system/bta/include/bta_api.h b/system/bta/include/bta_api.h index 48096adddc..79d7dc84c9 100644 --- a/system/bta/include/bta_api.h +++ b/system/bta/include/bta_api.h @@ -283,24 +283,26 @@ typedef union { /* Search callback */ typedef void(tBTA_DM_SEARCH_CBACK)(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH* p_data); + +// TODO: delete bd_name parameter after separate_service_and_device_discovery +// rolls out typedef void(tBTA_DM_GATT_DISC_CBACK)(RawAddress bd_addr, BD_NAME bd_name, std::vector<bluetooth::Uuid>& services, bool transport_le); typedef void(tBTA_DM_DID_RES_CBACK)(RawAddress bd_addr, uint8_t vendor_id_src, uint16_t vendor_id, uint16_t product_id, uint16_t version); - +// TODO: delete after separate_service_and_device_discovery rolls out typedef void(tBTA_DM_NAME_READ_CBACK)(RawAddress bd_addr, tHCI_ERROR_CODE hci_status, const BD_NAME bd_name); typedef void(tBTA_DM_DISC_CBACK)(RawAddress bd_addr, tBTA_SERVICE_MASK services, - tBT_DEVICE_TYPE device_type, const std::vector<bluetooth::Uuid>& uuids, tBTA_STATUS result, tHCI_STATUS hci_status); struct service_discovery_callbacks { - /* legacy callback I'll tear apart and get rid of */ tBTA_DM_GATT_DISC_CBACK* on_gatt_results; tBTA_DM_DID_RES_CBACK* on_did_received; + // TODO: delete after separate_service_and_device_discovery rolls out tBTA_DM_NAME_READ_CBACK* on_name_read; tBTA_DM_DISC_CBACK* on_service_discovery_results; }; diff --git a/system/bta/include/bta_jv_api.h b/system/bta/include/bta_jv_api.h index 9c6ec12b02..8becb7bcc6 100644 --- a/system/bta/include/bta_jv_api.h +++ b/system/bta/include/bta_jv_api.h @@ -106,20 +106,6 @@ typedef uint8_t tBTA_JV_L2CAP_REASON; enum { BTA_JV_DISC_NONE, BTA_JV_DISC_LIMITED, BTA_JV_DISC_GENERAL }; typedef uint16_t tBTA_JV_DISC; -typedef uint32_t tBTA_JV_ROLE; - -#define BTA_JV_SERVICE_LMTD_DISCOVER \ - BTM_COD_SERVICE_LMTD_DISCOVER /* 0x0020 \ - */ -#define BTA_JV_SERVICE_POSITIONING BTM_COD_SERVICE_POSITIONING /* 0x0100 */ -#define BTA_JV_SERVICE_NETWORKING BTM_COD_SERVICE_NETWORKING /* 0x0200 */ -#define BTA_JV_SERVICE_RENDERING BTM_COD_SERVICE_RENDERING /* 0x0400 */ -#define BTA_JV_SERVICE_CAPTURING BTM_COD_SERVICE_CAPTURING /* 0x0800 */ -#define BTA_JV_SERVICE_OBJ_TRANSFER BTM_COD_SERVICE_OBJ_TRANSFER /* 0x1000 */ -#define BTA_JV_SERVICE_AUDIO BTM_COD_SERVICE_AUDIO /* 0x2000 */ -#define BTA_JV_SERVICE_TELEPHONY BTM_COD_SERVICE_TELEPHONY /* 0x4000 */ -#define BTA_JV_SERVICE_INFORMATION BTM_COD_SERVICE_INFORMATION /* 0x8000 */ - /* JV ID type */ #define BTA_JV_PM_ID_1 1 /* PM example profile 1 */ #define BTA_JV_PM_ID_2 2 /* PM example profile 2 */ @@ -171,10 +157,27 @@ struct formatter<tBTA_JV_CONN_STATE> : enum_formatter<tBTA_JV_CONN_STATE> {}; } // namespace fmt /* JV Connection types */ -#define BTA_JV_CONN_TYPE_RFCOMM 0 -#define BTA_JV_CONN_TYPE_L2CAP 1 -#define BTA_JV_CONN_TYPE_L2CAP_LE 2 -typedef int tBTA_JV_CONN_TYPE; +enum class tBTA_JV_CONN_TYPE { + UNKNOWN = -1, + RFCOMM = 0, + L2CAP = 1, + L2CAP_LE = 2, +}; + +inline std::string bta_jv_conn_type_text(const tBTA_JV_CONN_TYPE& type) { + switch (type) { + CASE_RETURN_STRING(tBTA_JV_CONN_TYPE::UNKNOWN); + CASE_RETURN_STRING(tBTA_JV_CONN_TYPE::RFCOMM); + CASE_RETURN_STRING(tBTA_JV_CONN_TYPE::L2CAP); + CASE_RETURN_STRING(tBTA_JV_CONN_TYPE::L2CAP_LE); + } + RETURN_UNKNOWN_TYPE_STRING(tBTA_JV_CONN_TYPE, type); +} + +namespace fmt { +template <> +struct formatter<tBTA_JV_CONN_TYPE> : enum_formatter<tBTA_JV_CONN_TYPE> {}; +} // namespace fmt enum tBTA_JV_EVT : uint16_t { /* Java I/F callback events */ @@ -558,7 +561,6 @@ tBTA_JV_STATUS BTA_JvDeleteRecord(uint32_t handle); * ******************************************************************************/ void BTA_JvL2capConnect(tBTA_JV_CONN_TYPE conn_type, tBTA_SEC sec_mask, - tBTA_JV_ROLE role, std::unique_ptr<tL2CAP_ERTM_INFO> ertm_info, uint16_t remote_psm, uint16_t rx_mtu, std::unique_ptr<tL2CAP_CFG_INFO> cfg, @@ -592,7 +594,6 @@ tBTA_JV_STATUS BTA_JvL2capClose(uint32_t handle); * ******************************************************************************/ void BTA_JvL2capStartServer(tBTA_JV_CONN_TYPE conn_type, tBTA_SEC sec_mask, - tBTA_JV_ROLE role, std::unique_ptr<tL2CAP_ERTM_INFO> ertm_info, uint16_t local_psm, uint16_t rx_mtu, std::unique_ptr<tL2CAP_CFG_INFO> cfg, @@ -673,8 +674,7 @@ tBTA_JV_STATUS BTA_JvL2capWrite(uint32_t handle, uint32_t req_id, BT_HDR* msg, * BTA_JV_FAILURE, otherwise. * ******************************************************************************/ -tBTA_JV_STATUS BTA_JvRfcommConnect(tBTA_SEC sec_mask, tBTA_JV_ROLE role, - uint8_t remote_scn, +tBTA_JV_STATUS BTA_JvRfcommConnect(tBTA_SEC sec_mask, uint8_t remote_scn, const RawAddress& peer_bd_addr, tBTA_JV_RFCOMM_CBACK* p_cback, uint32_t rfcomm_slot_id); @@ -706,8 +706,8 @@ tBTA_JV_STATUS BTA_JvRfcommClose(uint32_t handle, uint32_t rfcomm_slot_id); * BTA_JV_FAILURE, otherwise. * ******************************************************************************/ -tBTA_JV_STATUS BTA_JvRfcommStartServer(tBTA_SEC sec_mask, tBTA_JV_ROLE role, - uint8_t local_scn, uint8_t max_session, +tBTA_JV_STATUS BTA_JvRfcommStartServer(tBTA_SEC sec_mask, uint8_t local_scn, + uint8_t max_session, tBTA_JV_RFCOMM_CBACK* p_cback, uint32_t rfcomm_slot_id); diff --git a/system/bta/jv/bta_jv_act.cc b/system/bta/jv/bta_jv_act.cc index 3c5ee09d90..a25138e391 100644 --- a/system/bta/jv/bta_jv_act.cc +++ b/system/bta/jv/bta_jv_act.cc @@ -228,8 +228,7 @@ tBTA_JV_RFC_CB* bta_jv_alloc_rfc_cb(uint16_t port_handle, p_cb->curr_sess = 1; for (j = 0; j < BTA_JV_MAX_RFC_SR_SESSION; j++) p_cb->rfc_hdl[j] = 0; p_cb->rfc_hdl[0] = port_handle; - log::verbose("port_handle={}, handle={}", port_handle, - loghex(p_cb->handle)); + log::verbose("port_handle={}, handle=0x{:x}", port_handle, p_cb->handle); p_pcb = &bta_jv_cb.port_cb[port_handle - 1]; p_pcb->handle = p_cb->handle; @@ -304,9 +303,10 @@ static tBTA_JV_STATUS bta_jv_free_rfc_cb(tBTA_JV_RFC_CB* p_cb, return tBTA_JV_STATUS::FAILURE; } log::verbose( - "max_sess={}, curr_sess={}, p_pcb={}, user={}, state={}, jv handle={}", + "max_sess={}, curr_sess={}, p_pcb={}, user={}, state={}, jv " + "handle=0x{:x}", p_cb->max_sess, p_cb->curr_sess, fmt::ptr(p_pcb), p_pcb->rfcomm_slot_id, - p_pcb->state, loghex(p_pcb->handle)); + p_pcb->state, p_pcb->handle); if (p_cb->curr_sess <= 0) return tBTA_JV_STATUS::SUCCESS; @@ -337,9 +337,9 @@ static tBTA_JV_STATUS bta_jv_free_rfc_cb(tBTA_JV_RFC_CB* p_cb, break; default: log::warn( - "failed, ignore port state= {}, scn={}, p_pcb= {}, jv handle={}, " + "failed, ignore port state= {}, scn={}, p_pcb= {}, jv handle=0x{:x}, " "port_handle={}, user_data={}", - p_pcb->state, p_cb->scn, fmt::ptr(p_pcb), loghex(p_pcb->handle), + p_pcb->state, p_cb->scn, fmt::ptr(p_pcb), p_pcb->handle, p_pcb->port_handle, p_pcb->rfcomm_slot_id); status = tBTA_JV_STATUS::FAILURE; break; @@ -354,9 +354,9 @@ static tBTA_JV_STATUS bta_jv_free_rfc_cb(tBTA_JV_RFC_CB* p_cb, if (port_status != PORT_SUCCESS) { status = tBTA_JV_STATUS::FAILURE; log::warn( - "Remove jv handle={}, state={}, port_status={}, port_handle={}, " + "Remove jv handle=0x{:x}, state={}, port_status={}, port_handle={}, " "close_pending={}", - loghex(p_pcb->handle), p_pcb->state, port_status, p_pcb->port_handle, + p_pcb->handle, p_pcb->state, port_status, p_pcb->port_handle, close_pending); } } @@ -462,9 +462,8 @@ static tBTA_JV_STATUS bta_jv_free_set_pm_profile_cb(uint32_t jv_handle) { } log::verbose( - "jv_handle={}, idx={}app_id={}, bd_counter={}, appid_counter={}", - loghex(jv_handle), i, bta_jv_cb.pm_cb[i].app_id, bd_counter, - appid_counter); + "jv_handle=0x{:x}, idx={}app_id={}, bd_counter={}, appid_counter={}", + jv_handle, i, bta_jv_cb.pm_cb[i].app_id, bd_counter, appid_counter); if (bd_counter > 1) { bta_jv_pm_conn_idle(&bta_jv_cb.pm_cb[i]); } @@ -486,8 +485,9 @@ static tBTA_JV_STATUS bta_jv_free_set_pm_profile_cb(uint32_t jv_handle) { bta_jv_rfc_port_to_pcb(bta_jv_cb.rfc_cb[hi].rfc_hdl[si]); if (p_pcb) { if (NULL == p_pcb->p_pm_cb) - log::warn("jv_handle={}, port_handle={}, i={}, no link to pm_cb?", - loghex(jv_handle), p_pcb->port_handle, i); + log::warn( + "jv_handle=0x{:x}, port_handle={}, i={}, no link to pm_cb?", + jv_handle, p_pcb->port_handle, i); p_cb = &p_pcb->p_pm_cb; } } @@ -495,8 +495,7 @@ static tBTA_JV_STATUS bta_jv_free_set_pm_profile_cb(uint32_t jv_handle) { if (jv_handle < BTA_JV_MAX_L2C_CONN) { tBTA_JV_L2C_CB* p_l2c_cb = &bta_jv_cb.l2c_cb[jv_handle]; if (NULL == p_l2c_cb->p_pm_cb) - log::warn("jv_handle={}, i={} no link to pm_cb?", loghex(jv_handle), - i); + log::warn("jv_handle=0x{:x}, i={} no link to pm_cb?", jv_handle, i); p_cb = &p_l2c_cb->p_pm_cb; } } @@ -557,8 +556,8 @@ static tBTA_JV_PM_CB* bta_jv_alloc_set_pm_profile_cb(uint32_t jv_handle, } } log::verbose( - "handle={}, app_id={}, idx={}, BTA_JV_PM_MAX_NUM={}, pp_cb={}", - loghex(jv_handle), app_id, i, BTA_JV_PM_MAX_NUM, fmt::ptr(pp_cb)); + "handle=0x{:x}, app_id={}, idx={}, BTA_JV_PM_MAX_NUM={}, pp_cb={}", + jv_handle, app_id, i, BTA_JV_PM_MAX_NUM, fmt::ptr(pp_cb)); break; } } @@ -571,7 +570,7 @@ static tBTA_JV_PM_CB* bta_jv_alloc_set_pm_profile_cb(uint32_t jv_handle, bta_jv_cb.pm_cb[i].state = BTA_JV_PM_IDLE_ST; return &bta_jv_cb.pm_cb[i]; } - log::warn("handle={}, app_id={}, return NULL", loghex(jv_handle), app_id); + log::warn("handle=0x{:x}, app_id={}, return NULL", jv_handle, app_id); return NULL; } @@ -660,7 +659,7 @@ static uint16_t bta_jv_get_free_psm() { for (int i = 0; i < cnt; i++) { uint16_t psm = bta_jv_cb.free_psm_list[i]; if (psm != 0) { - log::verbose("Reusing PSM={}", loghex(psm)); + log::verbose("Reusing PSM=0x{:x}", psm); bta_jv_cb.free_psm_list[i] = 0; return psm; } @@ -681,9 +680,9 @@ static void bta_jv_set_free_psm(uint16_t psm) { } if (free_index != -1) { bta_jv_cb.free_psm_list[free_index] = psm; - log::verbose("Recycling PSM={}", loghex(psm)); + log::verbose("Recycling PSM=0x{:x}", psm); } else { - log::error("unable to free psm={} no more free slots", loghex(psm)); + log::error("unable to free psm=0x{:x} no more free slots", psm); } } @@ -720,7 +719,7 @@ void bta_jv_get_channel_id( uint16_t psm = 0; switch (type) { - case BTA_JV_CONN_TYPE_RFCOMM: { + case tBTA_JV_CONN_TYPE::RFCOMM: { uint8_t scn = 0; if (channel > 0) { if (BTA_TryAllocateSCN(channel)) { @@ -741,14 +740,14 @@ void bta_jv_get_channel_id( } return; } - case BTA_JV_CONN_TYPE_L2CAP: + case tBTA_JV_CONN_TYPE::L2CAP: psm = bta_jv_get_free_psm(); if (psm == 0) { psm = bta_jv_allocate_l2cap_classic_psm(); - log::verbose("returned PSM={}", loghex(psm)); + log::verbose("returned PSM=0x{:x}", psm); } break; - case BTA_JV_CONN_TYPE_L2CAP_LE: + case tBTA_JV_CONN_TYPE::L2CAP_LE: psm = L2CA_AllocateLePSM(); if (psm == 0) { log::error("Error: No free LE PSM available"); @@ -769,14 +768,14 @@ void bta_jv_get_channel_id( void bta_jv_free_scn(tBTA_JV_CONN_TYPE type /* One of BTA_JV_CONN_TYPE_ */, uint16_t scn) { switch (type) { - case BTA_JV_CONN_TYPE_RFCOMM: + case tBTA_JV_CONN_TYPE::RFCOMM: BTA_FreeSCN(scn); break; - case BTA_JV_CONN_TYPE_L2CAP: + case tBTA_JV_CONN_TYPE::L2CAP: bta_jv_set_free_psm(scn); break; - case BTA_JV_CONN_TYPE_L2CAP_LE: - log::verbose("type=BTA_JV_CONN_TYPE_L2CAP_LE. psm={}", scn); + case tBTA_JV_CONN_TYPE::L2CAP_LE: + log::verbose("type=BTA_JV_CONN_TYPE::L2CAP_LE. psm={}", scn); L2CA_FreeLePSM(scn); break; default: @@ -972,7 +971,7 @@ static void bta_jv_l2cap_client_cback(uint16_t gap_handle, uint16_t event, if (gap_handle >= BTA_JV_MAX_L2C_CONN && !p_cb->p_cback) return; - log::verbose("gap_handle={}, evt={}", gap_handle, loghex(event)); + log::verbose("gap_handle={}, evt=0x{:x}", gap_handle, event); evt_data.l2c_open.status = tBTA_JV_STATUS::SUCCESS; evt_data.l2c_open.handle = gap_handle; @@ -1026,8 +1025,8 @@ static void bta_jv_l2cap_client_cback(uint16_t gap_handle, uint16_t event, /* makes an l2cap client connection */ void bta_jv_l2cap_connect(tBTA_JV_CONN_TYPE type, tBTA_SEC sec_mask, - tBTA_JV_ROLE /* role */, uint16_t remote_psm, - uint16_t rx_mtu, const RawAddress& peer_bd_addr, + uint16_t remote_psm, uint16_t rx_mtu, + const RawAddress& peer_bd_addr, std::unique_ptr<tL2CAP_CFG_INFO> cfg_param, std::unique_ptr<tL2CAP_ERTM_INFO> ertm_info, tBTA_JV_L2CAP_CBACK* p_cback, @@ -1052,7 +1051,7 @@ void bta_jv_l2cap_connect(tBTA_JV_CONN_TYPE type, tBTA_SEC sec_mask, if (sec_id) { /* PSM checking is not required for LE COC */ - if ((type != BTA_JV_CONN_TYPE_L2CAP) || + if ((type != tBTA_JV_CONN_TYPE::L2CAP) || (bta_jv_check_psm(remote_psm))) /* allowed */ { // Given a client socket type @@ -1060,15 +1059,15 @@ void bta_jv_l2cap_connect(tBTA_JV_CONN_TYPE type, tBTA_SEC sec_mask, const tBT_TRANSPORT transport = [](tBTA_JV_CONN_TYPE type) -> tBT_TRANSPORT { switch (type) { - case BTA_JV_CONN_TYPE_L2CAP: + case tBTA_JV_CONN_TYPE::L2CAP: return BT_TRANSPORT_BR_EDR; - case BTA_JV_CONN_TYPE_L2CAP_LE: + case tBTA_JV_CONN_TYPE::L2CAP_LE: return BT_TRANSPORT_LE; - case BTA_JV_CONN_TYPE_RFCOMM: + case tBTA_JV_CONN_TYPE::RFCOMM: default: break; } - log::warn("Unexpected socket type:{}", type); + log::warn("Unexpected socket type:{}", bta_jv_conn_type_text(type)); return BT_TRANSPORT_AUTO; }(type); @@ -1138,7 +1137,7 @@ static void bta_jv_l2cap_server_cback(uint16_t gap_handle, uint16_t event, if (gap_handle >= BTA_JV_MAX_L2C_CONN && !p_cb->p_cback) return; - log::verbose("gap_handle={}, evt={}", gap_handle, loghex(event)); + log::verbose("gap_handle={}, evt=0x{:x}", gap_handle, event); evt_data.l2c_open.status = tBTA_JV_STATUS::SUCCESS; evt_data.l2c_open.handle = gap_handle; @@ -1190,8 +1189,7 @@ static void bta_jv_l2cap_server_cback(uint16_t gap_handle, uint16_t event, /** starts an L2CAP server */ void bta_jv_l2cap_start_server(tBTA_JV_CONN_TYPE type, tBTA_SEC sec_mask, - tBTA_JV_ROLE /* role */, uint16_t local_psm, - uint16_t rx_mtu, + uint16_t local_psm, uint16_t rx_mtu, std::unique_ptr<tL2CAP_CFG_INFO> cfg_param, std::unique_ptr<tL2CAP_ERTM_INFO> ertm_info, tBTA_JV_L2CAP_CBACK* p_cback, @@ -1222,20 +1220,20 @@ void bta_jv_l2cap_start_server(tBTA_JV_CONN_TYPE type, tBTA_SEC sec_mask, // return the associated transport const tBT_TRANSPORT transport = [](tBTA_JV_CONN_TYPE type) -> tBT_TRANSPORT { switch (type) { - case BTA_JV_CONN_TYPE_L2CAP: + case tBTA_JV_CONN_TYPE::L2CAP: return BT_TRANSPORT_BR_EDR; - case BTA_JV_CONN_TYPE_L2CAP_LE: + case tBTA_JV_CONN_TYPE::L2CAP_LE: return BT_TRANSPORT_LE; - case BTA_JV_CONN_TYPE_RFCOMM: + case tBTA_JV_CONN_TYPE::RFCOMM: default: break; } - log::warn("Unexpected socket type:{}", type); + log::warn("Unexpected socket type:{}", bta_jv_conn_type_text(type)); return BT_TRANSPORT_AUTO; }(type); if (0 == sec_id || - ((type == BTA_JV_CONN_TYPE_L2CAP) && (!bta_jv_check_psm(local_psm))) || + ((type == tBTA_JV_CONN_TYPE::L2CAP) && (!bta_jv_check_psm(local_psm))) || (handle = GAP_ConnOpen("JV L2CAP", sec_id, 1, nullptr, local_psm, max_mps, &cfg, ertm_info.get(), sec_mask, bta_jv_l2cap_server_cback, transport)) == @@ -1436,7 +1434,7 @@ static void bta_jv_port_event_cl_cback(uint32_t code, uint16_t port_handle) { log::verbose("port_handle={}", port_handle); if (NULL == p_cb || NULL == p_cb->p_cback) return; - log::verbose("code={}, port_handle={}, handle={}", loghex(code), port_handle, + log::verbose("code=0x{:x}, port_handle={}, handle={}", code, port_handle, p_cb->handle); if (code & PORT_EV_RXCHAR) { evt_data.data_ind.handle = p_cb->handle; @@ -1537,10 +1535,9 @@ static int find_rfc_pcb(uint32_t rfcomm_slot_id, tBTA_JV_RFC_CB** cb, *pcb = &bta_jv_cb.port_cb[i]; *cb = &bta_jv_cb.rfc_cb[rfc_handle - 1]; log::verbose( - "FOUND rfc_cb_handle={}, port.jv_handle={}, state={}, " - "rfc_cb->handle={}", - loghex(rfc_handle), loghex((*pcb)->handle), (*pcb)->state, - loghex((*cb)->handle)); + "FOUND rfc_cb_handle=0x{:x}, port.jv_handle=0x{:x}, state={}, " + "rfc_cb->handle=0x{:x}", + rfc_handle, (*pcb)->handle, (*pcb)->state, (*cb)->handle); return 1; } } @@ -1587,8 +1584,8 @@ static void bta_jv_port_mgmt_sr_cback(uint32_t code, uint16_t port_handle) { return; } uint32_t rfcomm_slot_id = p_pcb->rfcomm_slot_id; - log::verbose("code={}, port_handle={}, handle={}, p_pcb{}, user={}", code, - loghex(port_handle), loghex(p_cb->handle), fmt::ptr(p_pcb), + log::verbose("code={}, port_handle=0x{:x}, handle=0x{:x}, p_pcb{}, user={}", + code, port_handle, p_cb->handle, fmt::ptr(p_pcb), p_pcb->rfcomm_slot_id); int status = PORT_CheckConnection(port_handle, &rem_bda, &lcid); @@ -1663,7 +1660,7 @@ static void bta_jv_port_event_sr_cback(uint32_t code, uint16_t port_handle) { return; } - log::verbose("code={}, port_handle={}, handle={}", loghex(code), port_handle, + log::verbose("code=0x{:x}, port_handle={}, handle={}", code, port_handle, p_cb->handle); uint32_t user_data = p_pcb->rfcomm_slot_id; @@ -1756,7 +1753,7 @@ static tBTA_JV_PCB* bta_jv_add_rfc_port(tBTA_JV_RFC_CB* p_cb, PORT_SetState(p_pcb->port_handle, &port_state); p_pcb->handle = BTA_JV_RFC_H_S_TO_HDL(p_cb->handle, si); - log::verbose("p_pcb->handle={}, curr_sess={}", loghex(p_pcb->handle), + log::verbose("p_pcb->handle=0x{:x}, curr_sess={}", p_pcb->handle, p_cb->curr_sess); } else { log::error("RFCOMM_CreateConnection failed"); @@ -1888,8 +1885,8 @@ void bta_jv_set_pm_profile(uint32_t handle, tBTA_JV_PM_ID app_id, tBTA_JV_STATUS status; tBTA_JV_PM_CB* p_cb; - log::verbose("handle={}, app_id={}, init_st={}", loghex(handle), app_id, - init_st); + log::verbose("handle=0x{:x}, app_id={}, init_st={}", handle, app_id, + bta_jv_conn_state_text(init_st)); /* clear PM control block */ if (app_id == BTA_JV_PM_ID_CLEAR) { @@ -1955,8 +1952,9 @@ static void bta_jv_pm_conn_idle(tBTA_JV_PM_CB* p_cb) { static void bta_jv_pm_state_change(tBTA_JV_PM_CB* p_cb, const tBTA_JV_CONN_STATE state) { log::verbose( - "p_cb={}, handle={}, busy/idle_state={}, app_id={}, conn_state={}", - fmt::ptr(p_cb), loghex(p_cb->handle), p_cb->state, p_cb->app_id, state); + "p_cb={}, handle=0x{:x}, busy/idle_state={}, app_id={}, conn_state={}", + fmt::ptr(p_cb), p_cb->handle, p_cb->state, p_cb->app_id, + bta_jv_conn_state_text(state)); switch (state) { case BTA_JV_CONN_OPEN: @@ -1994,7 +1992,7 @@ static void bta_jv_pm_state_change(tBTA_JV_PM_CB* p_cb, break; default: - log::warn("Invalid state={}", state); + log::warn("Invalid state={}", bta_jv_conn_state_text(state)); break; } } diff --git a/system/bta/jv/bta_jv_api.cc b/system/bta/jv/bta_jv_api.cc index 3cf47a6540..c2ce066dab 100644 --- a/system/bta/jv/bta_jv_api.cc +++ b/system/bta/jv/bta_jv_api.cc @@ -116,13 +116,8 @@ void BTA_JvDisable(void) { ******************************************************************************/ void BTA_JvGetChannelId(tBTA_JV_CONN_TYPE conn_type, uint32_t id, int32_t channel) { - log::verbose("conn_type:{}, id:{}, channel:{}", conn_type, id, channel); - - if (conn_type != BTA_JV_CONN_TYPE_RFCOMM && - conn_type != BTA_JV_CONN_TYPE_L2CAP && - conn_type != BTA_JV_CONN_TYPE_L2CAP_LE) { - log::fatal("Invalid conn_type={}", conn_type); - } + log::verbose("conn_type:{}, id:{}, channel:{}", + bta_jv_conn_type_text(conn_type), id, channel); do_in_main_thread(FROM_HERE, Bind(&bta_jv_get_channel_id, conn_type, channel, id, id)); @@ -142,8 +137,10 @@ void BTA_JvGetChannelId(tBTA_JV_CONN_TYPE conn_type, uint32_t id, * tBTA_JV_STATUS::FAILURE, otherwise. * ******************************************************************************/ -tBTA_JV_STATUS BTA_JvFreeChannel(uint16_t channel, int conn_type) { - log::verbose("channel:{}, conn_type:{}", channel, conn_type); +tBTA_JV_STATUS BTA_JvFreeChannel(uint16_t channel, + tBTA_JV_CONN_TYPE conn_type) { + log::verbose("channel:{}, conn_type:{}", channel, + bta_jv_conn_type_text(conn_type)); do_in_main_thread(FROM_HERE, Bind(&bta_jv_free_scn, conn_type, channel)); return tBTA_JV_STATUS::SUCCESS; @@ -225,7 +222,7 @@ tBTA_JV_STATUS BTA_JvDeleteRecord(uint32_t handle) { * tBTA_JV_L2CAP_CBACK is called with BTA_JV_L2CAP_OPEN_EVT * ******************************************************************************/ -void BTA_JvL2capConnect(int conn_type, tBTA_SEC sec_mask, tBTA_JV_ROLE role, +void BTA_JvL2capConnect(tBTA_JV_CONN_TYPE conn_type, tBTA_SEC sec_mask, std::unique_ptr<tL2CAP_ERTM_INFO> ertm_info, uint16_t remote_psm, uint16_t rx_mtu, std::unique_ptr<tL2CAP_CFG_INFO> cfg, @@ -233,14 +230,15 @@ void BTA_JvL2capConnect(int conn_type, tBTA_SEC sec_mask, tBTA_JV_ROLE role, tBTA_JV_L2CAP_CBACK* p_cback, uint32_t l2cap_socket_id) { log::verbose( - "conn_type:{}, role:{}, remote_psm:{}, peer_bd_addr:{}, " + "conn_type:{}, remote_psm:{}, peer_bd_addr:{}, " "l2cap_socket_id:{}", - conn_type, role, remote_psm, peer_bd_addr, l2cap_socket_id); + bta_jv_conn_type_text(conn_type), remote_psm, peer_bd_addr, + l2cap_socket_id); log::assert_that(p_cback != nullptr, "assert failed: p_cback != nullptr"); do_in_main_thread(FROM_HERE, - Bind(&bta_jv_l2cap_connect, conn_type, sec_mask, role, - remote_psm, rx_mtu, peer_bd_addr, base::Passed(&cfg), + Bind(&bta_jv_l2cap_connect, conn_type, sec_mask, remote_psm, + rx_mtu, peer_bd_addr, base::Passed(&cfg), base::Passed(&ertm_info), p_cback, l2cap_socket_id)); } @@ -280,18 +278,17 @@ tBTA_JV_STATUS BTA_JvL2capClose(uint32_t handle) { * ******************************************************************************/ void BTA_JvL2capStartServer(tBTA_JV_CONN_TYPE conn_type, tBTA_SEC sec_mask, - tBTA_JV_ROLE role, std::unique_ptr<tL2CAP_ERTM_INFO> ertm_info, uint16_t local_psm, uint16_t rx_mtu, std::unique_ptr<tL2CAP_CFG_INFO> cfg, tBTA_JV_L2CAP_CBACK* p_cback, uint32_t l2cap_socket_id) { - log::verbose("conn_type:{}, role:{}, local_psm:{}, l2cap_socket_id:{}", - conn_type, role, local_psm, l2cap_socket_id); - log::assert_that(p_cback != nullptr, "assert failed: p_cback != nullptr"); + log::verbose("conn_type:{}, local_psm:{}, l2cap_socket_id:{}", + bta_jv_conn_type_text(conn_type), local_psm, l2cap_socket_id); + CHECK(p_cback); do_in_main_thread(FROM_HERE, - Bind(&bta_jv_l2cap_start_server, conn_type, sec_mask, role, + Bind(&bta_jv_l2cap_start_server, conn_type, sec_mask, local_psm, rx_mtu, base::Passed(&cfg), base::Passed(&ertm_info), p_cback, l2cap_socket_id)); } @@ -423,8 +420,7 @@ tBTA_JV_STATUS BTA_JvL2capWrite(uint32_t handle, uint32_t req_id, BT_HDR* msg, * tBTA_JV_STATUS::FAILURE, otherwise. * ******************************************************************************/ -tBTA_JV_STATUS BTA_JvRfcommConnect(tBTA_SEC sec_mask, tBTA_JV_ROLE role, - uint8_t remote_scn, +tBTA_JV_STATUS BTA_JvRfcommConnect(tBTA_SEC sec_mask, uint8_t remote_scn, const RawAddress& peer_bd_addr, tBTA_JV_RFCOMM_CBACK* p_cback, uint32_t rfcomm_slot_id) { @@ -479,8 +475,8 @@ tBTA_JV_STATUS BTA_JvRfcommClose(uint32_t handle, uint32_t rfcomm_slot_id) { * tBTA_JV_STATUS::FAILURE, otherwise. * ******************************************************************************/ -tBTA_JV_STATUS BTA_JvRfcommStartServer(tBTA_SEC sec_mask, tBTA_JV_ROLE role, - uint8_t local_scn, uint8_t max_session, +tBTA_JV_STATUS BTA_JvRfcommStartServer(tBTA_SEC sec_mask, uint8_t local_scn, + uint8_t max_session, tBTA_JV_RFCOMM_CBACK* p_cback, uint32_t rfcomm_slot_id) { log::verbose("local_scn:{}, rfcomm_slot_id:{}", local_scn, rfcomm_slot_id); diff --git a/system/bta/jv/bta_jv_int.h b/system/bta/jv/bta_jv_int.h index 490e6027e0..ae8380ed18 100644 --- a/system/bta/jv/bta_jv_int.h +++ b/system/bta/jv/bta_jv_int.h @@ -154,16 +154,15 @@ void bta_jv_start_discovery(const RawAddress& bd_addr, uint16_t num_uuid, void bta_jv_create_record(uint32_t rfcomm_slot_id); void bta_jv_delete_record(uint32_t handle); void bta_jv_l2cap_connect(tBTA_JV_CONN_TYPE type, tBTA_SEC sec_mask, - tBTA_JV_ROLE role, uint16_t remote_psm, - uint16_t rx_mtu, const RawAddress& peer_bd_addr, + uint16_t remote_psm, uint16_t rx_mtu, + const RawAddress& peer_bd_addr, std::unique_ptr<tL2CAP_CFG_INFO> cfg, std::unique_ptr<tL2CAP_ERTM_INFO> ertm_info, tBTA_JV_L2CAP_CBACK* p_cback, uint32_t l2cap_socket_id); void bta_jv_l2cap_close(uint32_t handle, tBTA_JV_L2C_CB* p_cb); void bta_jv_l2cap_start_server(tBTA_JV_CONN_TYPE type, tBTA_SEC sec_mask, - tBTA_JV_ROLE role, uint16_t local_psm, - uint16_t rx_mtu, + uint16_t local_psm, uint16_t rx_mtu, std::unique_ptr<tL2CAP_CFG_INFO> cfg_param, std::unique_ptr<tL2CAP_ERTM_INFO> ertm_info, tBTA_JV_L2CAP_CBACK* p_cback, diff --git a/system/bta/le_audio/audio_hal_client/audio_sink_hal_client.cc b/system/bta/le_audio/audio_hal_client/audio_sink_hal_client.cc index 935e2e3e08..0ba5b1e379 100644 --- a/system/bta/le_audio/audio_hal_client/audio_sink_hal_client.cc +++ b/system/bta/le_audio/audio_hal_client/audio_sink_hal_client.cc @@ -106,6 +106,11 @@ void SinkImpl::Release() { log::info(""); if (halSourceInterface_) { + if (le_audio_source_hal_state == HAL_STARTED) { + halSourceInterface_->StopSession(); + le_audio_source_hal_state = HAL_STOPPED; + } + halSourceInterface_->Cleanup(); auto halInterface = audio::le_audio::LeAudioClientInterface::Get(); diff --git a/system/bta/le_audio/audio_hal_client/audio_source_hal_client.cc b/system/bta/le_audio/audio_hal_client/audio_source_hal_client.cc index e7a357b3df..720cc10db7 100644 --- a/system/bta/le_audio/audio_hal_client/audio_source_hal_client.cc +++ b/system/bta/le_audio/audio_hal_client/audio_source_hal_client.cc @@ -148,6 +148,11 @@ void SourceImpl::Release() { worker_thread_->ShutDown(); if (halSinkInterface_) { + if (le_audio_sink_hal_state_ == HAL_STARTED) { + halSinkInterface_->StopSession(); + le_audio_sink_hal_state_ = HAL_STOPPED; + } + halSinkInterface_->Cleanup(); auto halInterface = audio::le_audio::LeAudioClientInterface::Get(); diff --git a/system/bta/le_audio/audio_set_configurations.fbs b/system/bta/le_audio/audio_set_configurations.fbs index 251eaaeded..87ee8c3a9d 100644 --- a/system/bta/le_audio/audio_set_configurations.fbs +++ b/system/bta/le_audio/audio_set_configurations.fbs @@ -56,10 +56,9 @@ enum AudioSetConfigurationTargetLatency : byte { HIGH_RELIABILITY = 0x03, } table AudioSetSubConfiguration { - device_cnt: ubyte; + ase_channel_cnt: ubyte; ase_cnt: ubyte; direction: AudioSetConfigurationDirection = SINK; - configuration_strategy: AudioSetConfigurationStrategy; codec_id : CodecId (required); codec_configuration: [CodecSpecificConfiguration] (required); } diff --git a/system/bta/le_audio/audio_set_configurations.json b/system/bta/le_audio/audio_set_configurations.json index 05bf3e81b0..09708f32d6 100644 --- a/system/bta/le_audio/audio_set_configurations.json +++ b/system/bta/le_audio/audio_set_configurations.json @@ -13,16 +13,11 @@ " Codec Configuration parameter types:", " SUPPORTED_SAMPLING_FREQUENCY = 1", " SUPPORTED_FRAME_DURATION = 2", - " SUPPORTED_AUDIO_CHANNEL_ALLOCATION = 3", " SUPPORTED_OCTETS_PER_CODEC_FRAME = 4", " SUPPORTED_CODEC_FRAME_BLOCKS_PER_SDU = 5", " Example values which can be used as 'codec_configuration.compound_value'", " Codec Coding formats:", " LC3 = 6", - " ASE Configuration strategies:", - " MONO_ONE_CIS_PER_DEVICE = 0", - " STEREO_TWO_CISES_PER_DEVICE = 1", - " STEREO_ONE_CIS_PER_DEVICE = 2", " Sampling Frequencies: ", " 8000Hz = 1", " 11025Hz = 2", @@ -43,1139 +38,1400 @@ ], "configurations": [ { - "name": "DualDev_OneChanStereoSnk_16_1_Low_Latency", - "codec_config_name": "DualDev_OneChanStereoSnk_16_1", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-OneChan-SnkAse-Lc3_16_1_Low_Latency", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "DualDev_OneChanStereoSnk_16_1_Balanced_Reliability", - "codec_config_name": "DualDev_OneChanStereoSnk_16_1", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "Two-OneChan-SnkAse-Lc3_16_1_Balanced_Reliability", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "DualDev_OneChanStereoSnk_16_1_1", - "codec_config_name": "DualDev_OneChanStereoSnk_16_1", - "qos_config_name": ["QoS_Config_16_1_1"] + "name": "Two-OneChan-SnkAse-Lc3_16_1_1", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_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": "Two-OneChan-SnkAse-Lc3_16_1_2", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1", + "qos_config_name": [ + "QoS_Config_16_1_2" + ] }, { - "name": "DualDev_OneChanStereoSnk_16_2_Low_Latency", - "codec_config_name": "DualDev_OneChanStereoSnk_16_2", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-OneChan-SnkAse-Lc3_16_2_Low_Latency", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "DualDev_OneChanStereoSnk_16_2_Balanced_Reliability", - "codec_config_name": "DualDev_OneChanStereoSnk_16_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "Two-OneChan-SnkAse-Lc3_16_2_Balanced_Reliability", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "DualDev_OneChanStereoSnk_16_2_1", - "codec_config_name": "DualDev_OneChanStereoSnk_16_2", - "qos_config_name": ["QoS_Config_16_2_1"] + "name": "Two-OneChan-SnkAse-Lc3_16_2_1", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_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": "Two-OneChan-SnkAse-Lc3_16_2_2", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_16_2_2" + ] }, { - "name": "SingleDev_OneChanStereoSnk_16_1_Low_Latency", - "codec_config_name": "SingleDev_OneChanStereoSnk_16_1", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-OneChan-SnkAse-Lc3_16_1_Low_Latency", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_OneChanStereoSnk_16_1_Balanced_Reliability", - "codec_config_name": "SingleDev_OneChanStereoSnk_16_1", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "Two-OneChan-SnkAse-Lc3_16_1_Balanced_Reliability", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_OneChanStereoSnk_16_1_1", - "codec_config_name": "SingleDev_OneChanStereoSnk_16_1", - "qos_config_name": ["QoS_Config_16_1_1"] + "name": "Two-OneChan-SnkAse-Lc3_16_1_1", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_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": "Two-OneChan-SnkAse-Lc3_16_1_2", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1", + "qos_config_name": [ + "QoS_Config_16_1_2" + ] }, { - "name": "SingleDev_OneChanStereoSnk_16_2_Low_Latency", - "codec_config_name": "SingleDev_OneChanStereoSnk_16_2", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-OneChan-SnkAse-Lc3_16_2_Low_Latency", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_OneChanStereoSnk_16_2_Balanced_Reliability", - "codec_config_name": "SingleDev_OneChanStereoSnk_16_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "Two-OneChan-SnkAse-Lc3_16_2_Balanced_Reliability", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_OneChanStereoSnk_16_2_1", - "codec_config_name": "SingleDev_OneChanStereoSnk_16_2", - "qos_config_name": ["QoS_Config_16_2_1"] + "name": "Two-OneChan-SnkAse-Lc3_16_2_1", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_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": "Two-OneChan-SnkAse-Lc3_16_2_2", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_16_2_2" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_16_1_Low_Latency", - "codec_config_name": "SingleDev_TwoChanStereoSnk_16_1", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "One-TwoChan-SnkAse-Lc3_16_1_Low_Latency", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_1", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_16_1_Balanced_Reliability", - "codec_config_name": "SingleDev_TwoChanStereoSnk_16_1", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "One-TwoChan-SnkAse-Lc3_16_1_Balanced_Reliability", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_1", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_16_1_1", - "codec_config_name": "SingleDev_TwoChanStereoSnk_16_1", - "qos_config_name": ["QoS_Config_16_1_1"] + "name": "One-TwoChan-SnkAse-Lc3_16_1_1", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_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": "One-TwoChan-SnkAse-Lc3_16_1_2", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_1", + "qos_config_name": [ + "QoS_Config_16_1_2" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_16_2_Low_Latency", - "codec_config_name": "SingleDev_TwoChanStereoSnk_16_2", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "One-TwoChan-SnkAse-Lc3_16_2_Low_Latency", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_16_2_Balanced_Reliability", - "codec_config_name": "SingleDev_TwoChanStereoSnk_16_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "One-TwoChan-SnkAse-Lc3_16_2_Balanced_Reliability", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_16_2_1", - "codec_config_name": "SingleDev_TwoChanStereoSnk_16_2", - "qos_config_name": ["QoS_Config_16_2_1"] + "name": "One-TwoChan-SnkAse-Lc3_16_2_1", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_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": "One-TwoChan-SnkAse-Lc3_16_2_2", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_16_2_2" + ] }, { - "name": "SingleDev_OneChanMonoSnk_32_1_Balanced_Reliability", - "codec_config_name": "SingleDev_OneChanMonoSnk_32_1", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "One-OneChan-SnkAse-Lc3_32_1_Balanced_Reliability", + "codec_config_name": "One-OneChan-SnkAse-Lc3_32_1", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_OneChanMonoSnk_32_1_1", - "codec_config_name": "SingleDev_OneChanMonoSnk_32_1", - "qos_config_name": ["QoS_Config_32_1_1"] + "name": "One-OneChan-SnkAse-Lc3_32_1_1", + "codec_config_name": "One-OneChan-SnkAse-Lc3_32_1", + "qos_config_name": [ + "QoS_Config_32_1_1" + ] }, { - "name": "SingleDev_OneChanMonoSnk_32_1_2", - "codec_config_name": "SingleDev_OneChanMonoSnk_32_1", - "qos_config_name": ["QoS_Config_32_1_2"] + "name": "One-OneChan-SnkAse-Lc3_32_1_2", + "codec_config_name": "One-OneChan-SnkAse-Lc3_32_1", + "qos_config_name": [ + "QoS_Config_32_1_2" + ] }, { - "name": "SingleDev_OneChanMonoSnk_32_2_Balanced_Reliability", - "codec_config_name": "SingleDev_OneChanMonoSnk_32_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "One-OneChan-SnkAse-Lc3_32_2_Balanced_Reliability", + "codec_config_name": "One-OneChan-SnkAse-Lc3_32_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_OneChanMonoSnk_32_2_1", - "codec_config_name": "SingleDev_OneChanMonoSnk_32_2", - "qos_config_name": ["QoS_Config_32_2_1"] + "name": "One-OneChan-SnkAse-Lc3_32_2_1", + "codec_config_name": "One-OneChan-SnkAse-Lc3_32_2", + "qos_config_name": [ + "QoS_Config_32_2_1" + ] }, { - "name": "SingleDev_OneChanMonoSnk_32_2_2", - "codec_config_name": "SingleDev_OneChanMonoSnk_32_2", - "qos_config_name": ["QoS_Config_32_2_2"] + "name": "One-OneChan-SnkAse-Lc3_32_2_2", + "codec_config_name": "One-OneChan-SnkAse-Lc3_32_2", + "qos_config_name": [ + "QoS_Config_32_2_2" + ] }, { - "name": "SingleDev_OneChanMonoSnk_16_1_Balanced_Reliability", - "codec_config_name": "SingleDev_OneChanMonoSnk_16_1", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "One-OneChan-SnkAse-Lc3_16_1_Balanced_Reliability", + "codec_config_name": "One-OneChan-SnkAse-Lc3_16_1", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_OneChanMonoSnk_16_1_1", - "codec_config_name": "SingleDev_OneChanMonoSnk_16_1", - "qos_config_name": ["QoS_Config_16_1_1"] + "name": "One-OneChan-SnkAse-Lc3_16_1_1", + "codec_config_name": "One-OneChan-SnkAse-Lc3_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": "One-OneChan-SnkAse-Lc3_16_1_2", + "codec_config_name": "One-OneChan-SnkAse-Lc3_16_1", + "qos_config_name": [ + "QoS_Config_16_1_2" + ] }, { - "name": "DualDev_OneChanMonoSnk_16_2_Balanced_Reliability", - "codec_config_name": "DualDev_OneChanMonoSnk_16_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "Two-OneChan-SnkAse-Lc3_16_2_Balanced_Reliability", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_OneChanMonoSnk_16_2_Balanced_Reliability", - "codec_config_name": "SingleDev_OneChanMonoSnk_16_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "One-OneChan-SnkAse-Lc3_16_2_Balanced_Reliability", + "codec_config_name": "One-OneChan-SnkAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_OneChanMonoSnk_16_2_1", - "codec_config_name": "SingleDev_OneChanMonoSnk_16_2", - "qos_config_name": ["QoS_Config_16_2_1"] + "name": "One-OneChan-SnkAse-Lc3_16_2_1", + "codec_config_name": "One-OneChan-SnkAse-Lc3_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": "One-OneChan-SnkAse-Lc3_16_2_2", + "codec_config_name": "One-OneChan-SnkAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_16_2_2" + ] }, { - "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency", - "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1_1", - "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1", - "qos_config_name": ["QoS_Config_16_1_1"] + "name": "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_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": "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_2", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1", + "qos_config_name": [ + "QoS_Config_16_1_2" + ] }, { - "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_Low_Latency", - "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_Low_Latency", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_2", - "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2", - "qos_config_name": ["QoS_Config_16_2_2"] + "name": "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_2", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_16_2_2" + ] }, { - "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_1", - "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2", - "qos_config_name": ["QoS_Config_16_2_1"] + "name": "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_1", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_16_2_1" + ] }, { - "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_Low_Latency", - "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_Low_Latency", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_2", - "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1", - "qos_config_name": ["QoS_Config_16_1_2"] + "name": "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_2", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1", + "qos_config_name": [ + "QoS_Config_16_1_2" + ] }, { - "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_1", - "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1", - "qos_config_name": ["QoS_Config_16_1_1"] + "name": "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_1", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1", + "qos_config_name": [ + "QoS_Config_16_1_1" + ] }, { - "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency", - "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2_1", - "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2", - "qos_config_name": ["QoS_Config_16_2_1"] + "name": "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_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": "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_2", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_16_2_2" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_Low_Latency", - "codec_config_name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2_Low_Latency", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_1", - "codec_config_name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2", - "qos_config_name": ["QoS_Config_32_2_1"] + "name": "One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2_1", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2", + "qos_config_name": [ + "QoS_Config_32_2_1" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_Low_Latency", - "codec_config_name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_Low_Latency", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_2", - "codec_config_name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2", - "qos_config_name": ["QoS_Config_16_2_2"] + "name": "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_2", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_16_2_2" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_1", - "codec_config_name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2", - "qos_config_name": ["QoS_Config_16_2_1"] + "name": "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_1", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_16_2_1" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_Low_Latency", - "codec_config_name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_Low_Latency", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_2", - "codec_config_name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1", - "qos_config_name": ["QoS_Config_16_1_2"] + "name": "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_2", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1", + "qos_config_name": [ + "QoS_Config_16_1_2" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_1", - "codec_config_name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1", - "qos_config_name": ["QoS_Config_16_1_1"] + "name": "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_1", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1", + "qos_config_name": [ + "QoS_Config_16_1_1" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency", - "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_1", - "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1", - "qos_config_name": ["QoS_Config_16_1_1"] + "name": "One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_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": "One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_2", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1", + "qos_config_name": [ + "QoS_Config_16_1_2" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency", - "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_1", - "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2", - "qos_config_name": ["QoS_Config_16_2_1"] + "name": "One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_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": "One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_2", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_16_2_2" + ] }, { - "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency", - "codec_config_name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_1", - "codec_config_name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1", - "qos_config_name": ["QoS_Config_16_1_1"] + "name": "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_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": "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_2", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1", + "qos_config_name": [ + "QoS_Config_16_1_2" + ] }, { - "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency", - "codec_config_name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_1", - "codec_config_name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2", - "qos_config_name": ["QoS_Config_16_2_1"] + "name": "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_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": "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_2", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_16_2_2" + ] }, { - "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_Low_Latency", - "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency", + "codec_config_name": "One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_1", - "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1", - "qos_config_name": ["QoS_Config_16_1_1"] + "name": "One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1", + "codec_config_name": "One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1", + "qos_config_name": [ + "QoS_Config_16_1_1" + ] }, { - "name": "DualDev_OneChanMonoSrc_16_2_Balanced_Reliability", - "codec_config_name": "DualDev_OneChanMonoSrc_16_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "Two-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability", + "codec_config_name": "Two-OneChan-SrcAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_OneChanStereoSrc_16_2_Balanced_Reliability", - "codec_config_name": "SingleDev_OneChanStereoSrc_16_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "Two-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability", + "codec_config_name": "Two-OneChan-SrcAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_OneChanMonoSrc_48_4_Balanced_Reliability", - "codec_config_name": "SingleDev_OneChanMonoSrc_48_4", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "One-OneChan-SrcAse-Lc3_48_4_Balanced_Reliability", + "codec_config_name": "One-OneChan-SrcAse-Lc3_48_4", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_OneChanMonoSrc_48_3_Balanced_Reliability", - "codec_config_name": "SingleDev_OneChanMonoSrc_48_3", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "One-OneChan-SrcAse-Lc3_48_3_Balanced_Reliability", + "codec_config_name": "One-OneChan-SrcAse-Lc3_48_3", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_OneChanMonoSrc_48_2_Balanced_Reliability", - "codec_config_name": "SingleDev_OneChanMonoSrc_48_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "One-OneChan-SrcAse-Lc3_48_2_Balanced_Reliability", + "codec_config_name": "One-OneChan-SrcAse-Lc3_48_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_OneChanMonoSrc_48_1_Balanced_Reliability", - "codec_config_name": "SingleDev_OneChanMonoSrc_48_1", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "One-OneChan-SrcAse-Lc3_48_1_Balanced_Reliability", + "codec_config_name": "One-OneChan-SrcAse-Lc3_48_1", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_OneChanMonoSrc_32_2_Balanced_Reliability", - "codec_config_name": "SingleDev_OneChanMonoSrc_32_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "One-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability", + "codec_config_name": "One-OneChan-SrcAse-Lc3_32_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_OneChanMonoSrc_32_1_Balanced_Reliability", - "codec_config_name": "SingleDev_OneChanMonoSrc_32_1", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "One-OneChan-SrcAse-Lc3_32_1_Balanced_Reliability", + "codec_config_name": "One-OneChan-SrcAse-Lc3_32_1", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_OneChanMonoSrc_24_2_Balanced_Reliability", - "codec_config_name": "SingleDev_OneChanMonoSrc_24_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "One-OneChan-SrcAse-Lc3_24_2_Balanced_Reliability", + "codec_config_name": "One-OneChan-SrcAse-Lc3_24_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_OneChanMonoSrc_24_1_Balanced_Reliability", - "codec_config_name": "SingleDev_OneChanMonoSrc_24_1", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "One-OneChan-SrcAse-Lc3_24_1_Balanced_Reliability", + "codec_config_name": "One-OneChan-SrcAse-Lc3_24_1", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_OneChanMonoSrc_16_2_Balanced_Reliability", - "codec_config_name": "SingleDev_OneChanMonoSrc_16_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability", + "codec_config_name": "One-OneChan-SrcAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_OneChanMonoSrc_16_1_Balanced_Reliability", - "codec_config_name": "SingleDev_OneChanMonoSrc_16_1", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "One-OneChan-SrcAse-Lc3_16_1_Balanced_Reliability", + "codec_config_name": "One-OneChan-SrcAse-Lc3_16_1", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_2", - "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1", - "qos_config_name": ["QoS_Config_16_1_2"] + "name": "One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_2", + "codec_config_name": "One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1", + "qos_config_name": [ + "QoS_Config_16_1_2" + ] }, { - "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_Low_Latency", - "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency", + "codec_config_name": "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_1", - "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2", - "qos_config_name": ["QoS_Config_16_2_1"] + "name": "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1", + "codec_config_name": "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_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": "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_2", + "codec_config_name": "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_16_2_2" + ] }, { - "name": "DualDev_OneChanStereoSnk_24_1_Low_Latency", - "codec_config_name": "DualDev_OneChanStereoSnk_24_1", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-OneChan-SnkAse-Lc3_24_1_Low_Latency", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_24_1", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_24_1_Low_Latency", - "codec_config_name": "SingleDev_TwoChanStereoSnk_24_1", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "One-TwoChan-SnkAse-Lc3_24_1_Low_Latency", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_24_1", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_OneChanStereoSnk_24_1_Low_Latency", - "codec_config_name": "SingleDev_OneChanStereoSnk_24_2", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-OneChan-SnkAse-Lc3_24_2_Low_Latency", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_24_2", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "DualDev_OneChanStereoSnk_24_2_Low_Latency", - "codec_config_name": "DualDev_OneChanStereoSnk_24_2", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-OneChan-SnkAse-Lc3_24_2_Low_Latency", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_24_2", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "DualDev_OneChanStereoSnk_24_2_Balanced_Reliability", - "codec_config_name": "DualDev_OneChanStereoSnk_24_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "Two-OneChan-SnkAse-Lc3_24_2_Balanced_Reliability", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_24_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "DualDev_OneChanStereoSnk_24_2_2", - "codec_config_name": "DualDev_OneChanStereoSnk_24_2", - "qos_config_name": ["QoS_Config_24_2_2"] + "name": "Two-OneChan-SnkAse-Lc3_24_2_2", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_24_2", + "qos_config_name": [ + "QoS_Config_24_2_2" + ] }, { - "name": "SingleDev_OneChanStereoSnk_24_2_Low_Latency", - "codec_config_name": "SingleDev_OneChanStereoSnk_24_2", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-OneChan-SnkAse-Lc3_24_2_Low_Latency", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_24_2", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_OneChanStereoSnk_24_2_Balanced_Reliability", - "codec_config_name": "SingleDev_OneChanStereoSnk_24_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "Two-OneChan-SnkAse-Lc3_24_2_Balanced_Reliability", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_24_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_OneChanStereoSnk_24_2_2", - "codec_config_name": "SingleDev_OneChanStereoSnk_24_2", - "qos_config_name": ["QoS_Config_24_2_2"] + "name": "Two-OneChan-SnkAse-Lc3_24_2_2", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_24_2", + "qos_config_name": [ + "QoS_Config_24_2_2" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_24_2_Low_Latency", - "codec_config_name": "SingleDev_TwoChanStereoSnk_24_2", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "One-TwoChan-SnkAse-Lc3_24_2_Low_Latency", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_24_2", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_24_2_Balanced_Reliability", - "codec_config_name": "SingleDev_TwoChanStereoSnk_24_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "One-TwoChan-SnkAse-Lc3_24_2_Balanced_Reliability", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_24_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_24_2_2", - "codec_config_name": "SingleDev_TwoChanStereoSnk_24_2", - "qos_config_name": ["QoS_Config_24_2_2"] + "name": "One-TwoChan-SnkAse-Lc3_24_2_2", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_24_2", + "qos_config_name": [ + "QoS_Config_24_2_2" + ] }, { - "name": "SingleDev_OneChanMonoSnk_24_2_Balanced_Reliability", - "codec_config_name": "SingleDev_OneChanMonoSnk_24_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "One-OneChan-SnkAse-Lc3_24_2_Balanced_Reliability", + "codec_config_name": "One-OneChan-SnkAse-Lc3_24_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_OneChanMonoSnk_24_2_2", - "codec_config_name": "SingleDev_OneChanMonoSnk_24_2", - "qos_config_name": ["QoS_Config_24_2_2"] + "name": "One-OneChan-SnkAse-Lc3_24_2_2", + "codec_config_name": "One-OneChan-SnkAse-Lc3_24_2", + "qos_config_name": [ + "QoS_Config_24_2_2" + ] }, { - "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_Low_Latency", - "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_Low_Latency", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_1", - "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2", - "qos_config_name": ["QoS_Config_32_2_1"] + "name": "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_1", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2", + "qos_config_name": [ + "QoS_Config_32_2_1" + ] }, { - "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency", - "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_32_2", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_32_2_1", - "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_32_2", - "qos_config_name": ["QoS_Config_32_2_1"] + "name": "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2", + "qos_config_name": [ + "QoS_Config_32_2_1" + ] }, { - "name": "DualDev_OneChanStereoSnk_32_2_Low_Latency", - "codec_config_name": "DualDev_OneChanStereoSnk_32_2", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-OneChan-SnkAse-Lc3_32_2_Low_Latency", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_32_2", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "DualDev_OneChanStereoSnk_32_1_Low_Latency", - "codec_config_name": "DualDev_OneChanStereoSnk_32_1", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-OneChan-SnkAse-Lc3_32_1_Low_Latency", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_32_1", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_32_1_Low_Latency", - "codec_config_name": "SingleDev_TwoChanStereoSnk_32_1", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "One-TwoChan-SnkAse-Lc3_32_1_Low_Latency", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_32_1", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_OneChanStereoSnk_32_2_Low_Latency", - "codec_config_name": "SingleDev_OneChanStereoSnk_32_2", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-OneChan-SnkAse-Lc3_32_2_Low_Latency", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_32_2", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_OneChanStereoSnk_32_1_Low_Latency", - "codec_config_name": "SingleDev_OneChanStereoSnk_32_1", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-OneChan-SnkAse-Lc3_32_1_Low_Latency", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_32_1", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency", - "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_1", - "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2", - "qos_config_name": ["QoS_Config_32_2_1"] + "name": "One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2", + "qos_config_name": [ + "QoS_Config_32_2_1" + ] }, { - "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency", - "codec_config_name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2_1", - "codec_config_name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2", - "qos_config_name": ["QoS_Config_32_2_1"] + "name": "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2", + "qos_config_name": [ + "QoS_Config_32_2_1" + ] }, { - "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_Low_Latency", - "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency", + "codec_config_name": "One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_1", - "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2", - "qos_config_name": ["QoS_Config_32_2_1"] + "name": "One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1", + "codec_config_name": "One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2", + "qos_config_name": [ + "QoS_Config_32_2_1" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_32_2_Low_Latency", - "codec_config_name": "SingleDev_TwoChanStereoSnk_32_2", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "One-TwoChan-SnkAse-Lc3_32_2_Low_Latency", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_32_2", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "DualDev_OneChanStereoSnk_48_4_High_Reliability", - "codec_config_name": "DualDev_OneChanStereoSnk_48_4", - "qos_config_name": ["QoS_Config_High_Reliability"] + "name": "Two-OneChan-SnkAse-Lc3_48_4_High_Reliability", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_4", + "qos_config_name": [ + "QoS_Config_High_Reliability" + ] }, { - "name": "DualDev_OneChanStereoSnk_48_4_1", - "codec_config_name": "DualDev_OneChanStereoSnk_48_4", - "qos_config_name": ["QoS_Config_48_4_1"] + "name": "Two-OneChan-SnkAse-Lc3_48_4_1", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_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": "Two-OneChan-SnkAse-Lc3_48_4_2", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_4", + "qos_config_name": [ + "QoS_Config_48_4_2" + ] }, { - "name": "DualDev_OneChanStereoSnk_48_3_Low_Latency", - "codec_config_name": "DualDev_OneChanStereoSnk_48_3", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-OneChan-SnkAse-Lc3_48_3_Low_Latency", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_3", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "DualDev_OneChanStereoSnk_48_3_High_Reliability", - "codec_config_name": "DualDev_OneChanStereoSnk_48_3", - "qos_config_name": ["QoS_Config_High_Reliability"] + "name": "Two-OneChan-SnkAse-Lc3_48_3_High_Reliability", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_3", + "qos_config_name": [ + "QoS_Config_High_Reliability" + ] }, { - "name": "DualDev_OneChanStereoSnk_48_3_2", - "codec_config_name": "DualDev_OneChanStereoSnk_48_3", - "qos_config_name": ["QoS_Config_48_3_2"] + "name": "Two-OneChan-SnkAse-Lc3_48_3_2", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_3", + "qos_config_name": [ + "QoS_Config_48_3_2" + ] }, { - "name": "DualDev_OneChanStereoSnk_48_2_Low_Latency", - "codec_config_name": "DualDev_OneChanStereoSnk_48_2", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-OneChan-SnkAse-Lc3_48_2_Low_Latency", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_2", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "DualDev_OneChanStereoSnk_48_2_High_Reliability", - "codec_config_name": "DualDev_OneChanStereoSnk_48_2", - "qos_config_name": ["QoS_Config_High_Reliability"] + "name": "Two-OneChan-SnkAse-Lc3_48_2_High_Reliability", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_2", + "qos_config_name": [ + "QoS_Config_High_Reliability" + ] }, { - "name": "DualDev_OneChanStereoSnk_48_2_2", - "codec_config_name": "DualDev_OneChanStereoSnk_48_2", - "qos_config_name": ["QoS_Config_48_2_2"] + "name": "Two-OneChan-SnkAse-Lc3_48_2_2", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_2", + "qos_config_name": [ + "QoS_Config_48_2_2" + ] }, { - "name": "DualDev_OneChanStereoSnk_48_1_Low_Latency", - "codec_config_name": "DualDev_OneChanStereoSnk_48_1", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-OneChan-SnkAse-Lc3_48_1_Low_Latency", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_1", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "DualDev_OneChanStereoSnk_48_1_High_Reliability", - "codec_config_name": "DualDev_OneChanStereoSnk_48_1", - "qos_config_name": ["QoS_Config_High_Reliability"] + "name": "Two-OneChan-SnkAse-Lc3_48_1_High_Reliability", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_1", + "qos_config_name": [ + "QoS_Config_High_Reliability" + ] }, { - "name": "DualDev_OneChanStereoSnk_48_1_2", - "codec_config_name": "DualDev_OneChanStereoSnk_48_1", - "qos_config_name": ["QoS_Config_48_1_2"] + "name": "Two-OneChan-SnkAse-Lc3_48_1_2", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_1", + "qos_config_name": [ + "QoS_Config_48_1_2" + ] }, { - "name": "SingleDev_OneChanStereoSnk_48_4_High_Reliability", - "codec_config_name": "SingleDev_OneChanStereoSnk_48_4", - "qos_config_name": ["QoS_Config_High_Reliability"] + "name": "Two-OneChan-SnkAse-Lc3_48_4_High_Reliability", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_4", + "qos_config_name": [ + "QoS_Config_High_Reliability" + ] }, { - "name": "SingleDev_OneChanStereoSnk_48_4_1", - "codec_config_name": "SingleDev_OneChanStereoSnk_48_4", - "qos_config_name": ["QoS_Config_48_4_1"] + "name": "Two-OneChan-SnkAse-Lc3_48_4_1", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_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": "Two-OneChan-SnkAse-Lc3_48_4_2", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_4", + "qos_config_name": [ + "QoS_Config_48_4_2" + ] }, { - "name": "SingleDev_OneChanStereoSnk_48_3_Low_Latency", - "codec_config_name": "SingleDev_OneChanStereoSnk_48_3", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-OneChan-SnkAse-Lc3_48_3_Low_Latency", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_3", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_OneChanStereoSnk_48_3_High_Reliability", - "codec_config_name": "SingleDev_OneChanStereoSnk_48_3", - "qos_config_name": ["QoS_Config_High_Reliability"] + "name": "Two-OneChan-SnkAse-Lc3_48_3_High_Reliability", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_3", + "qos_config_name": [ + "QoS_Config_High_Reliability" + ] }, { - "name": "SingleDev_OneChanStereoSnk_48_3_2", - "codec_config_name": "SingleDev_OneChanStereoSnk_48_3", - "qos_config_name": ["QoS_Config_48_3_2"] + "name": "Two-OneChan-SnkAse-Lc3_48_3_2", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_3", + "qos_config_name": [ + "QoS_Config_48_3_2" + ] }, { - "name": "SingleDev_OneChanStereoSnk_48_2_Low_Latency", - "codec_config_name": "SingleDev_OneChanStereoSnk_48_2", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-OneChan-SnkAse-Lc3_48_2_Low_Latency", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_2", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_OneChanStereoSnk_48_2_High_Reliability", - "codec_config_name": "SingleDev_OneChanStereoSnk_48_2", - "qos_config_name": ["QoS_Config_High_Reliability"] + "name": "Two-OneChan-SnkAse-Lc3_48_2_High_Reliability", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_2", + "qos_config_name": [ + "QoS_Config_High_Reliability" + ] }, { - "name": "SingleDev_OneChanStereoSnk_48_2_2", - "codec_config_name": "SingleDev_OneChanStereoSnk_48_2", - "qos_config_name": ["QoS_Config_48_2_2"] + "name": "Two-OneChan-SnkAse-Lc3_48_2_2", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_2", + "qos_config_name": [ + "QoS_Config_48_2_2" + ] }, { - "name": "SingleDev_OneChanStereoSnk_48_1_Low_Latency", - "codec_config_name": "SingleDev_OneChanStereoSnk_48_1", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-OneChan-SnkAse-Lc3_48_1_Low_Latency", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_1", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_OneChanStereoSnk_48_1_High_Reliability", - "codec_config_name": "SingleDev_OneChanStereoSnk_48_1", - "qos_config_name": ["QoS_Config_High_Reliability"] + "name": "Two-OneChan-SnkAse-Lc3_48_1_High_Reliability", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_1", + "qos_config_name": [ + "QoS_Config_High_Reliability" + ] }, { - "name": "SingleDev_OneChanStereoSnk_48_1_2", - "codec_config_name": "SingleDev_OneChanStereoSnk_48_1", - "qos_config_name": ["QoS_Config_48_1_2"] + "name": "Two-OneChan-SnkAse-Lc3_48_1_2", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_1", + "qos_config_name": [ + "QoS_Config_48_1_2" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_4_High_Reliability", - "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4", - "qos_config_name": ["QoS_Config_High_Reliability"] + "name": "One-TwoChan-SnkAse-Lc3_48_4_High_Reliability", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_4", + "qos_config_name": [ + "QoS_Config_High_Reliability" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_4_1", - "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4", - "qos_config_name": ["QoS_Config_48_4_1"] + "name": "One-TwoChan-SnkAse-Lc3_48_4_1", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_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": "One-TwoChan-SnkAse-Lc3_48_4_2", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_4", + "qos_config_name": [ + "QoS_Config_48_4_2" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_3_Low_Latency", - "codec_config_name": "SingleDev_TwoChanStereoSnk_48_3", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "One-TwoChan-SnkAse-Lc3_48_3_Low_Latency", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_3", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_3_High_Reliability", - "codec_config_name": "SingleDev_TwoChanStereoSnk_48_3", - "qos_config_name": ["QoS_Config_High_Reliability"] + "name": "One-TwoChan-SnkAse-Lc3_48_3_High_Reliability", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_3", + "qos_config_name": [ + "QoS_Config_High_Reliability" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_3_2", - "codec_config_name": "SingleDev_TwoChanStereoSnk_48_3", - "qos_config_name": ["QoS_Config_48_3_2"] + "name": "One-TwoChan-SnkAse-Lc3_48_3_2", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_3", + "qos_config_name": [ + "QoS_Config_48_3_2" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_2_Low_Latency", - "codec_config_name": "SingleDev_TwoChanStereoSnk_48_2", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "One-TwoChan-SnkAse-Lc3_48_2_Low_Latency", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_2", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_2_High_Reliability", - "codec_config_name": "SingleDev_TwoChanStereoSnk_48_2", - "qos_config_name": ["QoS_Config_High_Reliability"] + "name": "One-TwoChan-SnkAse-Lc3_48_2_High_Reliability", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_2", + "qos_config_name": [ + "QoS_Config_High_Reliability" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_2_2", - "codec_config_name": "SingleDev_TwoChanStereoSnk_48_2", - "qos_config_name": ["QoS_Config_48_2_2"] + "name": "One-TwoChan-SnkAse-Lc3_48_2_2", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_2", + "qos_config_name": [ + "QoS_Config_48_2_2" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_1_Low_Latency", - "codec_config_name": "SingleDev_TwoChanStereoSnk_48_1", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "One-TwoChan-SnkAse-Lc3_48_1_Low_Latency", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_1", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_1_High_Reliability", - "codec_config_name": "SingleDev_TwoChanStereoSnk_48_1", - "qos_config_name": ["QoS_Config_High_Reliability"] + "name": "One-TwoChan-SnkAse-Lc3_48_1_High_Reliability", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_1", + "qos_config_name": [ + "QoS_Config_High_Reliability" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_1_2", - "codec_config_name": "SingleDev_TwoChanStereoSnk_48_1", - "qos_config_name": ["QoS_Config_48_1_2"] + "name": "One-TwoChan-SnkAse-Lc3_48_1_2", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_1", + "qos_config_name": [ + "QoS_Config_48_1_2" + ] }, { - "name": "SingleDev_OneChanMonoSnk_48_4_High_Reliability", - "codec_config_name": "SingleDev_OneChanMonoSnk_48_4", - "qos_config_name": ["QoS_Config_High_Reliability"] + "name": "One-OneChan-SnkAse-Lc3_48_4_High_Reliability", + "codec_config_name": "One-OneChan-SnkAse-Lc3_48_4", + "qos_config_name": [ + "QoS_Config_High_Reliability" + ] }, { - "name": "SingleDev_OneChanMonoSnk_48_4_1", - "codec_config_name": "SingleDev_OneChanMonoSnk_48_4", - "qos_config_name": ["QoS_Config_48_4_1"] + "name": "One-OneChan-SnkAse-Lc3_48_4_1", + "codec_config_name": "One-OneChan-SnkAse-Lc3_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"] + "name": "One-OneChan-SnkAse-Lc3_48_4_2", + "codec_config_name": "One-OneChan-SnkAse-Lc3_48_4", + "qos_config_name": [ + "QoS_Config_48_4_2" + ] }, { - "name": "SingleDev_OneChanMonoSnk_48_3_High_Reliability", - "codec_config_name": "SingleDev_OneChanMonoSnk_48_3", - "qos_config_name": ["QoS_Config_High_Reliability"] + "name": "One-OneChan-SnkAse-Lc3_48_3_High_Reliability", + "codec_config_name": "One-OneChan-SnkAse-Lc3_48_3", + "qos_config_name": [ + "QoS_Config_High_Reliability" + ] }, { - "name": "SingleDev_OneChanMonoSnk_48_3_2", - "codec_config_name": "SingleDev_OneChanMonoSnk_48_3", - "qos_config_name": ["QoS_Config_48_3_2"] + "name": "One-OneChan-SnkAse-Lc3_48_3_2", + "codec_config_name": "One-OneChan-SnkAse-Lc3_48_3", + "qos_config_name": [ + "QoS_Config_48_3_2" + ] }, { - "name": "SingleDev_OneChanMonoSnk_48_2_High_Reliability", - "codec_config_name": "SingleDev_OneChanMonoSnk_48_2", - "qos_config_name": ["QoS_Config_High_Reliability"] + "name": "One-OneChan-SnkAse-Lc3_48_2_High_Reliability", + "codec_config_name": "One-OneChan-SnkAse-Lc3_48_2", + "qos_config_name": [ + "QoS_Config_High_Reliability" + ] }, { - "name": "SingleDev_OneChanMonoSnk_48_2_2", - "codec_config_name": "SingleDev_OneChanMonoSnk_48_2", - "qos_config_name": ["QoS_Config_48_2_2"] + "name": "One-OneChan-SnkAse-Lc3_48_2_2", + "codec_config_name": "One-OneChan-SnkAse-Lc3_48_2", + "qos_config_name": [ + "QoS_Config_48_2_2" + ] }, { - "name": "SingleDev_OneChanMonoSnk_48_1_High_Reliability", - "codec_config_name": "SingleDev_OneChanMonoSnk_48_1", - "qos_config_name": ["QoS_Config_High_Reliability"] + "name": "One-OneChan-SnkAse-Lc3_48_1_High_Reliability", + "codec_config_name": "One-OneChan-SnkAse-Lc3_48_1", + "qos_config_name": [ + "QoS_Config_High_Reliability" + ] }, { - "name": "SingleDev_OneChanMonoSnk_48_1_2", - "codec_config_name": "SingleDev_OneChanMonoSnk_48_1", - "qos_config_name": ["QoS_Config_48_1_2"] + "name": "One-OneChan-SnkAse-Lc3_48_1_2", + "codec_config_name": "One-OneChan-SnkAse-Lc3_48_1", + "qos_config_name": [ + "QoS_Config_48_1_2" + ] }, { "name": "VND_SingleDev_TwoChanStereoSnk_OneChanStereoSrc_32khz_60octs_Low_Latency_1", "codec_config_name": "VND_SingleDev_TwoChanStereoSnk_OneChanStereoSrc_32khz_60octs_1", - "qos_config_name": ["QoS_Config_Low_Latency"] + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { "name": "VND_SingleDev_TwoChanStereoSnk_OneChanStereoSrc_32khz_60oct_R3_L22_1", "codec_config_name": "VND_SingleDev_TwoChanStereoSnk_OneChanStereoSrc_32khz_60octs_1", - "qos_config_name": ["VND_QoS_Config_R3_L22"] + "qos_config_name": [ + "VND_QoS_Config_R3_L22" + ] }, { "name": "VND_DualDev_OneChanStereoSnk_48khz_100octs_High_Reliability_1", "codec_config_name": "VND_DualDev_OneChanStereoSnk_48khz_100octs_1", - "qos_config_name": ["QoS_Config_High_Reliability"] + "qos_config_name": [ + "QoS_Config_High_Reliability" + ] }, { "name": "VND_DualDev_OneChanStereoSnk_48khz_100octs_R15_L70_1", "codec_config_name": "VND_DualDev_OneChanStereoSnk_48khz_100octs_1", - "qos_config_name": ["VND_QoS_Config_R15_L70"] + "qos_config_name": [ + "VND_QoS_Config_R15_L70" + ] }, { "name": "VND_SingleDev_OneChanStereoSnk_48khz_100octs_High_Reliability_1", "codec_config_name": "VND_SingleDev_OneChanStereoSnk_48khz_100octs_1", - "qos_config_name": ["QoS_Config_High_Reliability"] + "qos_config_name": [ + "QoS_Config_High_Reliability" + ] }, { "name": "VND_SingleDev_OneChanStereoSnk_48khz_100octs_R15_L70_1", "codec_config_name": "VND_SingleDev_OneChanStereoSnk_48khz_100octs_1", - "qos_config_name": ["VND_QoS_Config_R15_L70"] + "qos_config_name": [ + "VND_QoS_Config_R15_L70" + ] }, { "name": "VND_SingleDev_TwoChanStereoSnk_48khz_100octs_High_Reliability_1", "codec_config_name": "VND_SingleDev_TwoChanStereoSnk_48khz_100octs_1", - "qos_config_name": ["QoS_Config_High_Reliability"] + "qos_config_name": [ + "QoS_Config_High_Reliability" + ] }, { "name": "VND_SingleDev_TwoChanStereoSnk_48khz_100octs_R15_L70_1", "codec_config_name": "VND_SingleDev_TwoChanStereoSnk_48khz_100octs_1", - "qos_config_name": ["VND_QoS_Config_R15_L70"] + "qos_config_name": [ + "VND_QoS_Config_R15_L70" + ] }, { "name": "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_High_Reliability_1", "codec_config_name": "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_1", - "qos_config_name": ["QoS_Config_High_Reliability"] + "qos_config_name": [ + "QoS_Config_High_Reliability" + ] }, { "name": "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_R5_L12_1", "codec_config_name": "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_1", - "qos_config_name": ["VND_QoS_Config_R5_L12"] + "qos_config_name": [ + "VND_QoS_Config_R5_L12" + ] }, { - "name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_32_2_Balanced_Reliability", - "codec_config_name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_32_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "Two-OneChan-SnkAse-Lc3_48_4-Two-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_4-Two-OneChan-SrcAse-Lc3_32_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_24_2_Balanced_Reliability", - "codec_config_name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_24_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "Two-OneChan-SnkAse-Lc3_48_4-Two-OneChan-SrcAse-Lc3_24_2_Balanced_Reliability", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_4-Two-OneChan-SrcAse-Lc3_24_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_16_2_Balanced_Reliability", - "codec_config_name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_16_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "Two-OneChan-SnkAse-Lc3_48_4-Two-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_4-Two-OneChan-SrcAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability", - "codec_config_name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_32_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability", - "codec_config_name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_24_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2_Balanced_Reliability", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability", - "codec_config_name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_16_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_32_2_Balanced_Reliability", - "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_32_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "One-TwoChan-SnkAse-Lc3_48_4-One-TwoChan-SrcAse-Lc3_32_2_Balanced_Reliability", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_4-One-TwoChan-SrcAse-Lc3_32_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_24_2_Balanced_Reliability", - "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_24_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "One-TwoChan-SnkAse-Lc3_48_4-One-TwoChan-SrcAse-Lc3_24_2_Balanced_Reliability", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_4-One-TwoChan-SrcAse-Lc3_24_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_16_2_Balanced_Reliability", - "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_16_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "One-TwoChan-SnkAse-Lc3_48_4-One-TwoChan-SrcAse-Lc3_16_2_Balanced_Reliability", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_4-One-TwoChan-SrcAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability", - "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_32_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "One-TwoChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability", - "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_24_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "One-TwoChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2_Balanced_Reliability", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability", - "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_16_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "One-TwoChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability", + "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability", - "codec_config_name": "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_32_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability", - "codec_config_name": "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_24_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2_Balanced_Reliability", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability", - "codec_config_name": "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_16_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability", + "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability", - "codec_config_name": "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_32_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability", + "codec_config_name": "One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability", - "codec_config_name": "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_24_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2_Balanced_Reliability", + "codec_config_name": "One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability", - "codec_config_name": "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_16_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability", + "codec_config_name": "One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_1_Low_Latency", - "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_1", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-TwoChan-SnkAse-Lc3_48_1-Two-TwoChan-SrcAse-Lc3_48_1_Low_Latency", + "codec_config_name": "Two-TwoChan-SnkAse-Lc3_48_1-Two-TwoChan-SrcAse-Lc3_48_1", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_1_Balanced_Reliability", - "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_1", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "Two-TwoChan-SnkAse-Lc3_48_1-Two-TwoChan-SrcAse-Lc3_48_1_Balanced_Reliability", + "codec_config_name": "Two-TwoChan-SnkAse-Lc3_48_1-Two-TwoChan-SrcAse-Lc3_48_1", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { - "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_2_Low_Latency", - "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_2", - "qos_config_name": ["QoS_Config_Low_Latency"] + "name": "Two-TwoChan-SnkAse-Lc3_48_2-Two-TwoChan-SrcAse-Lc3_48_2_Low_Latency", + "codec_config_name": "Two-TwoChan-SnkAse-Lc3_48_2-Two-TwoChan-SrcAse-Lc3_48_2", + "qos_config_name": [ + "QoS_Config_Low_Latency" + ] }, { - "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_2_Balanced_Reliability", - "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "name": "Two-TwoChan-SnkAse-Lc3_48_2-Two-TwoChan-SrcAse-Lc3_48_2_Balanced_Reliability", + "codec_config_name": "Two-TwoChan-SnkAse-Lc3_48_2-Two-TwoChan-SrcAse-Lc3_48_2", + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { "name": "VND_SingleDev_TwoChanStereoSrc_48khz_100octs_Balanced_Reliability_1", "codec_config_name": "VND_SingleDev_TwoChanStereoSrc_48khz_100octs_1", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] }, { "name": "VND_SingleDev_TwoChanStereoSrc_48khz_100octs_R11_L40_1", "codec_config_name": "VND_SingleDev_TwoChanStereoSrc_48khz_100octs_1", - "qos_config_name": ["VND_QoS_Config_R11_L40"] + "qos_config_name": [ + "VND_QoS_Config_R11_L40" + ] }, { "name": "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_R5_L12_TwoChanStereoSrc_16khz_30octs_R3_L12_1", "codec_config_name": "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_TwoChanStereoSrc_16khz_30octs_1", - "qos_config_name": ["VND_QoS_Config_R5_L12", "VND_QoS_Config_R3_L12"] + "qos_config_name": [ + "VND_QoS_Config_R5_L12", + "VND_QoS_Config_R3_L12" + ] }, { "name": "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_TwoChanStereoSrc_16khz_30octs_Balanced_Reliability_1", "codec_config_name": "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_TwoChanStereoSrc_16khz_30octs_1", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] + "qos_config_name": [ + "QoS_Config_Balanced_Reliability" + ] } ], "codec_configurations": [ { - "name": "DualDev_OneChanStereoSnk_16_2", - "subconfigurations": [ - { - "device_cnt": 2, - "ase_cnt": 2, - "direction": "SINK", - "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 3 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 1 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 40, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - } - ] - }, - { - "name": "DualDev_OneChanStereoSnk_16_1", - "subconfigurations": [ - { - "device_cnt": 2, - "ase_cnt": 2, - "direction": "SINK", - "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 3 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 0 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 30, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - } - ] - }, - { - "name": "SingleDev_OneChanStereoSnk_16_2", + "name": "Two-OneChan-SnkAse-Lc3_16_2", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 2, "direction": "SINK", - "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -1201,18 +1457,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -1231,18 +1475,17 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_OneChanStereoSnk_16_1", + "name": "Two-OneChan-SnkAse-Lc3_16_1", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 2, "direction": "SINK", - "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -1268,18 +1511,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -1298,18 +1529,17 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_TwoChanStereoSnk_16_2", + "name": "One-TwoChan-SnkAse-Lc3_16_2", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -1335,18 +1565,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -1365,18 +1583,17 @@ ] } } - ] + ], + "ase_channel_cnt": 2 } ] }, { - "name": "SingleDev_TwoChanStereoSnk_16_1", + "name": "One-TwoChan-SnkAse-Lc3_16_1", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -1402,18 +1619,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -1432,18 +1637,17 @@ ] } } - ] + ], + "ase_channel_cnt": 2 } ] }, { - "name": "SingleDev_OneChanStereoSrc_16_2", + "name": "Two-OneChan-SrcAse-Lc3_16_2", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 2, "direction": "SOURCE", - "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -1469,18 +1673,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -1499,15 +1691,15 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_OneChanMonoSrc_24_2", + "name": "One-OneChan-SrcAse-Lc3_24_2", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -1535,18 +1727,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -1565,18 +1745,17 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "DualDev_OneChanStereoSnk_32_2", + "name": "Two-OneChan-SnkAse-Lc3_32_2", "subconfigurations": [ { - "device_cnt": 2, "ase_cnt": 2, "direction": "SINK", - "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -1602,18 +1781,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -1632,18 +1799,17 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "DualDev_OneChanStereoSnk_32_1", + "name": "Two-OneChan-SnkAse-Lc3_32_1", "subconfigurations": [ { - "device_cnt": 2, "ase_cnt": 2, "direction": "SINK", - "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -1669,18 +1835,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -1699,18 +1853,17 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_OneChanMonoSnk_32_2", + "name": "One-OneChan-SnkAse-Lc3_32_2", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -1736,18 +1889,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -1766,18 +1907,17 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_OneChanMonoSnk_32_1", + "name": "One-OneChan-SnkAse-Lc3_32_1", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -1803,18 +1943,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -1833,85 +1961,17 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "DualDev_OneChanMonoSnk_16_2", + "name": "One-OneChan-SnkAse-Lc3_16_2", "subconfigurations": [ { - "device_cnt": 2, - "ase_cnt": 2, - "direction": "SINK", - "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 3 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 1 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 40, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - } - ] - }, - { - "name": "SingleDev_OneChanMonoSnk_16_2", - "subconfigurations": [ - { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -1937,18 +1997,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -1967,18 +2015,17 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_OneChanMonoSnk_16_1", + "name": "One-OneChan-SnkAse-Lc3_16_1", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -2004,18 +2051,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -2034,15 +2069,15 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2", + "name": "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2", "subconfigurations": [ { - "device_cnt": 2, "ase_cnt": 2, "direction": "SINK", "codec_id": { @@ -2070,18 +2105,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -2100,10 +2123,10 @@ ] } } - ] + ], + "ase_channel_cnt": 1 }, { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -2131,18 +2154,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -2161,15 +2172,15 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2", + "name": "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2", "subconfigurations": [ { - "device_cnt": 2, "ase_cnt": 2, "direction": "SINK", "codec_id": { @@ -2197,18 +2208,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -2227,10 +2226,10 @@ ] } } - ] + ], + "ase_channel_cnt": 1 }, { - "device_cnt": 2, "ase_cnt": 2, "direction": "SOURCE", "codec_id": { @@ -2258,18 +2257,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -2288,15 +2275,15 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1", + "name": "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1", "subconfigurations": [ { - "device_cnt": 2, "ase_cnt": 2, "direction": "SINK", "codec_id": { @@ -2324,18 +2311,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -2354,10 +2329,10 @@ ] } } - ] + ], + "ase_channel_cnt": 1 }, { - "device_cnt": 2, "ase_cnt": 2, "direction": "SOURCE", "codec_id": { @@ -2385,18 +2360,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -2415,15 +2378,15 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1", + "name": "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1", "subconfigurations": [ { - "device_cnt": 2, "ase_cnt": 2, "direction": "SINK", "codec_id": { @@ -2451,18 +2414,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -2481,10 +2432,10 @@ ] } } - ] + ], + "ase_channel_cnt": 1 }, { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -2512,18 +2463,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -2542,18 +2481,17 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2", + "name": "One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -2579,18 +2517,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -2609,13 +2535,12 @@ ] } } - ] + ], + "ase_channel_cnt": 2 }, { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -2641,18 +2566,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -2671,18 +2584,17 @@ ] } } - ] + ], + "ase_channel_cnt": 2 } ] }, { - "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2", + "name": "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -2708,18 +2620,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -2738,13 +2638,12 @@ ] } } - ] + ], + "ase_channel_cnt": 2 }, { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -2770,18 +2669,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -2800,18 +2687,17 @@ ] } } - ] + ], + "ase_channel_cnt": 2 } ] }, { - "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1", + "name": "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -2837,18 +2723,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -2867,13 +2741,12 @@ ] } } - ] + ], + "ase_channel_cnt": 2 }, { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -2899,18 +2772,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -2929,18 +2790,17 @@ ] } } - ] + ], + "ase_channel_cnt": 2 } ] }, { - "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2", + "name": "One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -2966,18 +2826,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -2996,10 +2844,10 @@ ] } } - ] + ], + "ase_channel_cnt": 2 }, { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -3027,18 +2875,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -3057,274 +2893,17 @@ ] } } - ] - } - ] - }, - { - "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1", - "subconfigurations": [ - { - "device_cnt": 1, - "ase_cnt": 1, - "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 3 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 0 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 30, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - }, - { - "device_cnt": 1, - "ase_cnt": 1, - "direction": "SOURCE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 3 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 0 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 30, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2", + "name": "One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1", "subconfigurations": [ { - "device_cnt": 1, - "ase_cnt": 2, - "direction": "SINK", - "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 3 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 1 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 40, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - }, - { - "device_cnt": 1, "ase_cnt": 1, - "direction": "SOURCE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 3 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 1 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 40, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - } - ] - }, - { - "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1", - "subconfigurations": [ - { - "device_cnt": 1, - "ase_cnt": 2, "direction": "SINK", - "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -3350,18 +2929,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -3380,10 +2947,10 @@ ] } } - ] + ], + "ase_channel_cnt": 2 }, { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -3411,18 +2978,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -3441,15 +2996,15 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2", + "name": "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", "codec_id": { @@ -3477,18 +3032,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -3507,10 +3050,10 @@ ] } } - ] + ], + "ase_channel_cnt": 1 }, { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -3538,18 +3081,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -3568,15 +3099,15 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1", + "name": "One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", "codec_id": { @@ -3604,18 +3135,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -3634,10 +3153,10 @@ ] } } - ] + ], + "ase_channel_cnt": 1 }, { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -3665,18 +3184,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -3695,81 +3202,15 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "DualDev_OneChanMonoSrc_16_2", + "name": "One-OneChan-SrcAse-Lc3_48_4", "subconfigurations": [ { - "device_cnt": 2, - "ase_cnt": 2, - "direction": "SOURCE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 3 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 1 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 40, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - } - ] - }, - { - "name": "SingleDev_OneChanMonoSrc_48_4", - "subconfigurations": [ - { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -3797,18 +3238,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -3827,15 +3256,15 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_OneChanMonoSrc_48_3", + "name": "One-OneChan-SrcAse-Lc3_48_3", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -3863,18 +3292,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -3893,15 +3310,15 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_OneChanMonoSrc_48_2", + "name": "One-OneChan-SrcAse-Lc3_48_2", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -3929,18 +3346,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -3959,15 +3364,15 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_OneChanMonoSrc_48_1", + "name": "One-OneChan-SrcAse-Lc3_48_1", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -3995,18 +3400,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -4025,15 +3418,15 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_OneChanMonoSrc_32_2", + "name": "One-OneChan-SrcAse-Lc3_32_2", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -4061,18 +3454,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -4091,15 +3472,15 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_OneChanMonoSrc_32_1", + "name": "One-OneChan-SrcAse-Lc3_32_1", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -4127,18 +3508,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -4157,15 +3526,15 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_OneChanMonoSrc_24_2", + "name": "One-OneChan-SrcAse-Lc3_24_1", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -4188,84 +3557,6 @@ "type": 2, "compound_value": { "value": [ - 1 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 60, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - } - ] - }, - { - "name": "SingleDev_OneChanMonoSrc_24_1", - "subconfigurations": [ - { - "device_cnt": 1, - "ase_cnt": 1, - "direction": "SOURCE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 5 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 0 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, 0 ] } @@ -4289,15 +3580,15 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_OneChanMonoSrc_16_2", + "name": "One-OneChan-SrcAse-Lc3_16_2", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -4325,18 +3616,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -4355,15 +3634,15 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_OneChanMonoSrc_16_1", + "name": "One-OneChan-SrcAse-Lc3_16_1", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -4391,18 +3670,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -4421,18 +3688,17 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "DualDev_OneChanStereoSnk_48_4", + "name": "Two-OneChan-SnkAse-Lc3_48_4", "subconfigurations": [ { - "device_cnt": 2, "ase_cnt": 2, "direction": "SINK", - "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -4458,18 +3724,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -4488,18 +3742,17 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "DualDev_OneChanStereoSnk_48_3", + "name": "Two-OneChan-SnkAse-Lc3_48_3", "subconfigurations": [ { - "device_cnt": 2, "ase_cnt": 2, "direction": "SINK", - "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -4525,18 +3778,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -4555,18 +3796,17 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "DualDev_OneChanStereoSnk_48_2", + "name": "Two-OneChan-SnkAse-Lc3_48_2", "subconfigurations": [ { - "device_cnt": 2, "ase_cnt": 2, "direction": "SINK", - "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -4592,18 +3832,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -4622,18 +3850,17 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "DualDev_OneChanStereoSnk_48_1", + "name": "Two-OneChan-SnkAse-Lc3_48_1", "subconfigurations": [ { - "device_cnt": 2, "ase_cnt": 2, "direction": "SINK", - "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -4659,18 +3886,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -4689,286 +3904,17 @@ ] } } - ] - } - ] - }, - { - "name": "SingleDev_OneChanStereoSnk_48_4", - "subconfigurations": [ - { - "device_cnt": 1, - "ase_cnt": 2, - "direction": "SINK", - "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 8 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 1 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 120, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_OneChanStereoSnk_48_3", + "name": "One-TwoChan-SnkAse-Lc3_48_4", "subconfigurations": [ { - "device_cnt": 1, - "ase_cnt": 2, - "direction": "SINK", - "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 8 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 1 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 90, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - } - ] - }, - { - "name": "SingleDev_OneChanStereoSnk_48_2", - "subconfigurations": [ - { - "device_cnt": 1, - "ase_cnt": 2, - "direction": "SINK", - "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 8 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 1 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 100, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - } - ] - }, - { - "name": "SingleDev_OneChanStereoSnk_48_1", - "subconfigurations": [ - { - "device_cnt": 1, - "ase_cnt": 2, - "direction": "SINK", - "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 8 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 0 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 75, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - } - ] - }, - { - "name": "SingleDev_TwoChanStereoSnk_48_4", - "subconfigurations": [ - { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -4994,18 +3940,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -5024,18 +3958,17 @@ ] } } - ] + ], + "ase_channel_cnt": 2 } ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_3", + "name": "One-TwoChan-SnkAse-Lc3_48_3", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -5061,18 +3994,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -5091,18 +4012,17 @@ ] } } - ] + ], + "ase_channel_cnt": 2 } ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_2", + "name": "One-TwoChan-SnkAse-Lc3_48_2", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -5128,18 +4048,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -5158,18 +4066,17 @@ ] } } - ] + ], + "ase_channel_cnt": 2 } ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_1", + "name": "One-TwoChan-SnkAse-Lc3_48_1", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -5195,18 +4102,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -5225,18 +4120,17 @@ ] } } - ] + ], + "ase_channel_cnt": 2 } ] }, { - "name": "SingleDev_OneChanMonoSnk_48_4", + "name": "One-OneChan-SnkAse-Lc3_48_4", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -5262,18 +4156,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -5292,18 +4174,17 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_OneChanMonoSnk_48_3", + "name": "One-OneChan-SnkAse-Lc3_48_3", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -5329,18 +4210,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -5359,18 +4228,17 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_OneChanMonoSnk_48_2", + "name": "One-OneChan-SnkAse-Lc3_48_2", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -5396,18 +4264,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -5426,18 +4282,17 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_OneChanMonoSnk_48_1", + "name": "One-OneChan-SnkAse-Lc3_48_1", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -5463,18 +4318,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -5493,7 +4336,8 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, @@ -5501,10 +4345,8 @@ "name": "VND_SingleDev_TwoChanStereoSnk_48khz_100octs_1", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -5530,18 +4372,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -5560,7 +4390,8 @@ ] } } - ] + ], + "ase_channel_cnt": 2 } ] }, @@ -5568,10 +4399,8 @@ "name": "VND_DualDev_OneChanStereoSnk_48khz_100octs_1", "subconfigurations": [ { - "device_cnt": 2, "ase_cnt": 2, "direction": "SINK", - "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -5597,18 +4426,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -5627,7 +4444,8 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, @@ -5635,10 +4453,8 @@ "name": "VND_SingleDev_OneChanStereoSnk_48khz_100octs_1", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 2, "direction": "SINK", - "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -5664,18 +4480,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -5694,7 +4498,8 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, @@ -5702,10 +4507,8 @@ "name": "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_1", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -5731,18 +4534,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -5761,15 +4552,15 @@ ] } } - ] + ], + "ase_channel_cnt": 2 } ] }, { - "name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_32_2", + "name": "Two-OneChan-SnkAse-Lc3_48_4-Two-OneChan-SrcAse-Lc3_32_2", "subconfigurations": [ { - "device_cnt": 2, "ase_cnt": 2, "direction": "SINK", "codec_id": { @@ -5797,18 +4588,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -5827,10 +4606,10 @@ ] } } - ] + ], + "ase_channel_cnt": 1 }, { - "device_cnt": 2, "ase_cnt": 2, "direction": "SOURCE", "codec_id": { @@ -5858,18 +4637,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -5888,15 +4655,15 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_24_2", + "name": "Two-OneChan-SnkAse-Lc3_48_4-Two-OneChan-SrcAse-Lc3_24_2", "subconfigurations": [ { - "device_cnt": 2, "ase_cnt": 2, "direction": "SINK", "codec_id": { @@ -5924,18 +4691,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -5954,10 +4709,10 @@ ] } } - ] + ], + "ase_channel_cnt": 1 }, { - "device_cnt": 2, "ase_cnt": 2, "direction": "SOURCE", "codec_id": { @@ -5985,18 +4740,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -6015,15 +4758,15 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_16_2", + "name": "Two-OneChan-SnkAse-Lc3_48_4-Two-OneChan-SrcAse-Lc3_16_2", "subconfigurations": [ { - "device_cnt": 2, "ase_cnt": 2, "direction": "SINK", "codec_id": { @@ -6051,18 +4794,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -6081,10 +4812,10 @@ ] } } - ] + ], + "ase_channel_cnt": 1 }, { - "device_cnt": 2, "ase_cnt": 2, "direction": "SOURCE", "codec_id": { @@ -6112,18 +4843,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -6142,15 +4861,15 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_32_2", + "name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2", "subconfigurations": [ { - "device_cnt": 2, "ase_cnt": 2, "direction": "SINK", "codec_id": { @@ -6178,18 +4897,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -6208,10 +4915,10 @@ ] } } - ] + ], + "ase_channel_cnt": 1 }, { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -6239,18 +4946,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -6269,15 +4964,15 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_24_2", + "name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2", "subconfigurations": [ { - "device_cnt": 2, "ase_cnt": 2, "direction": "SINK", "codec_id": { @@ -6305,18 +5000,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -6335,10 +5018,10 @@ ] } } - ] + ], + "ase_channel_cnt": 1 }, { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -6366,18 +5049,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -6396,15 +5067,15 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_16_2", + "name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2", "subconfigurations": [ { - "device_cnt": 2, "ase_cnt": 2, "direction": "SINK", "codec_id": { @@ -6432,18 +5103,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -6462,10 +5121,10 @@ ] } } - ] + ], + "ase_channel_cnt": 1 }, { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -6493,18 +5152,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -6523,18 +5170,17 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_32_2", + "name": "One-TwoChan-SnkAse-Lc3_48_4-One-TwoChan-SrcAse-Lc3_32_2", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -6560,18 +5206,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -6590,13 +5224,12 @@ ] } } - ] + ], + "ase_channel_cnt": 2 }, { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -6622,18 +5255,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -6652,18 +5273,17 @@ ] } } - ] + ], + "ase_channel_cnt": 2 } ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_24_2", + "name": "One-TwoChan-SnkAse-Lc3_48_4-One-TwoChan-SrcAse-Lc3_24_2", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -6689,18 +5309,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -6719,13 +5327,12 @@ ] } } - ] + ], + "ase_channel_cnt": 2 }, { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -6751,18 +5358,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -6781,18 +5376,17 @@ ] } } - ] + ], + "ase_channel_cnt": 2 } ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_16_2", + "name": "One-TwoChan-SnkAse-Lc3_48_4-One-TwoChan-SrcAse-Lc3_16_2", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -6818,18 +5412,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -6848,13 +5430,12 @@ ] } } - ] + ], + "ase_channel_cnt": 2 }, { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -6880,18 +5461,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -6910,18 +5479,17 @@ ] } } - ] + ], + "ase_channel_cnt": 2 } ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_32_2", + "name": "One-TwoChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -6947,18 +5515,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -6977,10 +5533,10 @@ ] } } - ] + ], + "ase_channel_cnt": 2 }, { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -7008,18 +5564,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -7038,18 +5582,17 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_24_2", + "name": "One-TwoChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -7075,18 +5618,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -7105,10 +5636,10 @@ ] } } - ] + ], + "ase_channel_cnt": 2 }, { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -7136,18 +5667,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -7166,18 +5685,17 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_16_2", + "name": "One-TwoChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -7203,18 +5721,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -7233,10 +5739,10 @@ ] } } - ] + ], + "ase_channel_cnt": 2 }, { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -7264,18 +5770,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -7294,274 +5788,17 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_32_2", + "name": "One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2", "subconfigurations": [ { - "device_cnt": 1, - "ase_cnt": 2, - "direction": "SINK", - "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 8 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 1 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 120, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - }, - { - "device_cnt": 1, - "ase_cnt": 1, - "direction": "SOURCE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 6 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 1 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 80, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - } - ] - }, - { - "name": "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_24_2", - "subconfigurations": [ - { - "device_cnt": 1, - "ase_cnt": 2, - "direction": "SINK", - "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 8 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 1 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 120, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - }, - { - "device_cnt": 1, "ase_cnt": 1, - "direction": "SOURCE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 5 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 1 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 60, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - } - ] - }, - { - "name": "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_16_2", - "subconfigurations": [ - { - "device_cnt": 1, - "ase_cnt": 2, "direction": "SINK", - "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -7587,18 +5824,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -7617,137 +5842,10 @@ ] } } - ] + ], + "ase_channel_cnt": 1 }, { - "device_cnt": 1, - "ase_cnt": 1, - "direction": "SOURCE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 3 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 1 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 40, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - } - ] - }, - { - "name": "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_32_2", - "subconfigurations": [ - { - "device_cnt": 1, - "ase_cnt": 1, - "direction": "SINK", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 8 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 1 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 120, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - }, - { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -7775,18 +5873,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -7805,15 +5891,15 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_24_2", + "name": "One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", "codec_id": { @@ -7841,18 +5927,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -7871,10 +5945,10 @@ ] } } - ] + ], + "ase_channel_cnt": 1 }, { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -7902,18 +5976,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -7932,15 +5994,15 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_16_2", + "name": "One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", "codec_id": { @@ -7968,18 +6030,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -7998,10 +6048,10 @@ ] } } - ] + ], + "ase_channel_cnt": 1 }, { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -8029,18 +6079,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -8059,18 +6097,17 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_1", + "name": "Two-TwoChan-SnkAse-Lc3_48_1-Two-TwoChan-SrcAse-Lc3_48_1", "subconfigurations": [ { - "device_cnt": 2, "ase_cnt": 2, "direction": "SOURCE", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -8096,18 +6133,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -8126,13 +6151,12 @@ ] } } - ] + ], + "ase_channel_cnt": 2 }, { - "device_cnt": 2, "ase_cnt": 2, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -8158,18 +6182,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -8188,18 +6200,17 @@ ] } } - ] + ], + "ase_channel_cnt": 2 } ] }, { - "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_2", + "name": "Two-TwoChan-SnkAse-Lc3_48_2-Two-TwoChan-SrcAse-Lc3_48_2", "subconfigurations": [ { - "device_cnt": 2, "ase_cnt": 2, "direction": "SOURCE", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -8225,18 +6236,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -8255,13 +6254,12 @@ ] } } - ] + ], + "ase_channel_cnt": 2 }, { - "device_cnt": 2, "ase_cnt": 2, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -8287,18 +6285,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -8317,7 +6303,8 @@ ] } } - ] + ], + "ase_channel_cnt": 2 } ] }, @@ -8325,10 +6312,8 @@ "name": "VND_SingleDev_TwoChanStereoSrc_48khz_100octs_1", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -8354,18 +6339,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -8384,7 +6357,8 @@ ] } } - ] + ], + "ase_channel_cnt": 2 } ] }, @@ -8392,10 +6366,8 @@ "name": "VND_SingleDev_TwoChanStereoSnk_OneChanStereoSrc_32khz_60octs_1", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -8421,18 +6393,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -8451,10 +6411,10 @@ ] } } - ] + ], + "ase_channel_cnt": 2 }, { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -8482,18 +6442,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -8512,7 +6460,8 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, @@ -8520,10 +6469,8 @@ "name": "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_TwoChanStereoSrc_16khz_30octs_1", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -8549,18 +6496,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -8579,13 +6514,12 @@ ] } } - ] + ], + "ase_channel_cnt": 2 }, { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -8611,18 +6545,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -8641,18 +6563,17 @@ ] } } - ] + ], + "ase_channel_cnt": 2 } ] }, { - "name": "DualDev_OneChanStereoSnk_24_2", + "name": "Two-OneChan-SnkAse-Lc3_24_2", "subconfigurations": [ { - "device_cnt": 2, "ase_cnt": 2, "direction": "SINK", - "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -8678,18 +6599,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -8708,18 +6617,17 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "DualDev_OneChanStereoSnk_24_1", + "name": "Two-OneChan-SnkAse-Lc3_24_1", "subconfigurations": [ { - "device_cnt": 2, "ase_cnt": 2, "direction": "SINK", - "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -8745,18 +6653,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -8775,152 +6671,17 @@ ] } } - ] - } - ] - }, - { - "name": "SingleDev_OneChanStereoSnk_24_2", - "subconfigurations": [ - { - "device_cnt": 1, - "ase_cnt": 2, - "direction": "SINK", - "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 5 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 1 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 60, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_OneChanStereoSnk_24_1", + "name": "One-TwoChan-SnkAse-Lc3_24_2", "subconfigurations": [ { - "device_cnt": 1, - "ase_cnt": 2, - "direction": "SINK", - "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 5 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 0 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 45, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - } - ] - }, - { - "name": "SingleDev_TwoChanStereoSnk_24_2", - "subconfigurations": [ - { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -8946,18 +6707,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -8976,18 +6725,17 @@ ] } } - ] + ], + "ase_channel_cnt": 2 } ] }, { - "name": "SingleDev_TwoChanStereoSnk_24_1", + "name": "One-TwoChan-SnkAse-Lc3_24_1", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -9013,18 +6761,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -9043,18 +6779,17 @@ ] } } - ] + ], + "ase_channel_cnt": 2 } ] }, { - "name": "SingleDev_OneChanMonoSnk_24_2", + "name": "One-OneChan-SnkAse-Lc3_24_2", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -9080,18 +6815,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -9110,15 +6833,15 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2", + "name": "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2", "subconfigurations": [ { - "device_cnt": 2, "ase_cnt": 2, "direction": "SINK", "codec_id": { @@ -9146,18 +6869,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -9176,10 +6887,10 @@ ] } } - ] + ], + "ase_channel_cnt": 1 }, { - "device_cnt": 2, "ase_cnt": 2, "direction": "SOURCE", "codec_id": { @@ -9207,18 +6918,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -9237,15 +6936,15 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_32_2", + "name": "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2", "subconfigurations": [ { - "device_cnt": 2, "ase_cnt": 2, "direction": "SINK", "codec_id": { @@ -9273,18 +6972,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -9303,10 +6990,10 @@ ] } } - ] + ], + "ase_channel_cnt": 1 }, { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -9334,18 +7021,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -9364,18 +7039,17 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2", + "name": "One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -9401,18 +7075,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -9431,10 +7093,10 @@ ] } } - ] + ], + "ase_channel_cnt": 2 }, { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -9462,18 +7124,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -9492,143 +7142,15 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2", + "name": "One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2", "subconfigurations": [ { - "device_cnt": 1, - "ase_cnt": 2, - "direction": "SINK", - "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 6 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 1 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 80, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - }, - { - "device_cnt": 1, - "ase_cnt": 1, - "direction": "SOURCE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 6 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 1 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 80, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - } - ] - }, - { - "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2", - "subconfigurations": [ - { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", "codec_id": { @@ -9656,18 +7178,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -9686,10 +7196,10 @@ ] } } - ] + ], + "ase_channel_cnt": 1 }, { - "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", "codec_id": { @@ -9717,18 +7227,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -9747,18 +7245,17 @@ ] } } - ] + ], + "ase_channel_cnt": 1 } ] }, { - "name": "SingleDev_TwoChanStereoSnk_32_2", + "name": "One-TwoChan-SnkAse-Lc3_32_2", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -9784,18 +7281,6 @@ } }, { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { "name": "octets_per_codec_frame", "type": 4, "compound_value": { @@ -9814,85 +7299,17 @@ ] } } - ] + ], + "ase_channel_cnt": 2 } ] }, { - "name": "SingleDev_TwoChanStereoSnk_32_1", + "name": "One-TwoChan-SnkAse-Lc3_32_1", "subconfigurations": [ { - "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 6 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 0 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 60, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - } - ] - }, - { - "name": "SingleDev_OneChanStereoSnk_32_2", - "subconfigurations": [ - { - "device_cnt": 1, - "ase_cnt": 2, - "direction": "SINK", - "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -9913,85 +7330,6 @@ "type": 2, "compound_value": { "value": [ - 1 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 80, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - } - ] - }, - { - "name": "SingleDev_OneChanStereoSnk_32_1", - "subconfigurations": [ - { - "device_cnt": 1, - "ase_cnt": 2, - "direction": "SINK", - "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 6 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 0 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, 0 ] } @@ -10015,7 +7353,8 @@ ] } } - ] + ], + "ase_channel_cnt": 2 } ] } @@ -10149,6 +7488,5 @@ "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 b84ff72a98..b29dba516e 100644 --- a/system/bta/le_audio/audio_set_scenarios.json +++ b/system/bta/le_audio/audio_set_scenarios.json @@ -8,243 +8,206 @@ { "name": "Conversational", "configurations": [ - "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_1", - "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_Low_Latency", - "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_Low_Latency", - "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_1", - "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_2", - "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_Low_Latency", - "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_1", - "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_2", - "DualDev_OneChanStereoSnk_OneChanMonoSrc_32_2_1", - "DualDev_OneChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency", - "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency", - "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2_1", - "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency", - "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1_1", - "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_Low_Latency", - "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_1", - "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_Low_Latency", - "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_1", - "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_2", - "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_Low_Latency", - "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_1", - "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_2", - "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency", - "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_1", - "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency", - "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_1", - "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency", - "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_1", - "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2_1", - "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency", - "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency", - "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_1", - "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency", - "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_1", - "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_Low_Latency", - "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_1", - "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_Low_Latency", - "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_1", - "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_Low_Latency", - "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_1", - "DualDev_OneChanMonoSrc_16_2_Balanced_Reliability", - "SingleDev_OneChanStereoSrc_16_2_Balanced_Reliability", - "SingleDev_OneChanMonoSrc_48_4_Balanced_Reliability", - "SingleDev_OneChanMonoSrc_48_2_Balanced_Reliability", - "SingleDev_OneChanMonoSrc_48_3_Balanced_Reliability", - "SingleDev_OneChanMonoSrc_48_1_Balanced_Reliability", - "SingleDev_OneChanMonoSrc_32_2_Balanced_Reliability", - "SingleDev_OneChanMonoSrc_32_1_Balanced_Reliability", - "SingleDev_OneChanMonoSrc_24_2_Balanced_Reliability", - "SingleDev_OneChanMonoSrc_24_1_Balanced_Reliability", - "SingleDev_OneChanMonoSrc_16_2_Balanced_Reliability", - "SingleDev_OneChanMonoSrc_16_1_Balanced_Reliability", + "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_1", + "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_Low_Latency", + "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_Low_Latency", + "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_1", + "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_2", + "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_Low_Latency", + "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_1", + "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_2", + "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1", + "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency", + "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency", + "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1", + "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency", + "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1", + "One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2_Low_Latency", + "One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2_1", + "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_Low_Latency", + "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_1", + "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_2", + "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_Low_Latency", + "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_1", + "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_2", + "One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency", + "One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1", + "One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency", + "One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1", + "One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency", + "One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1", + "One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency", + "One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1", + "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency", + "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1", + "One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency", + "One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1", + "Two-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability", + "One-OneChan-SrcAse-Lc3_48_4_Balanced_Reliability", + "One-OneChan-SrcAse-Lc3_48_2_Balanced_Reliability", + "One-OneChan-SrcAse-Lc3_48_3_Balanced_Reliability", + "One-OneChan-SrcAse-Lc3_48_1_Balanced_Reliability", + "One-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability", + "One-OneChan-SrcAse-Lc3_32_1_Balanced_Reliability", + "One-OneChan-SrcAse-Lc3_24_2_Balanced_Reliability", + "One-OneChan-SrcAse-Lc3_24_1_Balanced_Reliability", + "One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability", + "One-OneChan-SrcAse-Lc3_16_1_Balanced_Reliability", "VND_SingleDev_TwoChanStereoSnk_OneChanStereoSrc_32khz_60oct_R3_L22_1", - "DualDev_OneChanMonoSnk_16_2_Balanced_Reliability", - "SingleDev_OneChanStereoSnk_16_2_Balanced_Reliability", - "SingleDev_TwoChanStereoSnk_16_2_Balanced_Reliability", - "SingleDev_OneChanMonoSnk_16_2_Balanced_Reliability" + "Two-OneChan-SnkAse-Lc3_16_2_Balanced_Reliability", + "One-TwoChan-SnkAse-Lc3_16_2_Balanced_Reliability", + "One-OneChan-SnkAse-Lc3_16_2_Balanced_Reliability" ] }, { "name": "Media", "configurations": [ - "DualDev_OneChanStereoSnk_48_4_High_Reliability", - "DualDev_OneChanStereoSnk_48_4_2", - "DualDev_OneChanStereoSnk_48_2_High_Reliability", - "DualDev_OneChanStereoSnk_48_2_2", - "DualDev_OneChanStereoSnk_48_3_High_Reliability", - "DualDev_OneChanStereoSnk_48_3_2", - "DualDev_OneChanStereoSnk_48_1_High_Reliability", - "DualDev_OneChanStereoSnk_48_1_2", - "DualDev_OneChanStereoSnk_24_2_Balanced_Reliability", - "DualDev_OneChanStereoSnk_24_2_2", - "DualDev_OneChanStereoSnk_16_2_Balanced_Reliability", - "DualDev_OneChanStereoSnk_16_2_2", - "DualDev_OneChanStereoSnk_16_1_Balanced_Reliability", - "DualDev_OneChanStereoSnk_16_1_2", - "SingleDev_OneChanStereoSnk_48_4_High_Reliability", - "SingleDev_OneChanStereoSnk_48_4_2", - "SingleDev_OneChanStereoSnk_48_2_High_Reliability", - "SingleDev_OneChanStereoSnk_48_2_2", - "SingleDev_OneChanStereoSnk_48_3_High_Reliability", - "SingleDev_OneChanStereoSnk_48_3_2", - "SingleDev_OneChanStereoSnk_48_1_High_Reliability", - "SingleDev_OneChanStereoSnk_48_1_2", - "SingleDev_OneChanStereoSnk_24_2_Balanced_Reliability", - "SingleDev_OneChanStereoSnk_24_2_2", - "SingleDev_OneChanStereoSnk_16_2_Balanced_Reliability", - "SingleDev_OneChanStereoSnk_16_2_2", - "SingleDev_OneChanStereoSnk_16_1_Balanced_Reliability", - "SingleDev_OneChanStereoSnk_16_1_2", - "SingleDev_TwoChanStereoSnk_48_4_High_Reliability", - "SingleDev_TwoChanStereoSnk_48_4_2", - "SingleDev_TwoChanStereoSnk_48_4_High_Reliability", - "SingleDev_TwoChanStereoSnk_48_4_2", - "SingleDev_TwoChanStereoSnk_48_2_High_Reliability", - "SingleDev_TwoChanStereoSnk_48_2_2", - "SingleDev_TwoChanStereoSnk_48_3_High_Reliability", - "SingleDev_TwoChanStereoSnk_48_3_2", - "SingleDev_TwoChanStereoSnk_48_1_High_Reliability", - "SingleDev_TwoChanStereoSnk_48_1_2", - "SingleDev_TwoChanStereoSnk_24_2_Balanced_Reliability", - "SingleDev_TwoChanStereoSnk_24_2_2", - "SingleDev_TwoChanStereoSnk_16_2_Balanced_Reliability", - "SingleDev_TwoChanStereoSnk_16_2_2", - "SingleDev_TwoChanStereoSnk_16_1_Balanced_Reliability", - "SingleDev_TwoChanStereoSnk_16_1_2", - "SingleDev_OneChanMonoSnk_48_4_High_Reliability", - "SingleDev_OneChanMonoSnk_48_4_2", - "SingleDev_OneChanMonoSnk_48_2_High_Reliability", - "SingleDev_OneChanMonoSnk_48_2_2", - "SingleDev_OneChanMonoSnk_48_3_High_Reliability", - "SingleDev_OneChanMonoSnk_48_3_2", - "SingleDev_OneChanMonoSnk_48_1_High_Reliability", - "SingleDev_OneChanMonoSnk_48_1_2", - "SingleDev_OneChanMonoSnk_32_2_Balanced_Reliability", - "SingleDev_OneChanMonoSnk_32_2_2", - "SingleDev_OneChanMonoSnk_32_1_Balanced_Reliability", - "SingleDev_OneChanMonoSnk_32_1_2", - "SingleDev_OneChanMonoSnk_24_2_Balanced_Reliability", - "SingleDev_OneChanMonoSnk_24_2_2", - "SingleDev_OneChanMonoSnk_16_2_Balanced_Reliability", - "SingleDev_OneChanMonoSnk_16_2_2", - "SingleDev_OneChanMonoSnk_16_1_Balanced_Reliability", - "SingleDev_OneChanMonoSnk_16_1_2", + "Two-OneChan-SnkAse-Lc3_48_4_High_Reliability", + "Two-OneChan-SnkAse-Lc3_48_4_2", + "Two-OneChan-SnkAse-Lc3_48_2_High_Reliability", + "Two-OneChan-SnkAse-Lc3_48_2_2", + "Two-OneChan-SnkAse-Lc3_48_3_High_Reliability", + "Two-OneChan-SnkAse-Lc3_48_3_2", + "Two-OneChan-SnkAse-Lc3_48_1_High_Reliability", + "Two-OneChan-SnkAse-Lc3_48_1_2", + "Two-OneChan-SnkAse-Lc3_24_2_Balanced_Reliability", + "Two-OneChan-SnkAse-Lc3_24_2_2", + "Two-OneChan-SnkAse-Lc3_16_2_Balanced_Reliability", + "Two-OneChan-SnkAse-Lc3_16_2_2", + "Two-OneChan-SnkAse-Lc3_16_1_Balanced_Reliability", + "Two-OneChan-SnkAse-Lc3_16_1_2", + "One-TwoChan-SnkAse-Lc3_48_4_High_Reliability", + "One-TwoChan-SnkAse-Lc3_48_4_2", + "One-TwoChan-SnkAse-Lc3_48_2_High_Reliability", + "One-TwoChan-SnkAse-Lc3_48_2_2", + "One-TwoChan-SnkAse-Lc3_48_3_High_Reliability", + "One-TwoChan-SnkAse-Lc3_48_3_2", + "One-TwoChan-SnkAse-Lc3_48_1_High_Reliability", + "One-TwoChan-SnkAse-Lc3_48_1_2", + "One-TwoChan-SnkAse-Lc3_24_2_Balanced_Reliability", + "One-TwoChan-SnkAse-Lc3_24_2_2", + "One-TwoChan-SnkAse-Lc3_16_2_Balanced_Reliability", + "One-TwoChan-SnkAse-Lc3_16_2_2", + "One-TwoChan-SnkAse-Lc3_16_1_Balanced_Reliability", + "One-TwoChan-SnkAse-Lc3_16_1_2", + "One-OneChan-SnkAse-Lc3_48_4_High_Reliability", + "One-OneChan-SnkAse-Lc3_48_4_2", + "One-OneChan-SnkAse-Lc3_48_2_High_Reliability", + "One-OneChan-SnkAse-Lc3_48_2_2", + "One-OneChan-SnkAse-Lc3_48_3_High_Reliability", + "One-OneChan-SnkAse-Lc3_48_3_2", + "One-OneChan-SnkAse-Lc3_48_1_High_Reliability", + "One-OneChan-SnkAse-Lc3_48_1_2", + "One-OneChan-SnkAse-Lc3_32_2_Balanced_Reliability", + "One-OneChan-SnkAse-Lc3_32_2_2", + "One-OneChan-SnkAse-Lc3_32_1_Balanced_Reliability", + "One-OneChan-SnkAse-Lc3_32_1_2", + "One-OneChan-SnkAse-Lc3_24_2_Balanced_Reliability", + "One-OneChan-SnkAse-Lc3_24_2_2", + "One-OneChan-SnkAse-Lc3_16_2_Balanced_Reliability", + "One-OneChan-SnkAse-Lc3_16_2_2", + "One-OneChan-SnkAse-Lc3_16_1_Balanced_Reliability", + "One-OneChan-SnkAse-Lc3_16_1_2", "VND_DualDev_OneChanStereoSnk_48khz_100octs_High_Reliability_1", "VND_DualDev_OneChanStereoSnk_48khz_100octs_R15_L70_1", "VND_SingleDev_TwoChanStereoSnk_48khz_100octs_High_Reliability_1", "VND_SingleDev_TwoChanStereoSnk_48khz_100octs_R15_L70_1", "VND_SingleDev_OneChanStereoSnk_48khz_100octs_High_Reliability_1", "VND_SingleDev_OneChanStereoSnk_48khz_100octs_R15_L70_1", - "DualDev_OneChanMonoSrc_16_2_Balanced_Reliability", - "SingleDev_OneChanStereoSrc_16_2_Balanced_Reliability", - "SingleDev_OneChanMonoSrc_16_2_Balanced_Reliability" + "Two-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability", + "One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability" ] }, { "name": "Game", "configurations": [ - "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_1", - "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_Low_Latency", - "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_Low_Latency", - "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_Low_Latency", - "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_2_Low_Latency", - "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_1_Low_Latency", - "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_Low_Latency", - "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_Low_Latency", - "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_Low_Latency", - "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency", - "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency", - "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency", + "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_1", + "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_Low_Latency", + "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_Low_Latency", + "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_Low_Latency", + "Two-TwoChan-SnkAse-Lc3_48_2-Two-TwoChan-SrcAse-Lc3_48_2_Low_Latency", + "Two-TwoChan-SnkAse-Lc3_48_1-Two-TwoChan-SrcAse-Lc3_48_1_Low_Latency", + "One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2_Low_Latency", + "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_Low_Latency", + "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_Low_Latency", + "One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency", + "One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency", + "One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency", "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_TwoChanStereoSrc_16khz_30octs_Balanced_Reliability_1", "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_R5_L12_TwoChanStereoSrc_16khz_30octs_R3_L12_1", "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_High_Reliability_1", "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_R5_L12_1", - "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2_1", - "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency", - "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency", - "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency", - "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_Low_Latency", - "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_Low_Latency", - "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_Low_Latency", - "DualDev_OneChanStereoSnk_48_2_Low_Latency", - "DualDev_OneChanStereoSnk_48_3_Low_Latency", - "DualDev_OneChanStereoSnk_48_1_Low_Latency", - "DualDev_OneChanStereoSnk_32_2_Low_Latency", - "DualDev_OneChanStereoSnk_32_1_Low_Latency", - "DualDev_OneChanStereoSnk_24_2_Low_Latency", - "DualDev_OneChanStereoSnk_24_1_Low_Latency", - "DualDev_OneChanStereoSnk_16_2_Low_Latency", - "DualDev_OneChanStereoSnk_16_1_Low_Latency", - "SingleDev_TwoChanStereoSnk_48_2_Low_Latency", - "SingleDev_TwoChanStereoSnk_48_3_Low_Latency", - "SingleDev_TwoChanStereoSnk_48_1_Low_Latency", - "SingleDev_TwoChanStereoSnk_32_2_Low_Latency", - "SingleDev_TwoChanStereoSnk_32_1_Low_Latency", - "SingleDev_TwoChanStereoSnk_24_2_Low_Latency", - "SingleDev_TwoChanStereoSnk_24_1_Low_Latency", - "SingleDev_TwoChanStereoSnk_16_2_Low_Latency", - "SingleDev_TwoChanStereoSnk_16_1_Low_Latency", - "SingleDev_OneChanStereoSnk_48_2_Low_Latency", - "SingleDev_OneChanStereoSnk_48_3_Low_Latency", - "SingleDev_OneChanStereoSnk_48_1_Low_Latency", - "SingleDev_OneChanStereoSnk_32_2_Low_Latency", - "SingleDev_OneChanStereoSnk_32_1_Low_Latency", - "SingleDev_OneChanStereoSnk_24_2_Low_Latency", - "SingleDev_OneChanStereoSnk_24_1_Low_Latency", - "SingleDev_OneChanStereoSnk_16_2_Low_Latency", - "SingleDev_OneChanStereoSnk_16_1_Low_Latency" + "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1", + "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency", + "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency", + "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency", + "One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency", + "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency", + "One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency", + "Two-OneChan-SnkAse-Lc3_48_2_Low_Latency", + "Two-OneChan-SnkAse-Lc3_48_3_Low_Latency", + "Two-OneChan-SnkAse-Lc3_48_1_Low_Latency", + "Two-OneChan-SnkAse-Lc3_32_2_Low_Latency", + "Two-OneChan-SnkAse-Lc3_32_1_Low_Latency", + "Two-OneChan-SnkAse-Lc3_24_2_Low_Latency", + "Two-OneChan-SnkAse-Lc3_24_1_Low_Latency", + "Two-OneChan-SnkAse-Lc3_16_2_Low_Latency", + "Two-OneChan-SnkAse-Lc3_16_1_Low_Latency", + "One-TwoChan-SnkAse-Lc3_48_2_Low_Latency", + "One-TwoChan-SnkAse-Lc3_48_3_Low_Latency", + "One-TwoChan-SnkAse-Lc3_48_1_Low_Latency", + "One-TwoChan-SnkAse-Lc3_32_2_Low_Latency", + "One-TwoChan-SnkAse-Lc3_32_1_Low_Latency", + "One-TwoChan-SnkAse-Lc3_24_2_Low_Latency", + "One-TwoChan-SnkAse-Lc3_24_1_Low_Latency", + "One-TwoChan-SnkAse-Lc3_16_2_Low_Latency", + "One-TwoChan-SnkAse-Lc3_16_1_Low_Latency" ] }, { "name": "VoiceAssistants", "configurations": [ - "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_1", - "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_Low_Latency", - "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_Low_Latency", - "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_1", - "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_Low_Latency", - "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_1", - "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_2_Balanced_Reliability", - "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_1_Balanced_Reliability", - "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_Low_Latency", - "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_1", - "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_Low_Latency", - "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_1", - "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_Low_Latency", - "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_1", - "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency", - "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_1", - "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency", - "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_1", - "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency", - "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_1", - "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_Low_Latency", - "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_1", - "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_Low_Latency", - "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_1", - "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_Low_Latency", - "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_1", - "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_16_2_Balanced_Reliability", - "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_24_2_Balanced_Reliability", - "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_32_2_Balanced_Reliability", - "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability", - "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability", - "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability", - "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_16_2_Balanced_Reliability", - "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_24_2_Balanced_Reliability", - "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_32_2_Balanced_Reliability", - "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability", - "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability", - "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability", - "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability", - "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability", - "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability", - "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability", - "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability", - "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability" + "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_1", + "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_Low_Latency", + "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_Low_Latency", + "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_1", + "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_Low_Latency", + "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_1", + "Two-TwoChan-SnkAse-Lc3_48_2-Two-TwoChan-SrcAse-Lc3_48_2_Balanced_Reliability", + "Two-TwoChan-SnkAse-Lc3_48_1-Two-TwoChan-SrcAse-Lc3_48_1_Balanced_Reliability", + "One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2_Low_Latency", + "One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2_1", + "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_Low_Latency", + "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_1", + "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_Low_Latency", + "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_1", + "One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency", + "One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1", + "One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency", + "One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1", + "One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency", + "One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1", + "One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency", + "One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1", + "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency", + "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1", + "One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency", + "One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1", + "Two-OneChan-SnkAse-Lc3_48_4-Two-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability", + "Two-OneChan-SnkAse-Lc3_48_4-Two-OneChan-SrcAse-Lc3_24_2_Balanced_Reliability", + "Two-OneChan-SnkAse-Lc3_48_4-Two-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability", + "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability", + "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2_Balanced_Reliability", + "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability", + "One-TwoChan-SnkAse-Lc3_48_4-One-TwoChan-SrcAse-Lc3_16_2_Balanced_Reliability", + "One-TwoChan-SnkAse-Lc3_48_4-One-TwoChan-SrcAse-Lc3_24_2_Balanced_Reliability", + "One-TwoChan-SnkAse-Lc3_48_4-One-TwoChan-SrcAse-Lc3_32_2_Balanced_Reliability", + "One-TwoChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability", + "One-TwoChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2_Balanced_Reliability", + "One-TwoChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability", + "One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability", + "One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2_Balanced_Reliability", + "One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability" ] }, { @@ -252,45 +215,45 @@ "configurations": [ "VND_SingleDev_TwoChanStereoSrc_48khz_100octs_Balanced_Reliability_1", "VND_SingleDev_TwoChanStereoSrc_48khz_100octs_R11_L40_1", - "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_1", - "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_Low_Latency", - "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_Low_Latency", - "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_1", - "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_Low_Latency", - "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_1", - "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_2_Balanced_Reliability", - "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_1_Balanced_Reliability", - "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_Low_Latency", - "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_1", - "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_Low_Latency", - "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_1", - "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_Low_Latency", - "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_1", - "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency", - "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_1", - "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency", - "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_1", - "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency", - "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_1", - "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2_1", - "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency", - "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency", - "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_1", - "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency", - "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_1", - "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_Low_Latency", - "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_1", - "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_Low_Latency", - "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_1", - "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_Low_Latency", - "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_1", - "SingleDev_OneChanMonoSrc_48_2_Balanced_Reliability", - "SingleDev_OneChanMonoSrc_48_1_Balanced_Reliability", - "SingleDev_OneChanMonoSrc_32_2_Balanced_Reliability", - "SingleDev_OneChanMonoSrc_32_1_Balanced_Reliability", - "SingleDev_OneChanMonoSrc_16_2_Balanced_Reliability", - "SingleDev_OneChanMonoSrc_16_1_Balanced_Reliability" + "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_1", + "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_Low_Latency", + "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_Low_Latency", + "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_1", + "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_Low_Latency", + "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_1", + "Two-TwoChan-SnkAse-Lc3_48_2-Two-TwoChan-SrcAse-Lc3_48_2_Balanced_Reliability", + "Two-TwoChan-SnkAse-Lc3_48_1-Two-TwoChan-SrcAse-Lc3_48_1_Balanced_Reliability", + "One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2_Low_Latency", + "One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2_1", + "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_Low_Latency", + "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_1", + "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_Low_Latency", + "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_1", + "One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency", + "One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1", + "One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency", + "One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1", + "One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency", + "One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1", + "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1", + "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency", + "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency", + "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1", + "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency", + "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1", + "One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency", + "One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1", + "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency", + "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1", + "One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency", + "One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1", + "One-OneChan-SrcAse-Lc3_48_2_Balanced_Reliability", + "One-OneChan-SrcAse-Lc3_48_1_Balanced_Reliability", + "One-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability", + "One-OneChan-SrcAse-Lc3_32_1_Balanced_Reliability", + "One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability", + "One-OneChan-SrcAse-Lc3_16_1_Balanced_Reliability" ] } ] -} +}
\ No newline at end of file diff --git a/system/bta/le_audio/broadcaster/broadcaster_types.h b/system/bta/le_audio/broadcaster/broadcaster_types.h index e4754bcf7b..28e0fb5286 100644 --- a/system/bta/le_audio/broadcaster/broadcaster_types.h +++ b/system/bta/le_audio/broadcaster/broadcaster_types.h @@ -194,6 +194,12 @@ struct BroadcastSubgroupCodecConfig { return 0; } + /* Note: this should be used for tests only */ + const std::vector<BroadcastSubgroupBisCodecConfig>& GetBisCodecConfigs() + const { + return bis_codec_configs_; + } + std::optional<types::LeAudioLtvMap> GetBisCodecSpecData( uint8_t bis_idx) const { if (bis_codec_configs_.empty()) return std::nullopt; diff --git a/system/bta/le_audio/broadcaster/state_machine.cc b/system/bta/le_audio/broadcaster/state_machine.cc index 1353bb0260..20b32fb8d2 100644 --- a/system/bta/le_audio/broadcaster/state_machine.cc +++ b/system/bta/le_audio/broadcaster/state_machine.cc @@ -161,12 +161,6 @@ class BroadcastStateMachineImpl : public BroadcastStateMachine { return; } - /* Ext. advertisings are already on */ - SetState(State::CONFIGURED); - - callbacks_->OnStateMachineCreateStatus(GetBroadcastId(), true); - callbacks_->OnStateMachineEvent(GetBroadcastId(), State::CONFIGURED); - advertiser_if_->GetOwnAddress( advertising_sid, base::Bind(&BroadcastStateMachineImpl::OnAddressResponse, @@ -175,7 +169,7 @@ class BroadcastStateMachineImpl : public BroadcastStateMachine { void OnEnableAnnouncement(bool enable, uint8_t status) { log::info("operation={}, broadcast_id={}, status={}", - (enable ? "enable" : "disable"), GetBroadcastId(), status); + enable ? "enable" : "disable", GetBroadcastId(), status); if (status == bluetooth::hci::AdvertisingCallback::AdvertisingStatus::SUCCESS) { @@ -327,6 +321,12 @@ class BroadcastStateMachineImpl : public BroadcastStateMachine { log::info("own address={}, type={}", addr, addr_type); addr_ = addr; addr_type_ = addr_type; + + /* Ext. advertisings are already on */ + SetState(State::CONFIGURED); + + callbacks_->OnStateMachineCreateStatus(GetBroadcastId(), true); + callbacks_->OnStateMachineEvent(GetBroadcastId(), State::CONFIGURED); } void CreateBroadcastAnnouncement( @@ -337,7 +337,7 @@ class BroadcastStateMachineImpl : public BroadcastStateMachine { const bluetooth::le_audio::BasicAudioAnnouncementData& announcement, uint8_t streaming_phy) { log::info("is_public={}, broadcast_name={}, public_features={}", - (is_public ? "public" : "non-public"), broadcast_name, + is_public ? "public" : "non-public", broadcast_name, public_announcement.features); if (advertiser_if_ != nullptr) { AdvertiseParameters adv_params; diff --git a/system/bta/le_audio/broadcaster/state_machine_test.cc b/system/bta/le_audio/broadcaster/state_machine_test.cc index f71bb31378..1375975be4 100644 --- a/system/bta/le_audio/broadcaster/state_machine_test.cc +++ b/system/bta/le_audio/broadcaster/state_machine_test.cc @@ -1015,6 +1015,31 @@ TEST_F(StateMachineTest, AnnouncementTest) { BroadcastStateMachine::kBroadcastAdvertisingType); } +TEST_F(StateMachineTest, GetMetadataBeforeGettingAddress) { + unsigned int broadcast_id = 0; + + BleAdvertiserInterface::GetAddressCallback cb; + + /* Address should be already known after notifying callback recipients */ + EXPECT_CALL( + *(sm_callbacks_.get()), + OnStateMachineEvent(_, BroadcastStateMachine::State::CONFIGURED, _)) + .WillOnce([this](uint32_t broadcast_id, + BroadcastStateMachine::State state, const void* data) { + RawAddress test_address; + + RawAddress::FromString("00:00:00:00:00:00", test_address); + ASSERT_NE(test_address, + this->broadcasts_[broadcast_id]->GetOwnAddress()); + }); + + broadcast_id = InstantiateStateMachine(); + ASSERT_NE(broadcast_id, 0u); + ASSERT_TRUE(pending_broadcasts_.empty()); + ASSERT_FALSE(broadcasts_.empty()); + ASSERT_TRUE(broadcasts_[broadcast_id]->GetBroadcastId() == broadcast_id); +} + } // namespace } // namespace broadcaster } // namespace bluetooth::le_audio diff --git a/system/bta/le_audio/client.cc b/system/bta/le_audio/client.cc index 4ed0534f9b..b3515ca39c 100644 --- a/system/bta/le_audio/client.cc +++ b/system/bta/le_audio/client.cc @@ -644,8 +644,8 @@ class LeAudioClientImpl : public LeAudioClient { /* TODO This part possible to remove as this is to handle adding device to * the group which is unknown and not connected. */ - log::info("leAudioDevice unknown , address: {} group: {}", address, - loghex(group_id)); + log::info("leAudioDevice unknown , address: {} group: 0x{:x}", address, + group_id); if (group_id == bluetooth::groups::kGroupUnknown) return; @@ -1325,7 +1325,7 @@ class LeAudioClientImpl : public LeAudioClient { } void SetEnableState(const RawAddress& address, bool enabled) override { - log::info("{}: {}", address, (enabled ? "enabled" : "disabled")); + log::info("{}: {}", address, enabled ? "enabled" : "disabled"); auto leAudioDevice = leAudioDevices_.FindByAddress(address); if (leAudioDevice == nullptr) { log::warn("{} is null", address); @@ -1933,7 +1933,7 @@ class LeAudioClientImpl : public LeAudioClient { bluetooth::le_audio::client_parser::tmap::ParseTmapRole( leAudioDevice->tmap_role_, len, value); } else { - log::error("Unknown attribute read: {}", loghex(hdl)); + log::error("Unknown attribute read: 0x{:x}", hdl); } } @@ -2173,7 +2173,7 @@ class LeAudioClientImpl : public LeAudioClient { if (leAudioDevice == NULL || (leAudioDevice->conn_id_ == GATT_INVALID_CONN_ID)) { log::warn("Skipping device which is {}", - (leAudioDevice ? " not connected by service." : " null")); + leAudioDevice ? " not connected by service." : " null"); return; } @@ -3053,7 +3053,7 @@ class LeAudioClientImpl : public LeAudioClient { std::vector<struct ase>::iterator ase_it; if (!leAudioDevice) { - log::error("unknown conn_id={}", loghex(conn_id)); + log::error("unknown conn_id=0x{:x}", conn_id); return; } @@ -3134,33 +3134,28 @@ class LeAudioClientImpl : public LeAudioClient { return; } - auto num_of_devices = - get_num_of_devices_in_configuration(stream_conf->conf.get()); - - if (num_of_devices < group->NumOfConnected()) { - for (auto direction : - {bluetooth::le_audio::types::kLeAudioDirectionSink, - bluetooth::le_audio::types::kLeAudioDirectionSource}) { - log::info("Looking for requirements: {} - {}", stream_conf->conf->name, - ((direction == 1 ? "snk" : "src"))); - const auto& pacs = - (direction == bluetooth::le_audio::types::kLeAudioDirectionSink) - ? leAudioDevice->snk_pacs_ - : leAudioDevice->src_pacs_; - for (const auto& ent : stream_conf->conf->confs.get(direction)) { - if (!bluetooth::le_audio::utils::GetConfigurationSupportedPac( - pacs, ent.codec)) { - log::info("Configuration is not supported by device %s", - ADDRESS_TO_LOGGABLE_CSTR(leAudioDevice->address_)); - - /* Reconfigure if newly connected member device cannot support - * current codec configuration */ - group->SetPendingConfiguration(); - groupStateMachine_->StopStream(group); - stream_setup_start_timestamp_ = - bluetooth::common::time_get_os_boottime_us(); - return; - } + for (auto direction : + {bluetooth::le_audio::types::kLeAudioDirectionSink, + bluetooth::le_audio::types::kLeAudioDirectionSource}) { + log::info("Looking for requirements: {} - {}", stream_conf->conf->name, + ((direction == 1 ? "snk" : "src"))); + const auto& pacs = + (direction == bluetooth::le_audio::types::kLeAudioDirectionSink) + ? leAudioDevice->snk_pacs_ + : leAudioDevice->src_pacs_; + for (const auto& ent : stream_conf->conf->confs.get(direction)) { + if (!bluetooth::le_audio::utils::GetConfigurationSupportedPac( + pacs, ent.codec)) { + log::info("Configuration is not supported by device {}", + leAudioDevice->address_); + + /* Reconfigure if newly connected member device cannot support + * current codec configuration */ + group->SetPendingConfiguration(); + groupStateMachine_->StopStream(group); + stream_setup_start_timestamp_ = + bluetooth::common::time_get_os_boottime_us(); + return; } } } @@ -3219,7 +3214,7 @@ class LeAudioClientImpl : public LeAudioClient { void SendAudioGroupCurrentCodecConfigChanged(LeAudioDeviceGroup* group) { // This shall be called when configuration changes - log::debug(" {} ", group->group_id_); + log::debug("{}", group->group_id_); auto audio_set_conf = group->GetConfiguration(configuration_context_type_); if (!audio_set_conf) { @@ -3264,8 +3259,8 @@ class LeAudioClientImpl : public LeAudioClient { bluetooth::le_audio::ConnectionStatus::SUCCESS); if (leAudioDevice->group_id_ == bluetooth::groups::kGroupUnknown) { - log::warn(" LeAudio device {} connected with no group", - ADDRESS_TO_LOGGABLE_CSTR(leAudioDevice->address_)); + log::warn("LeAudio device {} connected with no group", + leAudioDevice->address_); callbacks_->OnConnectionState(ConnectionState::CONNECTED, leAudioDevice->address_); return; @@ -4085,7 +4080,7 @@ class LeAudioClientImpl : public LeAudioClient { "{}\n configuration_context_type_: {}\n group {}\n", active_group_id_, audio_receiver_state_, audio_sender_state_, ToHexString(configuration_context_type_), - (group ? " exist " : " does not exist ")); + group ? " exist " : " does not exist "); switch (audio_sender_state_) { case AudioState::STARTED: @@ -4114,7 +4109,7 @@ class LeAudioClientImpl : public LeAudioClient { "Reconfiguring to {}", ToString(audio_receiver_state_), ToString(audio_sender_state_), - (group->IsPendingConfiguration() ? "true" : "false"), + group->IsPendingConfiguration(), ToString(configuration_context_type_)); group->PrintDebugState(); SetConfigurationAndStopStreamWhenNeeded( @@ -4139,7 +4134,7 @@ class LeAudioClientImpl : public LeAudioClient { "Reconfiguring to {}", ToString(audio_receiver_state_), ToString(audio_sender_state_), - (group->IsPendingConfiguration() ? "true" : "false"), + group->IsPendingConfiguration(), ToString(configuration_context_type_)); group->PrintDebugState(); SetConfigurationAndStopStreamWhenNeeded( @@ -4152,7 +4147,7 @@ class LeAudioClientImpl : public LeAudioClient { "Reconfiguring to {}", ToString(audio_receiver_state_), ToString(audio_sender_state_), - (group->IsPendingConfiguration() ? "true" : "false"), + group->IsPendingConfiguration(), ToString(configuration_context_type_)); group->PrintDebugState(); CancelStreamingRequest(); @@ -4179,7 +4174,7 @@ class LeAudioClientImpl : public LeAudioClient { "Reconfiguring to {}", ToString(audio_receiver_state_), ToString(audio_sender_state_), - (group->IsPendingConfiguration() ? "true" : "false"), + group->IsPendingConfiguration(), ToString(configuration_context_type_)); group->PrintDebugState(); SetConfigurationAndStopStreamWhenNeeded( @@ -4192,7 +4187,7 @@ class LeAudioClientImpl : public LeAudioClient { "Reconfiguring to {}", ToString(audio_receiver_state_), ToString(audio_sender_state_), - (group->IsPendingConfiguration() ? "true" : "false"), + group->IsPendingConfiguration(), ToString(configuration_context_type_)); group->PrintDebugState(); CancelStreamingRequest(); @@ -4206,7 +4201,7 @@ class LeAudioClientImpl : public LeAudioClient { "audio_receiver_state: {} \naudio_sender_state: {} \n " "isPendingConfiguration: {} \n Reconfiguring to {}", ToString(audio_receiver_state_), ToString(audio_sender_state_), - (group->IsPendingConfiguration() ? "true" : "false"), + group->IsPendingConfiguration(), ToString(configuration_context_type_)); group->PrintDebugState(); break; @@ -4361,7 +4356,7 @@ class LeAudioClientImpl : public LeAudioClient { "{}\n configuration_context_type_: {}\n group {}\n", active_group_id_, audio_receiver_state_, audio_sender_state_, ToHexString(configuration_context_type_), - (group ? " exist " : " does not exist ")); + group ? " exist " : " does not exist "); switch (audio_receiver_state_) { case AudioState::STARTED: @@ -4388,7 +4383,7 @@ class LeAudioClientImpl : public LeAudioClient { "Reconfiguring to {}", ToString(audio_receiver_state_), ToString(audio_sender_state_), - (group->IsPendingConfiguration() ? "true" : "false"), + group->IsPendingConfiguration(), ToString(configuration_context_type_)); group->PrintDebugState(); SetConfigurationAndStopStreamWhenNeeded( @@ -4413,7 +4408,7 @@ class LeAudioClientImpl : public LeAudioClient { "Reconfiguring to {}", ToString(audio_receiver_state_), ToString(audio_sender_state_), - (group->IsPendingConfiguration() ? "true" : "false"), + group->IsPendingConfiguration(), ToString(configuration_context_type_)); group->PrintDebugState(); SetConfigurationAndStopStreamWhenNeeded( @@ -4426,7 +4421,7 @@ class LeAudioClientImpl : public LeAudioClient { "Reconfiguring to {}", ToString(audio_receiver_state_), ToString(audio_sender_state_), - (group->IsPendingConfiguration() ? "true" : "false"), + group->IsPendingConfiguration(), ToString(configuration_context_type_)); group->PrintDebugState(); CancelStreamingRequest(); @@ -4454,7 +4449,7 @@ class LeAudioClientImpl : public LeAudioClient { "Reconfiguring to {}", ToString(audio_receiver_state_), ToString(audio_sender_state_), - (group->IsPendingConfiguration() ? "true" : "false"), + group->IsPendingConfiguration(), ToString(configuration_context_type_)); group->PrintDebugState(); SetConfigurationAndStopStreamWhenNeeded( @@ -4467,7 +4462,7 @@ class LeAudioClientImpl : public LeAudioClient { "Reconfiguring to {}", ToString(audio_receiver_state_), ToString(audio_sender_state_), - (group->IsPendingConfiguration() ? "true" : "false"), + group->IsPendingConfiguration(), ToString(configuration_context_type_)); group->PrintDebugState(); CancelStreamingRequest(); @@ -4481,7 +4476,7 @@ class LeAudioClientImpl : public LeAudioClient { "{} \naudio_sender_state: {} \n isPendingConfiguration: {} \n " "Reconfiguring to {}", ToString(audio_receiver_state_), ToString(audio_sender_state_), - (group->IsPendingConfiguration() ? "true" : "false"), + group->IsPendingConfiguration(), ToString(configuration_context_type_)); group->PrintDebugState(); break; @@ -4837,9 +4832,8 @@ class LeAudioClientImpl : public LeAudioClient { * with any other bidirectional context */ if (IsInCall() || IsInVoipCall()) { - log::debug("In Call preference used: {}, voip call: {}", - (IsInCall() ? "true" : "false"), - (IsInVoipCall() ? "true" : "false")); + log::debug("In Call preference used: {}, voip call: {}", IsInCall(), + IsInVoipCall()); local_metadata_context_types_.sink.unset_all(kLeAudioContextAllBidir); local_metadata_context_types_.source.unset_all(kLeAudioContextAllBidir); local_metadata_context_types_.sink.set( @@ -4872,11 +4866,11 @@ class LeAudioClientImpl : public LeAudioClient { ? "Source" : "Sink")); log::debug("is_streaming_other_direction= {}", - (is_streaming_other_direction ? "True" : "False")); + is_streaming_other_direction ? "True" : "False"); log::debug("is_releasing_for_reconfiguration= {}", - (is_releasing_for_reconfiguration ? "True" : "False")); + is_releasing_for_reconfiguration ? "True" : "False"); log::debug("is_ongoing_call_on_other_direction={}", - (is_ongoing_call_on_other_direction ? "True" : "False")); + is_ongoing_call_on_other_direction ? "True" : "False"); if (remote_metadata.get(remote_other_direction) .test_any(kLeAudioContextAllBidir) && @@ -4971,7 +4965,7 @@ class LeAudioClientImpl : public LeAudioClient { auto source_supported_contexts = group->GetSupportedContexts( bluetooth::le_audio::types::kLeAudioDirectionSource); - log::debug(" group_id: {}, sink_supported: {}, source_supported {}", + log::debug("group_id: {}, sink_supported: {}, source_supported {}", group->group_id_, ToString(sink_supported_contexts), ToString(source_supported_contexts)); if (sink_supported_contexts.test(LeAudioContextType::VOICEASSISTANTS) && @@ -4989,7 +4983,7 @@ class LeAudioClientImpl : public LeAudioClient { } log::warn( - " group_id: {}, unexpected configuration, sink_supported: {}, " + "group_id: {}, unexpected configuration, sink_supported: {}, " "source_supported {}", group->group_id_, ToString(sink_supported_contexts), ToString(source_supported_contexts)); @@ -5402,9 +5396,9 @@ class LeAudioClientImpl : public LeAudioClient { leAudioDevices_.FindByCisConnHdl(cig_id, conn_handle); if (!leAudioDevice) { log::warn( - "device under connection handle: {}, has been disconnecected in " + "device under connection handle: 0x{:x}, has been disconnecected in " "meantime", - loghex(conn_handle)); + conn_handle); return; } LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_); diff --git a/system/bta/le_audio/client_parser.cc b/system/bta/le_audio/client_parser.cc index b23adb9b7d..05fbbc105a 100644 --- a/system/bta/le_audio/client_parser.cc +++ b/system/bta/le_audio/client_parser.cc @@ -135,8 +135,8 @@ bool ParseAseStatusHeader(ase_rsp_hdr& arh, uint16_t len, STREAM_TO_UINT8(arh.id, value); STREAM_TO_UINT8(arh.state, value); - log::info("ASE status: \tASE id: {}\tASE state: {} ({})", loghex(arh.id), - ase_state_map_string[arh.state], loghex(arh.state)); + log::info("ASE status: \tASE id: 0x{:x}\tASE state: {} (0x{:x})", arh.id, + ase_state_map_string[arh.state], arh.state); return true; } @@ -175,20 +175,18 @@ bool ParseAseStatusCodecConfiguredStateParams( std::vector<uint8_t>(value, value + codec_spec_conf_len); log::info( - "Codec configuration\n\tFraming: {}\n\tPreferred PHY: {}\n\tPreferred " - "retransmission number: {}\n\tMax transport latency: {}\n\tPresence " - "delay min: {}\n\tPresence delay max: " - "{}\n\tPreferredPresentationDelayMin: " - "{}\n\tPreferredPresentationDelayMax: {}\n\tCoding format: {}\n\tVendor " - "codec company ID: {}\n\tVendor codec ID: {}\n\tCodec specific conf len: " - "{}\n\tCodec specific conf: {}", - loghex(rsp.framing), loghex(rsp.preferred_phy), - loghex(rsp.preferred_retrans_nb), loghex(rsp.max_transport_latency), - loghex(rsp.pres_delay_min), loghex(rsp.pres_delay_max), - loghex(rsp.preferred_pres_delay_min), - loghex(rsp.preferred_pres_delay_max), loghex(rsp.codec_id.coding_format), - loghex(rsp.codec_id.vendor_company_id), - loghex(rsp.codec_id.vendor_codec_id), (int)codec_spec_conf_len, + "Codec configuration\n\tFraming: 0x{:x}\n\tPreferred PHY: " + "0x{:x}\n\tPreferred retransmission number: 0x{:x}\n\tMax transport " + "latency: 0x{:x}\n\tPresence delay min: 0x{:x}\n\tPresence delay max: " + "0x{:x}\n\tPreferredPresentationDelayMin: " + "0x{:x}\n\tPreferredPresentationDelayMax: 0x{:x}\n\tCoding format: " + "0x{:x}\n\tVendor codec company ID: 0x{:x}\n\tVendor codec ID: " + "0x{:x}\n\tCodec specific conf len: {}\n\tCodec specific conf: {}", + rsp.framing, rsp.preferred_phy, rsp.preferred_retrans_nb, + rsp.max_transport_latency, rsp.pres_delay_min, rsp.pres_delay_max, + rsp.preferred_pres_delay_min, rsp.preferred_pres_delay_max, + rsp.codec_id.coding_format, rsp.codec_id.vendor_company_id, + rsp.codec_id.vendor_codec_id, (int)codec_spec_conf_len, base::HexEncode(rsp.codec_spec_conf.data(), rsp.codec_spec_conf.size())); return true; @@ -213,13 +211,12 @@ bool ParseAseStatusQosConfiguredStateParams( STREAM_TO_UINT24(rsp.pres_delay, value); log::info( - "Codec QoS Configured\n\tCIG: {}\n\tCIS: {}\n\tSDU interval: " - "{}\n\tFraming: {}\n\tPHY: {}\n\tMax SDU: {}\n\tRetransmission number: " - "{}\n\tMax transport latency: {}\n\tPresentation delay: {}", - loghex(rsp.cig_id), loghex(rsp.cis_id), loghex(rsp.sdu_interval), - loghex(rsp.framing), loghex(rsp.phy), loghex(rsp.max_sdu), - loghex(rsp.retrans_nb), loghex(rsp.max_transport_latency), - loghex(rsp.pres_delay)); + "Codec QoS Configured\n\tCIG: 0x{:x}\n\tCIS: 0x{:x}\n\tSDU interval: " + "0x{:x}\n\tFraming: 0x{:x}\n\tPHY: 0x{:x}\n\tMax SDU: " + "0x{:x}\n\tRetransmission number: 0x{:x}\n\tMax transport latency: " + "0x{:x}\n\tPresentation delay: 0x{:x}", + rsp.cig_id, rsp.cis_id, rsp.sdu_interval, rsp.framing, rsp.phy, + rsp.max_sdu, rsp.retrans_nb, rsp.max_transport_latency, rsp.pres_delay); return true; } @@ -247,9 +244,9 @@ bool ParseAseStatusTransientStateParams(struct ase_transient_state_params& rsp, rsp.metadata = std::vector<uint8_t>(value, value + metadata_len); log::info( - "Status enabling/streaming/disabling\n\tCIG: {}\n\tCIS: {}\n\tMetadata: " - "{}", - loghex(rsp.cig_id), loghex(rsp.cis_id), + "Status enabling/streaming/disabling\n\tCIG: 0x{:x}\n\tCIS: " + "0x{:x}\n\tMetadata: {}", + rsp.cig_id, rsp.cis_id, base::HexEncode(rsp.metadata.data(), rsp.metadata.size())); return true; @@ -282,18 +279,19 @@ bool ParseAseCtpNotification(struct ctp_ntf& ntf, uint16_t len, ntf.entries.push_back(std::move(entry)); } - log::info("Control point notification\n\tOpcode: {} ({})\n\tNum ASE IDs: {}", - ctp_opcode_map_string[ntf.op], loghex(ntf.op), (int)num_entries); + log::info( + "Control point notification\n\tOpcode: {} (0x{:x})\n\tNum ASE IDs: {}", + ctp_opcode_map_string[ntf.op], ntf.op, (int)num_entries); for (size_t i = 0; i < num_entries; i++) - log::info("\n\tASE ID[{}] response: {} ({}) reason: {} ({})", - loghex(ntf.entries[i].ase_id), + log::info("\n\tASE ID[0x{:x}] response: {} (0x{:x}) reason: {} (0x{:x})", + ntf.entries[i].ase_id, ctp_response_code_map_string[ntf.entries[i].response_code], - loghex(ntf.entries[i].response_code), + ntf.entries[i].response_code, ((ctp_response_code_map.count(ntf.entries[i].response_code) != 0) ? (*ctp_response_code_map[ntf.entries[i].response_code]) [ntf.entries[i].reason] : ""), - loghex(ntf.entries[i].reason)); + ntf.entries[i].reason); return true; } @@ -346,13 +344,13 @@ bool PrepareAseCtpCodecConfig(const std::vector<struct ctp_codec_conf>& confs, static_cast<int>(conf.codec_config.size())); log::info( - "Codec configuration\n\tAse id: {}\n\tTarget latency: {}\n\tTarget " - "PHY: {}\n\tCoding format: {}\n\tVendor codec company ID: {}\n\tVendor " - "codec ID: {}\n\tCodec config len: {}\n\tCodec spec conf: \n{}", - loghex(conf.ase_id), loghex(conf.target_latency), - loghex(conf.target_phy), loghex(conf.codec_id.coding_format), - loghex(conf.codec_id.vendor_company_id), - loghex(conf.codec_id.vendor_codec_id), + "Codec configuration\n\tAse id: 0x{:x}\n\tTarget latency: " + "0x{:x}\n\tTarget PHY: 0x{:x}\n\tCoding format: 0x{:x}\n\tVendor codec " + "company ID: 0x{:x}\n\tVendor codec ID: 0x{:x}\n\tCodec config len: " + "{}\n\tCodec spec conf: \n{}", + conf.ase_id, conf.target_latency, conf.target_phy, + conf.codec_id.coding_format, conf.codec_id.vendor_company_id, + conf.codec_id.vendor_codec_id, static_cast<int>(conf.codec_config.size()), conf_ents_str.str()); } @@ -381,13 +379,13 @@ bool PrepareAseCtpConfigQos(const std::vector<struct ctp_qos_conf>& confs, UINT24_TO_STREAM(msg, conf.pres_delay); log::info( - "QoS configuration\n\tAse id: {}\n\tcig: {}\n\tCis: {}\n\tSDU " - "interval: {}\n\tFraming: {}\n\tPhy: {}\n\tMax sdu size: {}\n\tRetrans " - "nb: {}\n\tMax Transport latency: {}\n\tPres delay: {}", - loghex(conf.ase_id), loghex(conf.cig), loghex(conf.cis), - loghex(conf.sdu_interval), loghex(conf.framing), loghex(conf.phy), - loghex(conf.max_sdu), loghex(conf.retrans_nb), - loghex(conf.max_transport_latency), loghex(conf.pres_delay)); + "QoS configuration\n\tAse id: 0x{:x}\n\tcig: 0x{:x}\n\tCis: " + "0x{:x}\n\tSDU interval: 0x{:x}\n\tFraming: 0x{:x}\n\tPhy: " + "0x{:x}\n\tMax sdu size: 0x{:x}\n\tRetrans nb: 0x{:x}\n\tMax Transport " + "latency: 0x{:x}\n\tPres delay: 0x{:x}", + conf.ase_id, conf.cig, conf.cis, conf.sdu_interval, conf.framing, + conf.phy, conf.max_sdu, conf.retrans_nb, conf.max_transport_latency, + conf.pres_delay); } return true; @@ -427,7 +425,7 @@ bool PrepareAseCtpEnable(const std::vector<struct ctp_enable>& confs, ARRAY_TO_STREAM(msg, conf.metadata.data(), static_cast<int>(conf.metadata.size())); - log::info("Enable\n\tAse id: {}\n\tMetadata: {}", loghex(conf.ase_id), + log::info("Enable\n\tAse id: 0x{:x}\n\tMetadata: {}", conf.ase_id, base::HexEncode(conf.metadata.data(), conf.metadata.size())); } @@ -446,7 +444,7 @@ bool PrepareAseCtpAudioReceiverStartReady(const std::vector<uint8_t>& ase_ids, for (const uint8_t& id : ase_ids) { UINT8_TO_STREAM(msg, id); - log::info("ReceiverStartReady\n\tAse id: {}", loghex(id)); + log::info("ReceiverStartReady\n\tAse id: 0x{:x}", id); } return true; @@ -464,7 +462,7 @@ bool PrepareAseCtpDisable(const std::vector<uint8_t>& ase_ids, for (const uint8_t& id : ase_ids) { UINT8_TO_STREAM(msg, id); - log::info("Disable\n\tAse id: {}", loghex(id)); + log::info("Disable\n\tAse id: 0x{:x}", id); } return true; @@ -482,7 +480,7 @@ bool PrepareAseCtpAudioReceiverStopReady(const std::vector<uint8_t>& ase_ids, for (const uint8_t& ase_id : ase_ids) { UINT8_TO_STREAM(msg, ase_id); - log::info("ReceiverStopReady\n\tAse id: {}", loghex(ase_id)); + log::info("ReceiverStopReady\n\tAse id: 0x{:x}", ase_id); } return true; @@ -524,8 +522,7 @@ bool PrepareAseCtpUpdateMetadata( ARRAY_TO_STREAM(msg, conf.metadata.data(), static_cast<int>(conf.metadata.size())); - log::info("Update Metadata\n\tAse id: {}\n\tMetadata: {}", - loghex(conf.ase_id), + log::info("Update Metadata\n\tAse id: 0x{:x}\n\tMetadata: {}", conf.ase_id, base::HexEncode(conf.metadata.data(), conf.metadata.size())); } @@ -544,7 +541,7 @@ bool PrepareAseCtpRelease(const std::vector<uint8_t>& ase_ids, for (const uint8_t& ase_id : ase_ids) { UINT8_TO_STREAM(msg, ase_id); - log::info("Release\n\tAse id: {}", loghex(ase_id)); + log::info("Release\n\tAse id: 0x{:x}", ase_id); } return true; diff --git a/system/bta/le_audio/codec_manager.cc b/system/bta/le_audio/codec_manager.cc index 0468dc5463..d0f5f0b598 100644 --- a/system/bta/le_audio/codec_manager.cc +++ b/system/bta/le_audio/codec_manager.cc @@ -204,7 +204,7 @@ struct codec_manager_impl { } } - const AudioSetConfigurations* GetSupportedCodecConfigurations( + AudioSetConfigurations GetSupportedCodecConfigurations( const CodecManager::UnicastConfigurationRequirements& requirements) const { if (GetCodecLocation() == le_audio::types::CodecLocation::ADSP) { @@ -215,14 +215,14 @@ struct codec_manager_impl { // doesn't support. return context_type_offload_config_map_.count( requirements.audio_context_type) - ? &context_type_offload_config_map_.at( + ? context_type_offload_config_map_.at( requirements.audio_context_type) - : nullptr; + : AudioSetConfigurations(); } log::verbose("Get software config for the context type: {}", (int)requirements.audio_context_type); - return AudioSetConfigurationProvider::Get()->GetConfigurations( + return *AudioSetConfigurationProvider::Get()->GetConfigurations( requirements.audio_context_type); } @@ -248,18 +248,31 @@ struct codec_manager_impl { const CodecManager::UnicastConfigurationRequirements& requirements, CodecManager::UnicastConfigurationVerifier verifier) { auto configs = GetSupportedCodecConfigurations(requirements); - if (configs == nullptr) { + if (configs.empty()) { log::error("No valid configuration matching the requirements: {}", requirements); PrintDebugState(); return nullptr; } + + // Remove the dual bidir SWB config if not supported + if (!IsDualBiDirSwbSupported()) { + configs.erase( + std::remove_if(configs.begin(), configs.end(), + [](auto const& el) { + if (el->confs.source.empty()) return false; + return AudioSetConfigurationProvider::Get() + ->CheckConfigurationIsDualBiDirSwb(*el); + }), + configs.end()); + } + // Note: For the only supported right now legacy software configuration // provider, we use the device group logic to match the proper // configuration with group capabilities. Note that this path only // supports the LC3 codec format. For the multicodec support we should // rely on the configuration matcher behind the AIDL interface. - auto conf = verifier(requirements, configs); + auto conf = verifier(requirements, &configs); return conf ? std::make_unique<AudioSetConfiguration>(*conf) : nullptr; } @@ -268,32 +281,35 @@ struct codec_manager_impl { config); } + bool CheckCodecConfigIsDualBiDirSwb(const AudioSetConfiguration& config) { + return AudioSetConfigurationProvider::Get() + ->CheckConfigurationIsDualBiDirSwb(config); + } + void UpdateSupportedBroadcastConfig( const std::vector<AudioSetConfiguration>& adsp_capabilities) { log::info("UpdateSupportedBroadcastConfig"); for (const auto& adsp_audio_set_conf : adsp_capabilities) { - log::assert_that( - adsp_audio_set_conf.topology_info.has_value(), - "No topology info, which is required to properly configure the ASEs"); - if (adsp_audio_set_conf.confs.sink.size() != 1 || - adsp_audio_set_conf.topology_info->device_count.sink != 0 || - adsp_audio_set_conf.topology_info->device_count.source != 0) { + if (adsp_audio_set_conf.confs.sink.empty() || + !adsp_audio_set_conf.confs.source.empty()) { continue; } + auto& adsp_config = adsp_audio_set_conf.confs.sink[0]; const types::LeAudioCoreCodecConfig core_config = adsp_config.codec.params.GetAsCoreCodecConfig(); bluetooth::le_audio::broadcast_offload_config broadcast_config; - broadcast_config.stream_map.resize( - core_config.GetChannelCountPerIsoStream()); + broadcast_config.stream_map.resize(adsp_audio_set_conf.confs.sink.size()); // Enable the individual channels per BIS in the stream map + auto all_channels = adsp_config.codec.channel_count_per_iso_stream; + uint8_t channel_alloc_idx = 0; for (auto& [_, channels] : broadcast_config.stream_map) { - for (uint8_t i = 0; i < adsp_config.codec.channel_count_per_iso_stream; - ++i) { - channels |= (0b1 << i); + if (all_channels) { + channels |= (0b1 << channel_alloc_idx++); + --all_channels; } } @@ -704,17 +720,8 @@ struct codec_manager_impl { size_t match_cnt = 0; size_t expected_match_cnt = 0; - log::assert_that(adsp_audio_set_conf.topology_info.has_value(), - "ADSP capability is missing the topology information."); - for (auto direction : {le_audio::types::kLeAudioDirectionSink, le_audio::types::kLeAudioDirectionSource}) { - if (software_audio_set_conf->topology_info->device_count.get( - direction) != - adsp_audio_set_conf.topology_info->device_count.get(direction)) { - continue; - } - auto const& software_set_ase_confs = software_audio_set_conf->confs.get(direction); auto const& adsp_set_ase_confs = @@ -812,7 +819,7 @@ struct codec_manager_impl { le_audio::types::kLeAudioDirectionSource}) { log::debug( "dir: {}: number of confs {}:", - (direction == types::kLeAudioDirectionSink ? "sink" : "source"), + direction == types::kLeAudioDirectionSink ? "sink" : "source", (int)(adsp.confs.get(direction).size())); for (auto conf : adsp.confs.sink) { log::debug( @@ -1041,7 +1048,14 @@ bool CodecManager::CheckCodecConfigIsBiDirSwb( if (pimpl_->IsRunning()) { return pimpl_->codec_manager_impl_->CheckCodecConfigIsBiDirSwb(config); } + return false; +} +bool CodecManager::CheckCodecConfigIsDualBiDirSwb( + const set_configurations::AudioSetConfiguration& config) const { + if (pimpl_->IsRunning()) { + return pimpl_->codec_manager_impl_->CheckCodecConfigIsDualBiDirSwb(config); + } return false; } diff --git a/system/bta/le_audio/codec_manager.h b/system/bta/le_audio/codec_manager.h index a8a170544b..cd6fe86be8 100644 --- a/system/bta/le_audio/codec_manager.h +++ b/system/bta/le_audio/codec_manager.h @@ -104,10 +104,12 @@ class CodecManager { ::bluetooth::le_audio::set_configurations::AudioSetConfiguration> GetCodecConfig(const UnicastConfigurationRequirements& requirements, UnicastConfigurationVerifier verifier); - virtual bool CheckCodecConfigIsBiDirSwb( const ::bluetooth::le_audio::set_configurations::AudioSetConfiguration& config) const; + virtual bool CheckCodecConfigIsDualBiDirSwb( + const ::bluetooth::le_audio::set_configurations::AudioSetConfiguration& + config) const; virtual std::unique_ptr<broadcaster::BroadcastConfiguration> GetBroadcastConfig( const BroadcastConfigurationRequirements& requirements) const; diff --git a/system/bta/le_audio/codec_manager_test.cc b/system/bta/le_audio/codec_manager_test.cc index e131857a62..d3d6eb02ea 100644 --- a/system/bta/le_audio/codec_manager_test.cc +++ b/system/bta/le_audio/codec_manager_test.cc @@ -184,6 +184,8 @@ static constexpr char kPropLeAudioOffloadSupported[] = "ro.bluetooth.leaudio_offload.supported"; static constexpr char kPropLeAudioOffloadDisabled[] = "persist.bluetooth.leaudio_offload.disabled"; +static constexpr char kPropLeAudioBidirSwbSupported[] = + "bluetooth.leaudio.dual_bidirection_swb.supported"; class CodecManagerTestBase : public Test { public: @@ -218,6 +220,23 @@ class CodecManagerTestAdsp : public CodecManagerTestBase { osi_property_set_bool(kPropLeAudioOffloadSupported, true); osi_property_set_bool(kPropLeAudioOffloadDisabled, false); + // Allow for bidir SWB configurations + osi_property_set_bool(kPropLeAudioBidirSwbSupported, true); + + CodecManagerTestBase::SetUp(); + } +}; + +class CodecManagerTestAdspNoSwb : public CodecManagerTestBase { + public: + virtual void SetUp() override { + // Enable the HW offloader + osi_property_set_bool(kPropLeAudioOffloadSupported, true); + osi_property_set_bool(kPropLeAudioOffloadDisabled, false); + + // Allow for bidir SWB configurations + osi_property_set_bool(kPropLeAudioBidirSwbSupported, false); + CodecManagerTestBase::SetUp(); } }; @@ -471,11 +490,26 @@ TEST_F(CodecManagerTestAdsp, test_capabilities) { } TEST_F(CodecManagerTestAdsp, test_broadcast_config) { - std::vector<AudioSetConfiguration> offload_capabilities = { - {.name = "Test_Broadcast_Config_No_Dev_lc3_48_2", - .confs = {.sink = {set_configurations::AseConfiguration(lc3_48_2)}, - .source = {}}, - .topology_info = {{{0, 0}}}}}; + static const set_configurations::CodecConfigSetting bc_lc3_48_2 = { + .id = kLeAudioCodecIdLc3, + .params = types::LeAudioLtvMap({ + LTV_ENTRY_SAMPLING_FREQUENCY( + codec_spec_conf::kLeAudioSamplingFreq48000Hz), + LTV_ENTRY_FRAME_DURATION( + codec_spec_conf::kLeAudioCodecFrameDur10000us), + LTV_ENTRY_AUDIO_CHANNEL_ALLOCATION( + codec_spec_conf::kLeAudioLocationStereo), + LTV_ENTRY_OCTETS_PER_CODEC_FRAME(100), + }), + .channel_count_per_iso_stream = 2, + }; + + std::vector<AudioSetConfiguration> offload_capabilities = {{ + .name = "Test_Broadcast_Config_No_Dev_lc3_48_2", + .confs = {.sink = {set_configurations::AseConfiguration(bc_lc3_48_2), + set_configurations::AseConfiguration(bc_lc3_48_2)}, + .source = {}}, + }}; set_mock_offload_capabilities(offload_capabilities); const std::vector<bluetooth::le_audio::btle_audio_codec_config_t> @@ -491,16 +525,41 @@ TEST_F(CodecManagerTestAdsp, test_broadcast_config) { ASSERT_EQ(48000u, cfg->GetSamplingFrequencyHzMax()); ASSERT_EQ(10000u, cfg->GetSduIntervalUs()); ASSERT_EQ(100u, cfg->GetMaxSduOctets()); + ASSERT_EQ(1lu, cfg->subgroups.size()); + ASSERT_EQ(2lu, cfg->subgroups.at(0).GetNumBis()); + ASSERT_EQ(2lu, cfg->subgroups.at(0).GetNumChannelsTotal()); + + ASSERT_EQ(2lu, cfg->subgroups.at(0).GetBisCodecConfigs().at(0).GetNumBis()); + ASSERT_EQ(2lu, + cfg->subgroups.at(0).GetBisCodecConfigs().at(0).GetNumChannels()); + ASSERT_EQ( + 1lu, + cfg->subgroups.at(0).GetBisCodecConfigs().at(0).GetNumChannelsPerBis()); // Clean up the before testing any other offload capabilities. codec_manager->Stop(); } TEST_F(CodecManagerTestAdsp, test_update_broadcast_offloader) { - std::vector<AudioSetConfiguration> offload_capabilities = { - {.confs = {.sink = {set_configurations::AseConfiguration(lc3_48_2)}, - .source = {}}, - .topology_info = {{{0, 0}}}}}; + static const set_configurations::CodecConfigSetting bc_lc3_48_2 = { + .id = kLeAudioCodecIdLc3, + .params = types::LeAudioLtvMap({ + LTV_ENTRY_SAMPLING_FREQUENCY( + codec_spec_conf::kLeAudioSamplingFreq48000Hz), + LTV_ENTRY_FRAME_DURATION( + codec_spec_conf::kLeAudioCodecFrameDur10000us), + LTV_ENTRY_AUDIO_CHANNEL_ALLOCATION( + codec_spec_conf::kLeAudioLocationStereo), + LTV_ENTRY_OCTETS_PER_CODEC_FRAME(100), + }), + .channel_count_per_iso_stream = 2, + }; + std::vector<AudioSetConfiguration> offload_capabilities = {{ + .name = "Test_Broadcast_Config_For_Offloader", + .confs = {.sink = {set_configurations::AseConfiguration(bc_lc3_48_2), + set_configurations::AseConfiguration(bc_lc3_48_2)}, + .source = {}}, + }}; set_mock_offload_capabilities(offload_capabilities); const std::vector<bluetooth::le_audio::btle_audio_codec_config_t> @@ -541,6 +600,23 @@ class CodecManagerTestHost : public CodecManagerTestBase { osi_property_set_bool(kPropLeAudioOffloadSupported, false); osi_property_set_bool(kPropLeAudioOffloadDisabled, false); + // Allow for bidir SWB configurations + osi_property_set_bool(kPropLeAudioBidirSwbSupported, true); + + CodecManagerTestBase::SetUp(); + } +}; + +class CodecManagerTestHostNoSwb : public CodecManagerTestBase { + public: + virtual void SetUp() override { + // Enable the HW offloader + osi_property_set_bool(kPropLeAudioOffloadSupported, true); + osi_property_set_bool(kPropLeAudioOffloadDisabled, false); + + // Do not allow for bidir SWB configurations + osi_property_set_bool(kPropLeAudioBidirSwbSupported, false); + CodecManagerTestBase::SetUp(); } }; @@ -582,127 +658,376 @@ TEST_F(CodecManagerTestHost, test_non_bidir_swb) { {.codec_type = bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3}}; codec_manager->Start(offloading_preference); + // NON-SWB configs + ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({ + .confs = {.sink = {set_configurations::AseConfiguration(lc3_16_2), + set_configurations::AseConfiguration(lc3_16_2)}, + .source = {set_configurations::AseConfiguration(lc3_16_2), + set_configurations::AseConfiguration(lc3_16_2)}}, + })); + ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({ + .confs = {.sink = {set_configurations::AseConfiguration(lc3_24_2), + set_configurations::AseConfiguration(lc3_24_2)}, + .source = {set_configurations::AseConfiguration(lc3_16_2), + set_configurations::AseConfiguration(lc3_16_2)}}, + })); + ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({ + .confs = {.sink = {set_configurations::AseConfiguration(lc3_16_2), + set_configurations::AseConfiguration(lc3_16_2)}, + .source = {set_configurations::AseConfiguration(lc3_24_2), + set_configurations::AseConfiguration(lc3_24_2)}}, + })); + + ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({ + .confs = {.sink = {set_configurations::AseConfiguration(lc3_16_2), + set_configurations::AseConfiguration(lc3_16_2)}, + .source = {set_configurations::AseConfiguration(lc3_32_2), + set_configurations::AseConfiguration(lc3_32_2)}}, + })); + ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({ + .confs = {.sink = {set_configurations::AseConfiguration(lc3_32_2), + set_configurations::AseConfiguration(lc3_32_2)}, + .source = {set_configurations::AseConfiguration(lc3_16_2), + set_configurations::AseConfiguration(lc3_16_2)}}, + })); + + ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({ + .confs = {.sink = {set_configurations::AseConfiguration(lc3_24_2), + set_configurations::AseConfiguration(lc3_24_2)}, + .source = {set_configurations::AseConfiguration(lc3_24_2), + set_configurations::AseConfiguration(lc3_24_2)}}, + })); + ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({ + .confs = {.sink = {set_configurations::AseConfiguration(lc3_24_2), + set_configurations::AseConfiguration(lc3_24_2)}, + .source = {set_configurations::AseConfiguration(lc3_32_2), + set_configurations::AseConfiguration(lc3_32_2)}}, + })); + ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({ + .confs = {.sink = {set_configurations::AseConfiguration(lc3_32_2), + set_configurations::AseConfiguration(lc3_32_2)}, + .source = {set_configurations::AseConfiguration(lc3_24_2), + set_configurations::AseConfiguration(lc3_24_2)}}, + })); + + ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({ + .confs = {.sink = {set_configurations::AseConfiguration(lc3_16_2), + set_configurations::AseConfiguration(lc3_16_2)}}, + })); + ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({ + .confs = {.source = {set_configurations::AseConfiguration(lc3_16_2), + set_configurations::AseConfiguration(lc3_16_2)}}, + })); + ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({ + .confs = {.sink = {set_configurations::AseConfiguration(lc3_24_2), + set_configurations::AseConfiguration(lc3_24_2)}}, + })); + ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({ + .confs = {.source = {set_configurations::AseConfiguration(lc3_24_2), + set_configurations::AseConfiguration(lc3_24_2)}}, + })); + ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({ + .confs = {.sink = {set_configurations::AseConfiguration(lc3_32_2), + set_configurations::AseConfiguration(lc3_32_2)}}, + })); + ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({ + .confs = {.source = {set_configurations::AseConfiguration(lc3_32_2), + set_configurations::AseConfiguration(lc3_32_2)}}, + })); + ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({ + .confs = {.sink = {set_configurations::AseConfiguration(lc3_48_2), + set_configurations::AseConfiguration(lc3_48_2)}}, + })); + ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({ + .confs = {.source = {set_configurations::AseConfiguration(lc3_48_2), + set_configurations::AseConfiguration(lc3_48_2)}}, + })); + + // NON-DUAL-SWB configs + ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({ + .confs = {.sink = {set_configurations::AseConfiguration(lc3_16_2), + set_configurations::AseConfiguration(lc3_16_2)}, + .source = {set_configurations::AseConfiguration(lc3_16_2), + set_configurations::AseConfiguration(lc3_16_2)}}, + })); + ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({ + .confs = {.sink = {set_configurations::AseConfiguration(lc3_24_2), + set_configurations::AseConfiguration(lc3_24_2)}, + .source = {set_configurations::AseConfiguration(lc3_16_2), + set_configurations::AseConfiguration(lc3_16_2)}}, + })); + ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({ + .confs = {.sink = {set_configurations::AseConfiguration(lc3_16_2), + set_configurations::AseConfiguration(lc3_16_2)}, + .source = {set_configurations::AseConfiguration(lc3_24_2), + set_configurations::AseConfiguration(lc3_24_2)}}, + })); + + ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({ + .confs = {.sink = {set_configurations::AseConfiguration(lc3_16_2), + set_configurations::AseConfiguration(lc3_16_2)}, + .source = {set_configurations::AseConfiguration(lc3_32_2), + set_configurations::AseConfiguration(lc3_32_2)}}, + })); + ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({ + .confs = {.sink = {set_configurations::AseConfiguration(lc3_32_2), + set_configurations::AseConfiguration(lc3_32_2)}, + .source = {set_configurations::AseConfiguration(lc3_16_2), + set_configurations::AseConfiguration(lc3_16_2)}}, + })); + + ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({ + .confs = {.sink = {set_configurations::AseConfiguration(lc3_24_2), + set_configurations::AseConfiguration(lc3_24_2)}, + .source = {set_configurations::AseConfiguration(lc3_24_2), + set_configurations::AseConfiguration(lc3_24_2)}}, + })); + ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({ + .confs = {.sink = {set_configurations::AseConfiguration(lc3_24_2), + set_configurations::AseConfiguration(lc3_24_2)}, + .source = {set_configurations::AseConfiguration(lc3_32_2), + set_configurations::AseConfiguration(lc3_32_2)}}, + })); + ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({ + .confs = {.sink = {set_configurations::AseConfiguration(lc3_32_2), + set_configurations::AseConfiguration(lc3_32_2)}, + .source = {set_configurations::AseConfiguration(lc3_24_2), + set_configurations::AseConfiguration(lc3_24_2)}}, + })); + + ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({ + .confs = {.sink = {set_configurations::AseConfiguration(lc3_16_2), + set_configurations::AseConfiguration(lc3_16_2)}}, + })); + ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({ + .confs = {.source = {set_configurations::AseConfiguration(lc3_16_2), + set_configurations::AseConfiguration(lc3_16_2)}}, + })); + ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({ + .confs = {.sink = {set_configurations::AseConfiguration(lc3_24_2), + set_configurations::AseConfiguration(lc3_24_2)}}, + })); + ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({ + .confs = {.source = {set_configurations::AseConfiguration(lc3_24_2), + set_configurations::AseConfiguration(lc3_24_2)}}, + })); + ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({ + .confs = {.sink = {set_configurations::AseConfiguration(lc3_32_2), + set_configurations::AseConfiguration(lc3_32_2)}}, + })); + ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({ + .confs = {.source = {set_configurations::AseConfiguration(lc3_32_2), + set_configurations::AseConfiguration(lc3_32_2)}}, + })); + ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({ + .confs = {.sink = {set_configurations::AseConfiguration(lc3_48_2), + set_configurations::AseConfiguration(lc3_48_2)}}, + })); + ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({ + .confs = {.source = {set_configurations::AseConfiguration(lc3_48_2), + set_configurations::AseConfiguration(lc3_48_2)}}, + })); +} + +TEST_F(CodecManagerTestHost, test_dual_bidir_swb) { + const std::vector<bluetooth::le_audio::btle_audio_codec_config_t> + offloading_preference = { + {.codec_type = bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3}}; + codec_manager->Start(offloading_preference); + + // Single Dev BiDir SWB configs + ASSERT_TRUE(codec_manager->CheckCodecConfigIsDualBiDirSwb({ + .confs = {.sink = {set_configurations::AseConfiguration(lc3_32_2), + set_configurations::AseConfiguration(lc3_32_2)}, + .source = {set_configurations::AseConfiguration(lc3_32_2), + set_configurations::AseConfiguration(lc3_32_2)}}, + })); + ASSERT_TRUE(codec_manager->CheckCodecConfigIsDualBiDirSwb({ + .confs = {.sink = {set_configurations::AseConfiguration(lc3_48_2), + set_configurations::AseConfiguration(lc3_48_2)}, + .source = {set_configurations::AseConfiguration(lc3_32_2), + set_configurations::AseConfiguration(lc3_32_2)}}, + })); + ASSERT_TRUE(codec_manager->CheckCodecConfigIsDualBiDirSwb({ + .confs = {.sink = {set_configurations::AseConfiguration(lc3_32_2), + set_configurations::AseConfiguration(lc3_32_2)}, + .source = {set_configurations::AseConfiguration(lc3_48_2), + set_configurations::AseConfiguration(lc3_48_2)}}, + })); + ASSERT_TRUE(codec_manager->CheckCodecConfigIsDualBiDirSwb({ + .confs = {.sink = {set_configurations::AseConfiguration(lc3_48_2), + set_configurations::AseConfiguration(lc3_48_2)}, + .source = {set_configurations::AseConfiguration(lc3_48_2), + set_configurations::AseConfiguration(lc3_48_2)}}, + })); +} + +TEST_F(CodecManagerTestHost, test_dual_bidir_swb_supported) { + const std::vector<bluetooth::le_audio::btle_audio_codec_config_t> + offloading_preference = { + {.codec_type = bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3}}; + codec_manager->Start(offloading_preference); + + int num_of_dual_bidir_swb_configs = 0; + for (auto context : types::kLeAudioContextAllTypesArray) { + bool got_null_cfgs_container = false; + auto ptr = codec_manager->GetCodecConfig( + {.audio_context_type = context}, + [&](const CodecManager::UnicastConfigurationRequirements& requirements, + const set_configurations::AudioSetConfigurations* confs) + -> const set_configurations::AudioSetConfiguration* { + if (confs == nullptr) { + got_null_cfgs_container = true; + } else { + num_of_dual_bidir_swb_configs += std::count_if( + confs->begin(), confs->end(), [&](auto const& cfg) { + bool is_bidir = + codec_manager->CheckCodecConfigIsDualBiDirSwb(*cfg); + return codec_manager->CheckCodecConfigIsDualBiDirSwb(*cfg); + }); + } + // In this case the chosen configuration doesn't matter - select none + return nullptr; + }); + ASSERT_FALSE(got_null_cfgs_container); + } + + // Make sure some dual bidir SWB configs were returned + ASSERT_NE(0, num_of_dual_bidir_swb_configs); +} + +TEST_F(CodecManagerTestAdsp, test_dual_bidir_swb_supported) { + // Set the offloader capabilities std::vector<AudioSetConfiguration> offload_capabilities = { - {.confs = {.sink = {set_configurations::AseConfiguration(lc3_48_2)}, - .source = {}}}}; + { + .name = "Test_Bidir_SWB_Config_No_Dev_lc3_32_2", + .confs = {.sink = {set_configurations::AseConfiguration(lc3_32_2), + set_configurations::AseConfiguration(lc3_32_2)}, + .source = {set_configurations::AseConfiguration(lc3_32_2), + set_configurations::AseConfiguration(lc3_32_2)}}, + }, + { + .name = "Test_Bidir_Non_SWB_Config_No_Dev_lc3_16_2", + .confs = {.sink = {set_configurations::AseConfiguration(lc3_16_2), + set_configurations::AseConfiguration(lc3_16_2)}, + .source = {set_configurations::AseConfiguration(lc3_16_2), + set_configurations::AseConfiguration(lc3_16_2)}}, + }}; + set_mock_offload_capabilities(offload_capabilities); - // NON-SWB configs - ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb( - {.confs = {.sink = {set_configurations::AseConfiguration(lc3_16_2), - set_configurations::AseConfiguration(lc3_16_2)}, - .source = {set_configurations::AseConfiguration(lc3_16_2), - set_configurations::AseConfiguration(lc3_16_2)}}, - .topology_info = {{{1, 1}}}})); - ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb( - {.confs = {.sink = {set_configurations::AseConfiguration(lc3_24_2), - set_configurations::AseConfiguration(lc3_24_2)}, - .source = {set_configurations::AseConfiguration(lc3_16_2), - set_configurations::AseConfiguration(lc3_16_2)}}, - .topology_info = {{{1, 1}}}})); - ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb( - {.confs = {.sink = {set_configurations::AseConfiguration(lc3_16_2), - set_configurations::AseConfiguration(lc3_16_2)}, - .source = {set_configurations::AseConfiguration(lc3_24_2), - set_configurations::AseConfiguration(lc3_24_2)}}, - .topology_info = {{{1, 1}}}})); - - ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb( - {.confs = {.sink = {set_configurations::AseConfiguration(lc3_16_2), - set_configurations::AseConfiguration(lc3_16_2)}, - .source = {set_configurations::AseConfiguration(lc3_32_2), - set_configurations::AseConfiguration(lc3_32_2)}}, - .topology_info = {{{1, 1}}}})); - ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb( - {.confs = {.sink = {set_configurations::AseConfiguration(lc3_32_2), - set_configurations::AseConfiguration(lc3_32_2)}, - .source = {set_configurations::AseConfiguration(lc3_16_2), - set_configurations::AseConfiguration(lc3_16_2)}}, - .topology_info = {{{1, 1}}}})); - - ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb( - {.confs = {.sink = {set_configurations::AseConfiguration(lc3_24_2), - set_configurations::AseConfiguration(lc3_24_2)}, - .source = {set_configurations::AseConfiguration(lc3_24_2), - set_configurations::AseConfiguration(lc3_24_2)}}, - .topology_info = {{{1, 1}}}})); - ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb( - {.confs = {.sink = {set_configurations::AseConfiguration(lc3_24_2), - set_configurations::AseConfiguration(lc3_24_2)}, - .source = {set_configurations::AseConfiguration(lc3_32_2), - set_configurations::AseConfiguration(lc3_32_2)}}, - .topology_info = {{{1, 1}}}})); - ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb( - {.confs = {.sink = {set_configurations::AseConfiguration(lc3_32_2), - set_configurations::AseConfiguration(lc3_32_2)}, - .source = {set_configurations::AseConfiguration(lc3_24_2), - set_configurations::AseConfiguration(lc3_24_2)}}, - .topology_info = {{{1, 1}}}})); - - ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb( - {.confs = {.sink = {set_configurations::AseConfiguration(lc3_16_2), - set_configurations::AseConfiguration(lc3_16_2)}}, - .topology_info = {{{1, 0}}}})); - ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb( - {.confs = {.source = {set_configurations::AseConfiguration(lc3_16_2), - set_configurations::AseConfiguration(lc3_16_2)}}, - .topology_info = {{{0, 1}}}})); - ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb( - {.confs = {.sink = {set_configurations::AseConfiguration(lc3_24_2), - set_configurations::AseConfiguration(lc3_24_2)}}, - .topology_info = {{{1, 0}}}})); - ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb( - {.confs = {.source = {set_configurations::AseConfiguration(lc3_24_2), - set_configurations::AseConfiguration(lc3_24_2)}}, - .topology_info = {{{0, 1}}}})); - ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb( - {.confs = {.sink = {set_configurations::AseConfiguration(lc3_32_2), - set_configurations::AseConfiguration(lc3_32_2)}}, - .topology_info = {{{1, 0}}}})); - ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb( - {.confs = {.source = {set_configurations::AseConfiguration(lc3_32_2), - set_configurations::AseConfiguration(lc3_32_2)}}, - .topology_info = {{{0, 1}}}})); - ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb( - {.confs = {.sink = {set_configurations::AseConfiguration(lc3_48_2), - set_configurations::AseConfiguration(lc3_48_2)}}, - .topology_info = {{{1, 0}}}})); - ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb( - {.confs = {.source = {set_configurations::AseConfiguration(lc3_48_2), - set_configurations::AseConfiguration(lc3_48_2)}}, - .topology_info = {{{0, 1}}}})); + const std::vector<bluetooth::le_audio::btle_audio_codec_config_t> + offloading_preference = { + {.codec_type = bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3}}; + codec_manager->Start(offloading_preference); + + int num_of_dual_bidir_swb_configs = 0; + for (auto context : types::kLeAudioContextAllTypesArray) { + bool got_null_cfgs_container = false; + auto ptr = codec_manager->GetCodecConfig( + {.audio_context_type = context}, + [&](const CodecManager::UnicastConfigurationRequirements& requirements, + const set_configurations::AudioSetConfigurations* confs) + -> const set_configurations::AudioSetConfiguration* { + if (confs == nullptr) { + got_null_cfgs_container = true; + } else { + num_of_dual_bidir_swb_configs += std::count_if( + confs->begin(), confs->end(), [&](auto const& cfg) { + bool is_bidir = + codec_manager->CheckCodecConfigIsDualBiDirSwb(*cfg); + return codec_manager->CheckCodecConfigIsDualBiDirSwb(*cfg); + }); + } + // In this case the chosen configuration doesn't matter - select none + return nullptr; + }); + ASSERT_FALSE(got_null_cfgs_container); + } + + // Make sure some dual bidir SWB configs were returned + ASSERT_NE(0, num_of_dual_bidir_swb_configs); +} + +TEST_F(CodecManagerTestHostNoSwb, test_dual_bidir_swb_not_supported) { + const std::vector<bluetooth::le_audio::btle_audio_codec_config_t> + offloading_preference = { + {.codec_type = bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3}}; + codec_manager->Start(offloading_preference); + + int num_of_dual_bidir_swb_configs = 0; + for (auto context : types::kLeAudioContextAllTypesArray) { + bool got_null_cfgs_container = false; + auto ptr = codec_manager->GetCodecConfig( + {.audio_context_type = context}, + [&](const CodecManager::UnicastConfigurationRequirements& requirements, + const set_configurations::AudioSetConfigurations* confs) + -> const set_configurations::AudioSetConfiguration* { + if (confs == nullptr) { + got_null_cfgs_container = true; + } else { + num_of_dual_bidir_swb_configs += std::count_if( + confs->begin(), confs->end(), [&](auto const& cfg) { + return codec_manager->CheckCodecConfigIsDualBiDirSwb(*cfg); + }); + } + // In this case the chosen configuration doesn't matter - select none + return nullptr; + }); + ASSERT_FALSE(got_null_cfgs_container); + } + + // Make sure no dual bidir SWB configs were returned + ASSERT_EQ(0, num_of_dual_bidir_swb_configs); } -TEST_F(CodecManagerTestHost, test_bidir_swb) { +TEST_F(CodecManagerTestAdspNoSwb, test_dual_bidir_swb_not_supported) { + // Set the offloader capabilities + std::vector<AudioSetConfiguration> offload_capabilities = { + { + .name = "Test_Bidir_SWB_Config_No_Dev_lc3_32_2", + .confs = {.sink = {set_configurations::AseConfiguration(lc3_32_2), + set_configurations::AseConfiguration(lc3_32_2)}, + .source = {set_configurations::AseConfiguration(lc3_32_2), + set_configurations::AseConfiguration(lc3_32_2)}}, + }, + { + .name = "Test_Bidir_Non_SWB_Config_No_Dev_lc3_16_2", + .confs = {.sink = {set_configurations::AseConfiguration(lc3_16_2), + set_configurations::AseConfiguration(lc3_16_2)}, + .source = {set_configurations::AseConfiguration(lc3_16_2), + set_configurations::AseConfiguration(lc3_16_2)}}, + }}; + set_mock_offload_capabilities(offload_capabilities); + const std::vector<bluetooth::le_audio::btle_audio_codec_config_t> offloading_preference = { {.codec_type = bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3}}; codec_manager->Start(offloading_preference); - // SWB configs - ASSERT_TRUE(codec_manager->CheckCodecConfigIsBiDirSwb( - {.confs = {.sink = {set_configurations::AseConfiguration(lc3_32_2), - set_configurations::AseConfiguration(lc3_32_2)}, - .source = {set_configurations::AseConfiguration(lc3_32_2), - set_configurations::AseConfiguration(lc3_32_2)}}, - .topology_info = {{{1, 1}}}})); - ASSERT_TRUE(codec_manager->CheckCodecConfigIsBiDirSwb( - {.confs = {.sink = {set_configurations::AseConfiguration(lc3_48_2), - set_configurations::AseConfiguration(lc3_48_2)}, - .source = {set_configurations::AseConfiguration(lc3_32_2), - set_configurations::AseConfiguration(lc3_32_2)}}, - .topology_info = {{{1, 1}}}})); - ASSERT_TRUE(codec_manager->CheckCodecConfigIsBiDirSwb( - {.confs = {.sink = {set_configurations::AseConfiguration(lc3_32_2), - set_configurations::AseConfiguration(lc3_32_2)}, - .source = {set_configurations::AseConfiguration(lc3_48_2), - set_configurations::AseConfiguration(lc3_48_2)}}, - .topology_info = {{{1, 1}}}})); - ASSERT_TRUE(codec_manager->CheckCodecConfigIsBiDirSwb( - {.confs = {.sink = {set_configurations::AseConfiguration(lc3_48_2), - set_configurations::AseConfiguration(lc3_48_2)}, - .source = {set_configurations::AseConfiguration(lc3_48_2), - set_configurations::AseConfiguration(lc3_48_2)}}, - .topology_info = {{{1, 1}}}})); + int num_of_dual_bidir_swb_configs = 0; + for (auto context : types::kLeAudioContextAllTypesArray) { + bool got_null_cfgs_container = false; + auto ptr = codec_manager->GetCodecConfig( + {.audio_context_type = context}, + [&](const CodecManager::UnicastConfigurationRequirements& requirements, + const set_configurations::AudioSetConfigurations* confs) + -> const set_configurations::AudioSetConfiguration* { + if (confs == nullptr) { + got_null_cfgs_container = true; + } else { + num_of_dual_bidir_swb_configs += std::count_if( + confs->begin(), confs->end(), [&](auto const& cfg) { + return codec_manager->CheckCodecConfigIsDualBiDirSwb(*cfg); + }); + } + // In this case the chosen configuration doesn't matter - select none + return nullptr; + }); + ASSERT_FALSE(got_null_cfgs_container); + } + + // Make sure no dual bidir SWB configs were returned + ASSERT_EQ(0, num_of_dual_bidir_swb_configs); } TEST_F(CodecManagerTestHost, test_dont_update_broadcast_offloader) { diff --git a/system/bta/le_audio/device_groups.cc b/system/bta/le_audio/device_groups.cc index cfc9589b42..1370c6e7fe 100644 --- a/system/bta/le_audio/device_groups.cc +++ b/system/bta/le_audio/device_groups.cc @@ -28,6 +28,7 @@ #include "btm_iso_api.h" #include "hci/controller_interface.h" #include "internal_include/bt_trace.h" +#include "le_audio/codec_manager.h" #include "le_audio/le_audio_types.h" #include "le_audio_set_configuration_provider.h" #include "le_audio_utils.h" @@ -83,23 +84,32 @@ bool LeAudioDeviceGroup::IsAnyDeviceConnected(void) const { int LeAudioDeviceGroup::Size(void) const { return leAudioDevices_.size(); } -int LeAudioDeviceGroup::NumOfConnected(LeAudioContextType context_type) const { - if (leAudioDevices_.empty()) return 0; +int LeAudioDeviceGroup::NumOfConnected() const { + /* return number of connected devices from the set*/ + return std::count_if( + leAudioDevices_.begin(), leAudioDevices_.end(), [](auto& iter) { + auto dev = iter.lock(); + if (dev) { + return (dev->conn_id_ != GATT_INVALID_CONN_ID) && + (dev->GetConnectionState() == DeviceConnectState::CONNECTED); + } + return false; + }); +} - bool check_context_type = (context_type != LeAudioContextType::RFU); - AudioContexts type_set(context_type); +int LeAudioDeviceGroup::NumOfAvailableForDirection(int direction) const { + bool check_ase_count = direction < types::kLeAudioDirectionBoth; - /* return number of connected devices from the set*/ + /* return number of connected devices from the set with supported context */ return std::count_if( - leAudioDevices_.begin(), leAudioDevices_.end(), - [type_set, check_context_type](auto& iter) { + leAudioDevices_.begin(), leAudioDevices_.end(), [&](auto& iter) { auto dev = iter.lock(); if (dev) { - if (dev->conn_id_ == GATT_INVALID_CONN_ID) return false; - if (dev->GetConnectionState() != DeviceConnectState::CONNECTED) + if (check_ase_count && (dev->GetAseCount(direction) == 0)) { return false; - if (!check_context_type) return true; - return dev->GetSupportedContexts().test_any(type_set); + } + return (dev->conn_id_ != GATT_INVALID_CONN_ID) && + (dev->GetConnectionState() == DeviceConnectState::CONNECTED); } return false; }); @@ -644,7 +654,8 @@ uint8_t LeAudioDeviceGroup::GetPhyBitmask(uint8_t direction) const { // local supported PHY's uint8_t phy_bitfield = bluetooth::hci::kIsoCigPhy1M; - if (bluetooth::shim::GetController()->SupportsBle2mPhy()) + auto controller = bluetooth::shim::GetController(); + if (controller && controller->SupportsBle2mPhy()) phy_bitfield |= bluetooth::hci::kIsoCigPhy2M; if (!leAudioDevice) { @@ -740,10 +751,12 @@ uint16_t LeAudioDeviceGroup::GetRemoteDelay(uint8_t direction) const { uint16_t remote_delay_ms = 0; uint32_t presentation_delay; - if (!GetPresentationDelay(&presentation_delay, direction)) { + if (!GetFirstActiveDevice() || + !GetPresentationDelay(&presentation_delay, direction)) { /* This should never happens at stream request time but to be safe return * some sample value to not break streaming */ + log::error("No active device available. Default value used."); return 100; } @@ -765,6 +778,7 @@ bool LeAudioDeviceGroup::UpdateAudioSetConfigurationCache( LeAudioContextType ctx_type) const { CodecManager::UnicastConfigurationRequirements requirements = { .audio_context_type = ctx_type}; + auto new_conf = CodecManager::GetInstance()->GetCodecConfig( requirements, std::bind(&LeAudioDeviceGroup::FindFirstSupportedConfiguration, this, @@ -937,8 +951,7 @@ types::LeAudioConfigurationStrategy LeAudioDeviceGroup::GetGroupSinkStrategy() auto channel_count_bitmap = device->GetSupportedAudioChannelCounts(types::kLeAudioDirectionSink); log::debug("Supported channel counts for group {} (device {}) is {}", - group_id_, ADDRESS_TO_LOGGABLE_CSTR(device->address_), - channel_count_bitmap); + group_id_, device->address_, channel_count_bitmap); if (channel_count_bitmap == 1) { return types::LeAudioConfigurationStrategy::STEREO_TWO_CISES_PER_DEVICE; } @@ -1264,10 +1277,9 @@ bool CheckIfStrategySupported(types::LeAudioConfigurationStrategy strategy, auto channel_count_mask = device.GetSupportedAudioChannelCounts(direction); - auto requested_channel_count = conf.codec.params.GetAsCoreCodecConfig() - .GetChannelCountPerIsoStream(); - log::debug("Requested channel count: {}, supp. channel counts: {}", - requested_channel_count, loghex(channel_count_mask)); + auto requested_channel_count = conf.codec.GetChannelCountPerIsoStream(); + log::debug("Requested channel count: {}, supp. channel counts: 0x{:x}", + requested_channel_count, channel_count_mask); /* Return true if requested channel count is set in the supported channel * counts. In the channel_count_mask, bit 0 is set when 1 channel is @@ -1289,22 +1301,6 @@ bool CheckIfStrategySupported(types::LeAudioConfigurationStrategy strategy, bool LeAudioDeviceGroup::IsAudioSetConfigurationSupported( const CodecManager::UnicastConfigurationRequirements& requirements, const set_configurations::AudioSetConfiguration* audio_set_conf) const { - /* When at least one device supports the configuration context, configure - * for these devices only. Otherwise configure for all devices - we will - * not put this context into the metadata if not supported. - */ - auto num_of_connected = NumOfConnected(requirements.audio_context_type); - if (num_of_connected == 0) { - num_of_connected = NumOfConnected(); - } - if (!set_configurations::check_if_may_cover_scenario(audio_set_conf, - num_of_connected)) { - log::debug("cannot cover scenario {}, num. of connected: {}", - bluetooth::common::ToString(requirements.audio_context_type), - num_of_connected); - return false; - } - /* TODO For now: set ase if matching with first pac. * 1) We assume as well that devices will match requirements in order * e.g. 1 Device - 1 Requirement, 2 Device - 2 Requirement etc. @@ -1313,41 +1309,50 @@ bool LeAudioDeviceGroup::IsAudioSetConfigurationSupported( * 3) ASEs should be filled according to performance profile. */ auto required_snk_strategy = GetGroupSinkStrategy(); + bool status = false; for (auto direction : {types::kLeAudioDirectionSink, types::kLeAudioDirectionSource}) { log::debug("Looking for configuration: {} - {}", audio_set_conf->name, - (direction == types::kLeAudioDirectionSink ? "Sink" : "Source")); + direction == types::kLeAudioDirectionSink ? "Sink" : "Source"); auto const& ase_confs = audio_set_conf->confs.get(direction); + if (ase_confs.empty()) { + log::debug("No configurations for direction {}, skip it.", + (int)direction); + continue; + } - log::assert_that( - audio_set_conf->topology_info.has_value(), - "No topology info, which is required to properly configure the ASEs"); - auto const strategy = - audio_set_conf->topology_info->strategy.get(direction); - auto const device_cnt = - audio_set_conf->topology_info->device_count.get(direction); - auto const ase_cnt = ase_confs.size(); + // In some tests we expect the configuration to be there even when the + // contexts are not supported. Then we might want to configure the device + // but use UNSPECIFIED which is always supported (but can be unavailable) + auto device_cnt = NumOfAvailableForDirection(direction); + if (device_cnt == 0) { + if (bluetooth::csis::CsisClient::IsCsisClientRunning()) { + device_cnt = + bluetooth::csis::CsisClient::Get()->GetDesiredSize(group_id_); + } + if (device_cnt == 0) { + log::error("Device count is 0"); + continue; + } + } + auto const ase_cnt = ase_confs.size(); if (ase_cnt == 0) { log::error("ASE count is 0"); continue; } - if (device_cnt == 0) { - log::error("Device count is 0"); - continue; - } uint8_t const max_required_ase_per_dev = ase_cnt / device_cnt + (ase_cnt % device_cnt); - uint8_t required_device_cnt = device_cnt; - uint8_t active_ase_cnt = 0; + // Use strategy for the whole group (not only the connected devices) + auto const strategy = utils::GetStrategyForAseConfig(ase_confs, device_cnt); log::debug( "Number of devices: {}, number of ASEs: {}, Max ASE per device: {} " - "Strategy: {}", - required_device_cnt, ase_cnt, max_required_ase_per_dev, - static_cast<int>(strategy)); + "config strategy: {}, group strategy: {}", + device_cnt, ase_cnt, max_required_ase_per_dev, + static_cast<int>(strategy), (int)required_snk_strategy); if (direction == types::kLeAudioDirectionSink && strategy != required_snk_strategy) { @@ -1357,6 +1362,8 @@ bool LeAudioDeviceGroup::IsAudioSetConfigurationSupported( return false; } + uint8_t required_device_cnt = device_cnt; + uint8_t active_ase_cnt = 0; for (auto* device = GetFirstDevice(); device != nullptr && required_device_cnt > 0; device = GetNextDevice(device)) { @@ -1376,7 +1383,7 @@ bool LeAudioDeviceGroup::IsAudioSetConfigurationSupported( if (!utils::GetConfigurationSupportedPac(pacs, ent.codec)) { log::debug( "Insufficient PAC for {}", - (direction == types::kLeAudioDirectionSink ? "sink" : "source")); + direction == types::kLeAudioDirectionSink ? "sink" : "source"); continue; } @@ -1405,11 +1412,13 @@ bool LeAudioDeviceGroup::IsAudioSetConfigurationSupported( if (required_device_cnt > 0) { /* Don't left any active devices if requirements are not met */ - log::debug( - "Could not configure all the devices for direction: {}", - (direction == types::kLeAudioDirectionSink ? "Sink" : "Source")); + log::debug("Could not configure all the devices for direction: {}", + direction == types::kLeAudioDirectionSink ? "Sink" : "Source"); return false; } + + // At least one direction can be configured + status = true; } /* when disabling 32k dual mic, for later join case, we need to @@ -1426,9 +1435,13 @@ bool LeAudioDeviceGroup::IsAudioSetConfigurationSupported( } } - log::debug("Chosen ASE Configuration for group: {}, configuration: {}", - this->group_id_, audio_set_conf->name); - return true; + if (status) { + log::debug("Chosen ASE Configuration for group: {}, configuration: {}", + group_id_, audio_set_conf->name); + } else { + log::error("Could not configure either direction for group {}", group_id_); + } + return status; } /* This method should choose aproperiate ASEs to be active and set a cached @@ -1439,19 +1452,6 @@ bool LeAudioDeviceGroup::ConfigureAses( LeAudioContextType context_type, const types::BidirectionalPair<AudioContexts>& metadata_context_types, const types::BidirectionalPair<std::vector<uint8_t>>& ccid_lists) { - /* When at least one device supports the configuration context, configure - * for these devices only. Otherwise configure for all devices - we will - * not put this context into the metadata if not supported. - */ - auto num_of_connected = NumOfConnected(context_type); - if (num_of_connected == 0) { - num_of_connected = NumOfConnected(); - } - if (!set_configurations::check_if_may_cover_scenario(audio_set_conf, - num_of_connected)) { - return false; - } - bool reuse_cis_id = GetState() == AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED; @@ -1481,7 +1481,8 @@ bool LeAudioDeviceGroup::ConfigureAses( continue; } - auto required_device_cnt = NumOfConnected(); + auto const max_required_device_cnt = NumOfAvailableForDirection(direction); + auto required_device_cnt = max_required_device_cnt; uint8_t active_ase_cnt = 0; auto configuration_closure = [&](LeAudioDevice* dev) -> void { @@ -1495,8 +1496,8 @@ bool LeAudioDeviceGroup::ConfigureAses( return; } - if (!dev->ConfigureAses(audio_set_conf, direction, context_type, - &active_ase_cnt, + if (!dev->ConfigureAses(audio_set_conf, max_required_device_cnt, + direction, context_type, &active_ase_cnt, group_audio_locations_memo.get(direction), metadata_context_types.get(direction), ccid_lists.get(direction), reuse_cis_id)) { @@ -1665,10 +1666,7 @@ void LeAudioDeviceGroup::RemoveCisFromStreamIfNeeded( auto ases_pair = leAudioDevice->GetAsesByCisConnHdl(cis_conn_hdl); if (ases_pair.get(dir) && cis_conn_hdl == pair.first) { params.num_of_devices--; - params.num_of_channels -= - ases_pair.get(dir) - ->codec_config.GetAsCoreCodecConfig() - .GetChannelCountPerIsoStream(); + params.num_of_channels -= ases_pair.get(dir)->channel_count; params.audio_channel_allocation &= ~pair.second; } return (ases_pair.get(dir) && cis_conn_hdl == pair.first); @@ -1841,17 +1839,6 @@ LeAudioDeviceGroup::FindFirstSupportedConfiguration( bluetooth::common::ToString(requirements.audio_context_type), NumOfConnected()); - auto num_of_connected = NumOfConnected(requirements.audio_context_type); - if (num_of_connected == 0) { - num_of_connected = NumOfConnected(); - } - /* Filter out device set for all scenarios */ - if (!set_configurations::check_if_may_cover_scenario(confs, - num_of_connected)) { - log::debug(", group is unable to cover scenario"); - return nullptr; - } - /* Filter out device set for each end every scenario */ for (const auto& conf : *confs) { log::assert_that(conf != nullptr, "confs should not be null"); @@ -2044,7 +2031,7 @@ void LeAudioDeviceGroup::Dump(int fd, int active_group_id) const { LeAudioDeviceGroup* LeAudioDeviceGroups::Add(int group_id) { /* Get first free group id */ if (FindById(group_id)) { - log::error("group already exists, id: {}", loghex(group_id)); + log::error("group already exists, id: 0x{:x}", group_id); return nullptr; } diff --git a/system/bta/le_audio/device_groups.h b/system/bta/le_audio/device_groups.h index 16d15fca85..5bcdc0ea81 100644 --- a/system/bta/le_audio/device_groups.h +++ b/system/bta/le_audio/device_groups.h @@ -151,8 +151,8 @@ class LeAudioDeviceGroup { bool IsEmpty(void) const; bool IsAnyDeviceConnected(void) const; int Size(void) const; - int NumOfConnected(types::LeAudioContextType context_type = - types::LeAudioContextType::RFU) const; + int NumOfConnected() const; + int NumOfAvailableForDirection(int direction) const; bool Activate(types::LeAudioContextType context_type, const types::BidirectionalPair<types::AudioContexts>& metadata_context_types, diff --git a/system/bta/le_audio/devices.cc b/system/bta/le_audio/devices.cc index 2c5f64fa16..98198bdfba 100644 --- a/system/bta/le_audio/devices.cc +++ b/system/bta/le_audio/devices.cc @@ -27,6 +27,8 @@ #include "common/strings.h" #include "hci/controller_interface.h" #include "internal_include/bt_trace.h" +#include "le_audio/codec_manager.h" +#include "le_audio/le_audio_types.h" #include "le_audio_log_history.h" #include "le_audio_utils.h" #include "main/shim/entry.h" @@ -222,27 +224,25 @@ bool LeAudioDevice::IsAudioSetConfigurationSupported( if (confs.size() == 0) continue; log::info("Looking for requirements: {} - {}", audio_set_conf->name, - (direction == 1 ? "snk" : "src")); + direction == 1 ? "snk" : "src"); auto const& pacs = (direction == types::kLeAudioDirectionSink) ? snk_pacs_ : src_pacs_; for (const auto& ent : confs) { if (!utils::GetConfigurationSupportedPac(pacs, ent.codec)) { - log::info("Configuration is NOT supported by device {}", - ADDRESS_TO_LOGGABLE_CSTR(address_)); + log::info("Configuration is NOT supported by device {}", address_); return false; } } } - log::info("Configuration is supported by device {}", - ADDRESS_TO_LOGGABLE_CSTR(address_)); + log::info("Configuration is supported by device {}", address_); return true; } bool LeAudioDevice::ConfigureAses( const set_configurations::AudioSetConfiguration* audio_set_conf, - uint8_t direction, LeAudioContextType context_type, + uint8_t num_of_devices, uint8_t direction, LeAudioContextType context_type, uint8_t* number_of_already_active_group_ase, AudioLocations& group_audio_locations_memo, const AudioContexts& metadata_context_types, @@ -260,50 +260,63 @@ bool LeAudioDevice::ConfigureAses( return false; } - log::assert_that( - audio_set_conf->topology_info.has_value(), - "No topology info, which is required to properly configure the ASEs"); - auto device_cnt = audio_set_conf->topology_info->device_count.get(direction); - auto strategy = audio_set_conf->topology_info->strategy.get(direction); - auto const& ents = audio_set_conf->confs.get(direction); + auto const& ase_configs = audio_set_conf->confs.get(direction); + auto const& pacs = + (direction == types::kLeAudioDirectionSink) ? snk_pacs_ : src_pacs_; + for (size_t i = 0; i < ase_configs.size() && ase; ++i) { + auto const& ase_cfg = ase_configs.at(i); + if (!utils::GetConfigurationSupportedPac(pacs, ase_cfg.codec)) { + return false; + } + } /* The number_of_already_active_group_ase keeps all the active ases - * in other devices in the group. + * in other devices in the group for the given direction. * This function counts active ases only for this device, and we count here * new active ases and already active ases which we want to reuse in the * scenario */ uint8_t active_ases = *number_of_already_active_group_ase; - uint8_t max_required_ase_per_dev = - ents.size() / device_cnt + (ents.size() % device_cnt); - auto const& pacs = - (direction == types::kLeAudioDirectionSink) ? snk_pacs_ : src_pacs_; + auto audio_locations = (direction == types::kLeAudioDirectionSink) + ? snk_audio_locations_ + : src_audio_locations_; // Before we activate the ASEs, make sure we have the right configuration + uint8_t max_required_ase_per_dev = ase_configs.size() / num_of_devices + + (ase_configs.size() % num_of_devices); int needed_ase = std::min((int)(max_required_ase_per_dev), - (int)(ents.size() - active_ases)); + (int)(ase_configs.size() - active_ases)); for (int i = 0; i < needed_ase; ++i) { - auto const& ase_cfg = ents.at(i); + auto const& ase_cfg = ase_configs.at(i); if (!utils::GetConfigurationSupportedPac(pacs, ase_cfg.codec)) { + log::error("No matching PAC found. Stop the activation."); return false; } } - AudioLocations audio_locations = 0; - - /* Check direction and if audio location allows to create more cise */ - if (direction == types::kLeAudioDirectionSink) { - audio_locations = snk_audio_locations_; - } else { - audio_locations = src_audio_locations_; + auto strategy = utils::GetStrategyForAseConfig(ase_configs, num_of_devices); + + // Make sure we configure a single microphone if Dual Bidir SWB is not + // supported. + if (direction == types::kLeAudioDirectionSource && + !CodecManager::GetInstance()->IsDualBiDirSwbSupported() && + (active_ases != 0)) { + if (CodecManager::GetInstance()->CheckCodecConfigIsDualBiDirSwb( + *audio_set_conf)) { + log::error( + "Trying to configure the dual bidir SWB, but the feature is " + "disabled. This should not happen! Skipping ASE activation."); + return true; + } } - for (int i = 0; needed_ase && ase; needed_ase--) { + for (int i = 0; i < needed_ase && ase; ++i) { + auto const& ase_cfg = ase_configs.at(i); ase->active = true; ase->configured_for_context_type = context_type; - ase->is_codec_in_controller = ents[i].is_codec_in_controller; - ase->data_path_id = ents[i].data_path_id; + ase->is_codec_in_controller = ase_cfg.is_codec_in_controller; + ase->data_path_id = ase_cfg.data_path_id; active_ases++; /* In case of late connect, we could be here for STREAMING ase. @@ -315,9 +328,10 @@ bool LeAudioDevice::ConfigureAses( if (ase->state == AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED) ase->reconfigure = true; - ase->target_latency = ents[i].qos.target_latency; - ase->codec_id = ents[i].codec.id; - ase->codec_config = ents[i].codec.params; + ase->target_latency = ase_cfg.qos.target_latency; + ase->codec_id = ase_cfg.codec.id; + ase->codec_config = ase_cfg.codec.params; + ase->channel_count = ase_cfg.codec.channel_count_per_iso_stream; /* Let's choose audio channel allocation if not set */ ase->codec_config.Add( @@ -332,18 +346,13 @@ bool LeAudioDevice::ConfigureAses( ase->codec_config.Add( codec_spec_conf::kLeAudioLtvTypeCodecFrameBlocksPerSdu, GetMaxCodecFramesPerSduFromPac( - utils::GetConfigurationSupportedPac(pacs, ents.at(i).codec))); + utils::GetConfigurationSupportedPac(pacs, ase_cfg.codec))); } - /* Recalculate Max SDU size from the Core codec config */ - ase->qos_config.max_sdu_size = - ase->codec_config.GetAsCoreCodecConfig().CalculateMaxSduSize(); - /* Get the SDU interval from the Core codec config */ - ase->qos_config.sdu_interval = - ase->codec_config.GetAsCoreCodecConfig().GetFrameDurationUs(); - - ase->qos_config.retrans_nb = ents[i].qos.retransmission_number; - ase->qos_config.max_transport_latency = ents[i].qos.max_transport_latency; + ase->qos_config.sdu_interval = ase_cfg.qos.sduIntervalUs; + ase->qos_config.max_sdu_size = ase_cfg.qos.maxSdu; + ase->qos_config.retrans_nb = ase_cfg.qos.retransmission_number; + ase->qos_config.max_transport_latency = ase_cfg.qos.max_transport_latency; SetMetadataToAse(ase, metadata_context_types, ccid_lists); } @@ -351,15 +360,14 @@ bool LeAudioDevice::ConfigureAses( log::debug( "device={}, activated ASE id={}, direction={}, max_sdu_size={}, " "cis_id={}, target_latency={}", - address_, ase->id, (direction == 1 ? "snk" : "src"), - ase->qos_config.max_sdu_size, ase->cis_id, ents[i].qos.target_latency); + address_, ase->id, direction == 1 ? "snk" : "src", + ase->qos_config.max_sdu_size, ase->cis_id, ase_cfg.qos.target_latency); /* Try to use the already active ASE */ ase = GetNextActiveAseWithSameDirection(ase); if (ase == nullptr) { ase = GetFirstInactiveAse(direction, reuse_cis_id); } - ++i; } *number_of_already_active_group_ase = active_ases; diff --git a/system/bta/le_audio/devices.h b/system/bta/le_audio/devices.h index 756bd27635..febee4075f 100644 --- a/system/bta/le_audio/devices.h +++ b/system/bta/le_audio/devices.h @@ -180,7 +180,8 @@ class LeAudioDevice { const set_configurations::AudioSetConfiguration* audio_set_conf) const; bool ConfigureAses( const set_configurations::AudioSetConfiguration* audio_set_conf, - uint8_t direction, types::LeAudioContextType context_type, + uint8_t group_size, uint8_t direction, + types::LeAudioContextType context_type, uint8_t* number_of_already_active_group_ase, types::AudioLocations& group_audio_locations_out, const types::AudioContexts& metadata_context_types, diff --git a/system/bta/le_audio/devices_test.cc b/system/bta/le_audio/devices_test.cc index 465e405384..50a0d42172 100644 --- a/system/bta/le_audio/devices_test.cc +++ b/system/bta/le_audio/devices_test.cc @@ -24,12 +24,16 @@ #include "btif_storage_mock.h" #include "btm_api_mock.h" #include "device_groups.h" +#include "hardware/bt_le_audio.h" +#include "hci/controller_interface_mock.h" +#include "le_audio/le_audio_utils.h" #include "le_audio_set_configuration_provider.h" #include "le_audio_types.h" #include "mock_codec_manager.h" #include "mock_csis_client.h" #include "os/log.h" #include "stack/btm/btm_int_types.h" +#include "test/mock/mock_main_shim_entry.h" tACL_CONN* btm_bda_to_acl(const RawAddress& bda, tBT_TRANSPORT transport) { return nullptr; @@ -52,6 +56,7 @@ using ::bluetooth::le_audio::types::CisType; using ::bluetooth::le_audio::types::LeAudioContextType; using testing::_; using testing::Invoke; +using testing::NiceMock; using testing::Return; using testing::Test; @@ -470,6 +475,7 @@ class LeAudioAseConfigurationTest : public Test { void SetUp() override { group_ = new LeAudioDeviceGroup(group_id_); bluetooth::manager::SetMockBtmInterface(&btm_interface_); + bluetooth::hci::testing::mock_controller_ = &controller_interface_; auto codec_location = ::bluetooth::le_audio::types::CodecLocation::HOST; bluetooth::le_audio::AudioSetConfigurationProvider::Initialize( @@ -500,21 +506,48 @@ class LeAudioAseConfigurationTest : public Test { ON_CALL(*mock_codec_manager_, GetCodecLocation()) .WillByDefault(Return(location)); // Regardless of the codec location, return all the possible configurations + ON_CALL(*mock_codec_manager_, IsDualBiDirSwbSupported) + .WillByDefault(Return(true)); ON_CALL(*mock_codec_manager_, GetCodecConfig) .WillByDefault(Invoke( [](const bluetooth::le_audio::CodecManager:: UnicastConfigurationRequirements& requirements, bluetooth::le_audio::CodecManager::UnicastConfigurationVerifier verifier) { - auto configs = - bluetooth::le_audio::AudioSetConfigurationProvider::Get() - ->GetConfigurations(requirements.audio_context_type); - auto cfg = verifier(requirements, configs); + auto filtered = + *bluetooth::le_audio::AudioSetConfigurationProvider::Get() + ->GetConfigurations(requirements.audio_context_type); + // Filter out the dual bidir SWB configurations + if (!bluetooth::le_audio::CodecManager::GetInstance() + ->IsDualBiDirSwbSupported()) { + filtered.erase( + std::remove_if(filtered.begin(), filtered.end(), + [](auto const& el) { + if (el->confs.source.empty()) return false; + return AudioSetConfigurationProvider::Get() + ->CheckConfigurationIsDualBiDirSwb( + *el); + }), + filtered.end()); + } + auto cfg = verifier(requirements, &filtered); if (cfg == nullptr) { return std::unique_ptr<AudioSetConfiguration>(nullptr); } return std::make_unique<AudioSetConfiguration>(*cfg); })); + ON_CALL(*mock_codec_manager_, CheckCodecConfigIsBiDirSwb) + .WillByDefault(Invoke([](const bluetooth::le_audio::set_configurations:: + AudioSetConfiguration& config) { + return AudioSetConfigurationProvider::Get() + ->CheckConfigurationIsBiDirSwb(config); + })); + ON_CALL(*mock_codec_manager_, CheckCodecConfigIsDualBiDirSwb) + .WillByDefault(Invoke([](const bluetooth::le_audio::set_configurations:: + AudioSetConfiguration& config) { + return AudioSetConfigurationProvider::Get() + ->CheckConfigurationIsDualBiDirSwb(config); + })); } void TearDown() override { @@ -614,32 +647,25 @@ class LeAudioAseConfigurationTest : public Test { bool TestGroupAseConfigurationVerdict( const TestGroupAseConfigurationData& data, uint8_t directions_to_verify) { - uint8_t active_channel_num_snk = 0; - uint8_t active_channel_num_src = 0; + BidirectionalPair<uint8_t> active_channel_num = {0, 0}; if (directions_to_verify == 0) return false; if (data.device->HaveActiveAse() == 0) return false; for (ase* ase = data.device->GetFirstActiveAse(); ase; ase = data.device->GetNextActiveAse(ase)) { - auto core_config = ase->codec_config.GetAsCoreCodecConfig(); - - if (ase->direction == kLeAudioDirectionSink) - active_channel_num_snk += core_config.GetChannelCountPerIsoStream(); - else - active_channel_num_src += core_config.GetChannelCountPerIsoStream(); + active_channel_num.get(ase->direction) += ase->channel_count; } bool result = true; if (directions_to_verify & kLeAudioDirectionSink) { - result &= - (data.expected_active_channel_num_snk == active_channel_num_snk); + result &= (data.expected_active_channel_num_snk == + active_channel_num.get(kLeAudioDirectionSink)); } if (directions_to_verify & kLeAudioDirectionSource) { - result &= - (data.expected_active_channel_num_src == active_channel_num_src); + result &= (data.expected_active_channel_num_src == + active_channel_num.get(kLeAudioDirectionSource)); } - return result; } @@ -738,32 +764,14 @@ class LeAudioAseConfigurationTest : public Test { for (auto direction : {kLeAudioDirectionSink, kLeAudioDirectionSource}) { auto const& ase_confs = audio_set_conf->confs.get(direction); - ASSERT_TRUE(audio_set_conf->topology_info.has_value()); - auto device_cnt = - audio_set_conf->topology_info->device_count.get(direction); - auto strategy = - audio_set_conf->topology_info->strategy.get(direction); + auto strategy = bluetooth::le_audio::utils::GetStrategyForAseConfig( + ase_confs, data_size); auto const ase_cnt = ase_confs.size(); if (ase_cnt == 0) { // Skip the direction if not available continue; } - if (device_cnt == 0) { - log::error("Device count is 0"); - continue; - } - - /* We are interested in the configurations which contains exact number - * of devices and number of ases is same the number of expected ases - * to active - */ - if (device_cnt != data_size) { - log::debug("Device count mismatch device!=data ({}!={})", - static_cast<int>(device_cnt), - static_cast<int>(data_size)); - interesting_configuration = false; - } /* Make sure the strategy is the expected one */ if (direction == kLeAudioDirectionSink && @@ -956,6 +964,198 @@ class LeAudioAseConfigurationTest : public Test { } } + void TestSingleDevDualBidir(LeAudioDevice* device, + LeAudioContextType context_type) { + // Build PACs for device + PublishedAudioCapabilitiesBuilder snk_pac_builder, src_pac_builder; + snk_pac_builder.Reset(); + src_pac_builder.Reset(); + + const uint32_t supported_octets_per_codec_frame_80 = 80; + const uint32_t supported_octets_per_codec_frame_40 = 40; + const uint32_t supported_codec_frames_per_sdu = 1; + CodecConfigSetting swb = { + .id = LeAudioCodecIdLc3, + .params = LeAudioLtvMap({ + {codec_spec_conf::kLeAudioLtvTypeSamplingFreq, + UINT8_TO_VEC_UINT8(codec_spec_conf::kLeAudioSamplingFreq32000Hz)}, + {codec_spec_conf::kLeAudioLtvTypeFrameDuration, + UINT8_TO_VEC_UINT8(codec_spec_conf::kLeAudioCodecFrameDur10000us)}, + {codec_spec_conf::kLeAudioLtvTypeOctetsPerCodecFrame, + UINT16_TO_VEC_UINT8(supported_octets_per_codec_frame_80)}, + {codec_spec_conf::kLeAudioLtvTypeCodecFrameBlocksPerSdu, + UINT8_TO_VEC_UINT8(supported_codec_frames_per_sdu)}, + }), + .channel_count_per_iso_stream = 1}; + auto swb_config = AudioSetConfiguration({ + .name = "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_SWB", + .confs = {.sink = {AseConfiguration(swb), AseConfiguration(swb)}, + .source = {AseConfiguration(swb), AseConfiguration(swb)}}, + }); + + ASSERT_FALSE(swb.params.IsEmpty()); + ASSERT_TRUE(swb.params.Find(codec_spec_conf::kLeAudioLtvTypeSamplingFreq) + .has_value()); + + CodecConfigSetting non_swb = { + .id = LeAudioCodecIdLc3, + .params = LeAudioLtvMap({ + {codec_spec_conf::kLeAudioLtvTypeSamplingFreq, + UINT8_TO_VEC_UINT8(codec_spec_conf::kLeAudioSamplingFreq16000Hz)}, + {codec_spec_conf::kLeAudioLtvTypeFrameDuration, + UINT8_TO_VEC_UINT8(codec_spec_conf::kLeAudioCodecFrameDur10000us)}, + {codec_spec_conf::kLeAudioLtvTypeOctetsPerCodecFrame, + UINT16_TO_VEC_UINT8(supported_octets_per_codec_frame_40)}, + {codec_spec_conf::kLeAudioLtvTypeCodecFrameBlocksPerSdu, + UINT8_TO_VEC_UINT8(supported_codec_frames_per_sdu)}, + }), + .channel_count_per_iso_stream = 1}; + auto non_swb_config = AudioSetConfiguration({ + .name = + "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_NON_SWB", + .confs = {.sink = {AseConfiguration(non_swb), + AseConfiguration(non_swb)}, + .source = {AseConfiguration(non_swb), + AseConfiguration(non_swb)}}, + }); + AudioSetConfigurations configs = {{&swb_config, &non_swb_config}}; + + // Support single channel per ASE to activate two ASES on both direction + for (auto config : configs) { + for (const auto& entry : config->confs.sink) { + snk_pac_builder.Add(entry.codec, + kLeAudioCodecChannelCountSingleChannel); + } + for (const auto& entry : config->confs.source) { + src_pac_builder.Add(entry.codec, + kLeAudioCodecChannelCountSingleChannel); + } + } + + // Inject `configs` as there's no such config in the json file + ON_CALL(*mock_codec_manager_, GetCodecConfig) + .WillByDefault(Invoke( + [&configs]( + const bluetooth::le_audio::CodecManager:: + UnicastConfigurationRequirements& requirements, + bluetooth::le_audio::CodecManager::UnicastConfigurationVerifier + verifier) { + auto filtered = configs; + // Filter out the dual bidir SWB configurations + if (!bluetooth::le_audio::CodecManager::GetInstance() + ->IsDualBiDirSwbSupported()) { + filtered.erase( + std::remove_if(filtered.begin(), filtered.end(), + [](auto const& el) { + if (el->confs.source.empty()) return false; + return AudioSetConfigurationProvider::Get() + ->CheckConfigurationIsDualBiDirSwb( + *el); + }), + filtered.end()); + } + auto cfg = verifier(requirements, &filtered); + if (cfg == nullptr) { + return std::unique_ptr<AudioSetConfiguration>(nullptr); + } + return std::make_unique<AudioSetConfiguration>(*cfg); + })); + + // Make two ASES available in both directions with equal capabilities + device->snk_pacs_ = snk_pac_builder.Get(); + device->src_pacs_ = src_pac_builder.Get(); + + ASSERT_TRUE(group_->Configure(context_type, + {.sink = AudioContexts(context_type), + .source = AudioContexts(context_type)})); + + // Verify Dual-Bidir - the amount of ASES configured + TestGroupAseConfigurationData data[] = { + {device, kLeAudioCodecChannelCountSingleChannel, + kLeAudioCodecChannelCountSingleChannel, 2, 2}}; + TestGroupAseConfigurationVerdict( + data[0], kLeAudioDirectionSink | kLeAudioDirectionSource); + } + + /* Helper */ + static const AudioSetConfiguration* getSpecificConfiguration( + const char* config_name, LeAudioContextType context) { + auto all_configurations = + ::bluetooth::le_audio::AudioSetConfigurationProvider::Get() + ->GetConfigurations(context); + + if (all_configurations == nullptr) return nullptr; + if (all_configurations->end() == all_configurations->begin()) + return nullptr; + + auto iter = + std::find_if(all_configurations->begin(), all_configurations->end(), + [config_name](auto& configuration) { + return configuration->name == config_name; + }); + if (iter == all_configurations->end()) return nullptr; + return *iter; + } + + void TestDualDevDualBidir(LeAudioDevice* left, LeAudioDevice* right, + LeAudioContextType context_type) { + // Build PACs for device + PublishedAudioCapabilitiesBuilder snk_pac_builder, src_pac_builder; + snk_pac_builder.Reset(); + src_pac_builder.Reset(); + + /* Create PACs for conversational scenario, SWB and non SWB */ + for (auto config : + {getSpecificConfiguration( + "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_1", + context_type), + getSpecificConfiguration( + "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_1", + context_type)}) { + ASSERT_NE(nullptr, config); + for (const auto& entry : (*config).confs.sink) { + snk_pac_builder.Add(entry.codec, + kLeAudioCodecChannelCountSingleChannel); + } + for (const auto& entry : (*config).confs.source) { + src_pac_builder.Add(entry.codec, + kLeAudioCodecChannelCountSingleChannel); + } + } + + // Add pacs for remote to support the configs above + for (auto& dev : {left, right}) { + dev->snk_pacs_ = snk_pac_builder.Get(); + dev->src_pacs_ = src_pac_builder.Get(); + } + + /* Change location as by default it is stereo */ + left->snk_audio_locations_ = + ::bluetooth::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft; + left->src_audio_locations_ = + ::bluetooth::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft; + right->snk_audio_locations_ = + ::bluetooth::le_audio::codec_spec_conf::kLeAudioLocationFrontRight; + right->src_audio_locations_ = + ::bluetooth::le_audio::codec_spec_conf::kLeAudioLocationFrontRight; + group_->ReloadAudioLocations(); + + ASSERT_TRUE(group_->Configure(context_type, + {.sink = AudioContexts(context_type), + .source = AudioContexts(context_type)})); + + // Verify the amount of ASES configured + TestGroupAseConfigurationData data[] = { + {left, kLeAudioCodecChannelCountSingleChannel, + kLeAudioCodecChannelCountSingleChannel, 1, 1}, + {right, kLeAudioCodecChannelCountSingleChannel, + kLeAudioCodecChannelCountSingleChannel, 1, 1}}; + TestGroupAseConfigurationVerdict( + data[0], kLeAudioDirectionSink | kLeAudioDirectionSource); + TestGroupAseConfigurationVerdict( + data[1], kLeAudioDirectionSink | kLeAudioDirectionSource); + } + void SetAsesToCachedConfiguration(LeAudioDevice* device, LeAudioContextType context_type, uint8_t directions) { @@ -974,30 +1174,13 @@ class LeAudioAseConfigurationTest : public Test { LeAudioDeviceGroup* group_ = nullptr; bluetooth::manager::MockBtmInterface btm_interface_; MockCsisClient mock_csis_client_module_; + NiceMock<bluetooth::hci::testing::MockControllerInterface> + controller_interface_; bluetooth::le_audio::CodecManager* codec_manager_; MockCodecManager* mock_codec_manager_; }; -/* Helper */ -const AudioSetConfiguration* getSpecificConfiguration( - const char* config_name, LeAudioContextType context) { - auto all_configurations = - ::bluetooth::le_audio::AudioSetConfigurationProvider::Get() - ->GetConfigurations(context); - - if (all_configurations == nullptr) return nullptr; - if (all_configurations->end() == all_configurations->begin()) return nullptr; - - auto iter = - std::find_if(all_configurations->begin(), all_configurations->end(), - [config_name](auto& configuration) { - return configuration->name == config_name; - }); - if (iter == all_configurations->end()) return nullptr; - return *iter; -} - TEST_F(LeAudioAseConfigurationTest, test_context_update) { LeAudioDevice* left = AddTestDevice(1, 1); LeAudioDevice* right = AddTestDevice(1, 1); @@ -1016,11 +1199,11 @@ TEST_F(LeAudioAseConfigurationTest, test_context_update) { /* Put the PACS */ auto conversational_configuration = getSpecificConfiguration( - "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency", + "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency", LeAudioContextType::CONVERSATIONAL); - auto media_configuration = getSpecificConfiguration( - "SingleDev_TwoChanStereoSnk_48_4_High_Reliability", - LeAudioContextType::MEDIA); + auto media_configuration = + getSpecificConfiguration("One-TwoChan-SnkAse-Lc3_48_4_High_Reliability", + LeAudioContextType::MEDIA); ASSERT_NE(nullptr, conversational_configuration); ASSERT_NE(nullptr, media_configuration); @@ -1087,68 +1270,78 @@ TEST_F(LeAudioAseConfigurationTest, test_context_update) { left->GetAvailableContexts() | right->GetAvailableContexts()); /* MEDIA Available on remote sink direction only */ - ASSERT_TRUE(group_->GetConfiguration(LeAudioContextType::MEDIA) - ->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSink) - .size()); + auto config = group_->GetConfiguration(LeAudioContextType::MEDIA); + ASSERT_NE(nullptr, config); + ASSERT_TRUE( + config->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSink) + .size()); ASSERT_FALSE( - group_->GetConfiguration(LeAudioContextType::MEDIA) - ->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSource) + config->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSource) .size()); + ASSERT_EQ( + config->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSink) + .at(0) + .codec.GetChannelCountPerIsoStream(), + ::bluetooth::le_audio::LeAudioCodecConfiguration::kChannelNumberMono); /* CONVERSATIONAL Available on both directions */ - ASSERT_TRUE(group_->GetConfiguration(LeAudioContextType::CONVERSATIONAL) - ->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSink) - .size()); + config = group_->GetConfiguration(LeAudioContextType::CONVERSATIONAL); + ASSERT_NE(nullptr, config); + ASSERT_TRUE( + config->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSink) + .size()); ASSERT_TRUE( - group_->GetConfiguration(LeAudioContextType::CONVERSATIONAL) - ->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSource) + config->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSource) .size()); /* UNSPECIFIED Unavailable yet supported */ - ASSERT_TRUE(group_->GetConfiguration(LeAudioContextType::UNSPECIFIED) - ->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSink) - .size()); + config = group_->GetConfiguration(LeAudioContextType::UNSPECIFIED); + ASSERT_NE(nullptr, config); + ASSERT_TRUE( + config->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSink) + .size()); ASSERT_FALSE( - group_->GetConfiguration(LeAudioContextType::UNSPECIFIED) - ->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSource) + config->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSource) .size()); /* SOUNDEFFECTS Unavailable yet supported on sink only */ - ASSERT_TRUE(group_->GetConfiguration(LeAudioContextType::SOUNDEFFECTS) - ->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSink) - .size()); + config = group_->GetConfiguration(LeAudioContextType::SOUNDEFFECTS); + ASSERT_NE(nullptr, config); + ASSERT_TRUE( + config->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSink) + .size()); ASSERT_FALSE( - group_->GetConfiguration(LeAudioContextType::SOUNDEFFECTS) - ->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSource) + config->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSource) .size()); - /* INSTRUCTIONAL Unavailable and not supported but scenario is supported */ - ASSERT_TRUE(group_->GetConfiguration(LeAudioContextType::INSTRUCTIONAL) - ->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSink) - .size()); + /* INSTRUCTIONAL Unavailable and not supported, while UNSPECIFIED not + * available */ + config = group_->GetConfiguration(LeAudioContextType::INSTRUCTIONAL); + ASSERT_NE(nullptr, config); + ASSERT_TRUE( + config->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSink) + .size()); ASSERT_FALSE( - group_->GetConfiguration(LeAudioContextType::INSTRUCTIONAL) - ->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSource) + config->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSource) .size()); /* ALERTS on sink only */ - ASSERT_TRUE(group_->GetConfiguration(LeAudioContextType::ALERTS) - ->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSink) - .size()); + config = group_->GetConfiguration(LeAudioContextType::ALERTS); + ASSERT_NE(nullptr, config); + ASSERT_TRUE( + config->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSink) + .size()); ASSERT_FALSE( - group_->GetConfiguration(LeAudioContextType::ALERTS) - ->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSource) + config->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSource) .size()); - /* We should get the config for ALERTS for a single channel as only one earbud - * has it. */ + /* We should get the config for ALERTS for both channels as the other has + * UNSUPPORTED context supported and available. + */ auto sink_configs = group_->GetConfiguration(LeAudioContextType::ALERTS) ->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSink); - ASSERT_EQ(1lu, sink_configs.size()); - ASSERT_EQ( - sink_configs.at(0).codec.GetChannelCountPerIsoStream(), - ::bluetooth::le_audio::LeAudioCodecConfiguration::kChannelNumberMono); + ASSERT_EQ(2lu, sink_configs.size()); ASSERT_TRUE( group_->IsAudioSetConfigurationAvailable(LeAudioContextType::ALERTS)); @@ -1222,10 +1415,10 @@ TEST_F(LeAudioAseConfigurationTest, test_mono_speaker_media) { direction_to_verify); } -TEST_F(LeAudioAseConfigurationTest, test_bounded_headphones_ringtone) { - LeAudioDevice* bounded_headphones = AddTestDevice(2, 0); +TEST_F(LeAudioAseConfigurationTest, test_banded_headphones_ringtone) { + LeAudioDevice* banded_headphones = AddTestDevice(2, 0); TestGroupAseConfigurationData data( - {bounded_headphones, kLeAudioCodecChannelCountTwoChannel, + {banded_headphones, kLeAudioCodecChannelCountTwoChannel, kLeAudioCodecChannelCountSingleChannel, 2, 0}); uint8_t direction_to_verify = kLeAudioDirectionSink; @@ -1233,9 +1426,9 @@ TEST_F(LeAudioAseConfigurationTest, test_bounded_headphones_ringtone) { direction_to_verify); } -TEST_F(LeAudioAseConfigurationTest, test_bounded_headphones_conversational) { - LeAudioDevice* bounded_headphones = AddTestDevice(2, 0); - TestGroupAseConfigurationData data({bounded_headphones, +TEST_F(LeAudioAseConfigurationTest, test_banded_headphones_conversational) { + LeAudioDevice* banded_headphones = AddTestDevice(2, 0); + TestGroupAseConfigurationData data({banded_headphones, kLeAudioCodecChannelCountTwoChannel, kLeAudioCodecChannelCountNone, 2, 0}); @@ -1244,9 +1437,9 @@ TEST_F(LeAudioAseConfigurationTest, test_bounded_headphones_conversational) { direction_to_verify); } -TEST_F(LeAudioAseConfigurationTest, test_bounded_headphones_media) { - LeAudioDevice* bounded_headphones = AddTestDevice(2, 0); - TestGroupAseConfigurationData data({bounded_headphones, +TEST_F(LeAudioAseConfigurationTest, test_banded_headphones_media) { + LeAudioDevice* banded_headphones = AddTestDevice(2, 0); + TestGroupAseConfigurationData data({banded_headphones, kLeAudioCodecChannelCountTwoChannel, kLeAudioCodecChannelCountNone, 2, 0}); @@ -1256,14 +1449,14 @@ TEST_F(LeAudioAseConfigurationTest, test_bounded_headphones_media) { } TEST_F(LeAudioAseConfigurationTest, - test_bounded_headset_ringtone_mono_microphone) { - LeAudioDevice* bounded_headset = AddTestDevice(2, 1); + test_banded_headset_ringtone_mono_microphone) { + LeAudioDevice* banded_headset = AddTestDevice(2, 1); TestGroupAseConfigurationData data( - {bounded_headset, kLeAudioCodecChannelCountTwoChannel, + {banded_headset, kLeAudioCodecChannelCountTwoChannel, kLeAudioCodecChannelCountSingleChannel, 2, 1}); /* mono, change location as by default it is stereo */ - bounded_headset->src_audio_locations_ = + banded_headset->src_audio_locations_ = ::bluetooth::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft; group_->ReloadAudioLocations(); @@ -1271,9 +1464,9 @@ TEST_F(LeAudioAseConfigurationTest, } TEST_F(LeAudioAseConfigurationTest, - test_bounded_headset_ringtone_stereo_microphone) { - LeAudioDevice* bounded_headset = AddTestDevice(2, 2); - TestGroupAseConfigurationData data({bounded_headset, + test_banded_headset_ringtone_stereo_microphone) { + LeAudioDevice* banded_headset = AddTestDevice(2, 2); + TestGroupAseConfigurationData data({banded_headset, kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel, kLeAudioCodecChannelCountSingleChannel | @@ -1283,19 +1476,85 @@ TEST_F(LeAudioAseConfigurationTest, TestGroupAseConfiguration(LeAudioContextType::RINGTONE, &data, 1); } -TEST_F(LeAudioAseConfigurationTest, test_bounded_headset_conversational) { - LeAudioDevice* bounded_headset = AddTestDevice(2, 1); +TEST_F(LeAudioAseConfigurationTest, + test_earbuds_conversational_stereo_microphone_no_swb) { + // Turn off the dual bidir SWB support + ON_CALL(*mock_codec_manager_, IsDualBiDirSwbSupported) + .WillByDefault(Return(false)); + ASSERT_FALSE(CodecManager::GetInstance()->IsDualBiDirSwbSupported()); + + const auto context_type = LeAudioContextType::CONVERSATIONAL; + TestDualDevDualBidir(AddTestDevice(1, 1), AddTestDevice(1, 1), context_type); + + // Verify non-SWB config was selected + auto config = group_->GetCachedConfiguration(context_type).get(); + ASSERT_NE(nullptr, config); + ASSERT_FALSE( + CodecManager::GetInstance()->CheckCodecConfigIsDualBiDirSwb(*config)); +} + +TEST_F(LeAudioAseConfigurationTest, + test_earbuds_conversational_stereo_microphone_swb) { + // Turn on the dual bidir SWB support + ON_CALL(*mock_codec_manager_, IsDualBiDirSwbSupported) + .WillByDefault(Return(true)); + ASSERT_TRUE(CodecManager::GetInstance()->IsDualBiDirSwbSupported()); + + const auto context_type = LeAudioContextType::CONVERSATIONAL; + TestDualDevDualBidir(AddTestDevice(1, 1), AddTestDevice(1, 1), context_type); + + // Verify SWB config was selected + auto config = group_->GetCachedConfiguration(context_type).get(); + ASSERT_NE(nullptr, config); + ASSERT_TRUE( + CodecManager::GetInstance()->CheckCodecConfigIsDualBiDirSwb(*config)); +} + +TEST_F(LeAudioAseConfigurationTest, + test_banded_headset_ringtone_stereo_microphone_no_swb) { + // Turn off the dual bidir SWB support + ON_CALL(*mock_codec_manager_, IsDualBiDirSwbSupported) + .WillByDefault(Return(false)); + ASSERT_FALSE(CodecManager::GetInstance()->IsDualBiDirSwbSupported()); + + // Verify non-SWB config was selected + auto context_type = LeAudioContextType::CONVERSATIONAL; + TestSingleDevDualBidir(AddTestDevice(2, 2), context_type); + auto config = group_->GetCachedConfiguration(context_type).get(); + ASSERT_NE(nullptr, config); + ASSERT_FALSE( + CodecManager::GetInstance()->CheckCodecConfigIsDualBiDirSwb(*config)); +} + +TEST_F(LeAudioAseConfigurationTest, + test_banded_headset_ringtone_stereo_microphone_swb) { + // Turn on the dual bidir SWB support + ON_CALL(*mock_codec_manager_, IsDualBiDirSwbSupported) + .WillByDefault(Return(true)); + ASSERT_TRUE(CodecManager::GetInstance()->IsDualBiDirSwbSupported()); + + // Verify SWB config was selected + auto context_type = LeAudioContextType::CONVERSATIONAL; + TestSingleDevDualBidir(AddTestDevice(2, 2), context_type); + auto config = group_->GetCachedConfiguration(context_type).get(); + ASSERT_NE(nullptr, config); + ASSERT_TRUE( + CodecManager::GetInstance()->CheckCodecConfigIsDualBiDirSwb(*config)); +} + +TEST_F(LeAudioAseConfigurationTest, test_banded_headset_conversational) { + LeAudioDevice* banded_headset = AddTestDevice(2, 1); TestGroupAseConfigurationData data( - {bounded_headset, kLeAudioCodecChannelCountTwoChannel, + {banded_headset, kLeAudioCodecChannelCountTwoChannel, kLeAudioCodecChannelCountSingleChannel, 2, 1}); TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, &data, 1); } -TEST_F(LeAudioAseConfigurationTest, test_bounded_headset_media) { - LeAudioDevice* bounded_headset = AddTestDevice(2, 1); +TEST_F(LeAudioAseConfigurationTest, test_banded_headset_media) { + LeAudioDevice* banded_headset = AddTestDevice(2, 1); TestGroupAseConfigurationData data( - {bounded_headset, kLeAudioCodecChannelCountTwoChannel, + {banded_headset, kLeAudioCodecChannelCountTwoChannel, kLeAudioCodecChannelCountSingleChannel, 2, 0}); uint8_t directions_to_verify = kLeAudioDirectionSink; @@ -1538,6 +1797,9 @@ TEST_F(LeAudioAseConfigurationTest, test_reconnection_media) { TestSingleAseConfiguration(LeAudioContextType::MEDIA, data, 2, configuration, direction_to_verify); + // Get the proper configuration for the group + configuration = group_->GetConfiguration(LeAudioContextType::MEDIA).get(); + /* Generate CISes, symulate CIG creation and assign cis handles to ASEs.*/ group_->cig.GenerateCisIds(LeAudioContextType::MEDIA); std::vector<uint16_t> handles = {0x0012, 0x0013}; @@ -1557,6 +1819,7 @@ TEST_F(LeAudioAseConfigurationTest, test_reconnection_media) { /* Prepare reconfiguration */ uint8_t number_of_active_ases = 1; // Right one auto* ase = right->GetFirstActiveAseByDirection(kLeAudioDirectionSink); + ASSERT_NE(nullptr, ase); auto core_config = ase->codec_config.GetAsCoreCodecConfig(); BidirectionalPair<AudioLocations> group_audio_locations = { @@ -1568,7 +1831,7 @@ TEST_F(LeAudioAseConfigurationTest, test_reconnection_media) { BidirectionalPair<AudioContexts> audio_contexts = {AudioContexts(), AudioContexts()}; if (!configuration->confs.sink.empty()) { - left->ConfigureAses(configuration, kLeAudioDirectionSink, + left->ConfigureAses(configuration, group_->Size(), kLeAudioDirectionSink, group_->GetConfigurationContextType(), &number_of_active_ases, group_audio_locations.get(kLeAudioDirectionSink), @@ -1576,7 +1839,7 @@ TEST_F(LeAudioAseConfigurationTest, test_reconnection_media) { ccid_lists.get(kLeAudioDirectionSink), false); } if (!configuration->confs.source.empty()) { - left->ConfigureAses(configuration, kLeAudioDirectionSource, + left->ConfigureAses(configuration, group_->Size(), kLeAudioDirectionSource, group_->GetConfigurationContextType(), &number_of_active_ases, group_audio_locations.get(kLeAudioDirectionSource), @@ -1584,8 +1847,8 @@ TEST_F(LeAudioAseConfigurationTest, test_reconnection_media) { ccid_lists.get(kLeAudioDirectionSource), false); } - ASSERT_TRUE(number_of_active_ases == 2); - ASSERT_TRUE(group_audio_locations.sink == kChannelAllocationStereo); + ASSERT_EQ(number_of_active_ases, 2); + ASSERT_EQ(group_audio_locations.sink, kChannelAllocationStereo); uint8_t directions_to_verify = ::bluetooth::le_audio::types::kLeAudioDirectionSink; @@ -1630,7 +1893,7 @@ TEST_F(LeAudioAseConfigurationTest, test_reactivation_conversational) { group_->ReloadAudioLocations(); auto conversational_configuration = getSpecificConfiguration( - "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency", + "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency", LeAudioContextType::CONVERSATIONAL); ASSERT_NE(nullptr, conversational_configuration); @@ -1667,7 +1930,7 @@ TEST_F(LeAudioAseConfigurationTest, test_reactivation_conversational) { /* Get entry for the sink direction and use it to set configuration */ if (!conversational_configuration->confs.sink.empty()) { tws_headset->ConfigureAses( - conversational_configuration, kLeAudioDirectionSink, + conversational_configuration, group_->Size(), kLeAudioDirectionSink, group_->GetConfigurationContextType(), &number_of_already_active_ases.get(kLeAudioDirectionSink), group_audio_locations.get(kLeAudioDirectionSink), @@ -1676,7 +1939,7 @@ TEST_F(LeAudioAseConfigurationTest, test_reactivation_conversational) { } if (!conversational_configuration->confs.source.empty()) { tws_headset->ConfigureAses( - conversational_configuration, kLeAudioDirectionSource, + conversational_configuration, group_->Size(), kLeAudioDirectionSource, group_->GetConfigurationContextType(), &number_of_already_active_ases.get(kLeAudioDirectionSource), group_audio_locations.get(kLeAudioDirectionSource), @@ -1751,9 +2014,9 @@ TEST_F(LeAudioAseConfigurationTest, test_getting_cis_count) { right->snk_audio_locations_ = kChannelAllocationStereo; group_->ReloadAudioLocations(); - auto media_configuration = getSpecificConfiguration( - "SingleDev_TwoChanStereoSnk_48_4_High_Reliability", - LeAudioContextType::MEDIA); + auto media_configuration = + getSpecificConfiguration("One-TwoChan-SnkAse-Lc3_48_4_High_Reliability", + LeAudioContextType::MEDIA); ASSERT_NE(nullptr, media_configuration); // Build PACs for device @@ -1784,12 +2047,12 @@ TEST_F(LeAudioAseConfigurationTest, test_getting_cis_count) { /* Get entry for the sink direction and use it to set configuration */ if (!media_configuration->confs.sink.empty()) { - left->ConfigureAses(media_configuration, kLeAudioDirectionSink, - group_->GetConfigurationContextType(), - &number_of_already_active_ases, - group_audio_locations.get(kLeAudioDirectionSink), - audio_contexts.get(kLeAudioDirectionSink), - ccid_lists.get(kLeAudioDirectionSink), false); + left->ConfigureAses( + media_configuration, group_->Size(), kLeAudioDirectionSink, + group_->GetConfigurationContextType(), &number_of_already_active_ases, + group_audio_locations.get(kLeAudioDirectionSink), + audio_contexts.get(kLeAudioDirectionSink), + ccid_lists.get(kLeAudioDirectionSink), false); } /* Generate CIS, simulate CIG creation and assign cis handles to ASEs.*/ @@ -1817,7 +2080,7 @@ TEST_F(LeAudioAseConfigurationTest, test_config_support) { group_->ReloadAudioLocations(); auto test_config = getSpecificConfiguration( - "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_16_2_Balanced_" + "One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2_Balanced_" "Reliability", LeAudioContextType::VOICEASSISTANTS); ASSERT_NE(nullptr, test_config); diff --git a/system/bta/le_audio/le_audio_client_test.cc b/system/bta/le_audio/le_audio_client_test.cc index 95d0dba6b9..504768d4e7 100644 --- a/system/bta/le_audio/le_audio_client_test.cc +++ b/system/bta/le_audio/le_audio_client_test.cc @@ -20,6 +20,7 @@ #include <flag_macros.h> #include <gmock/gmock.h> #include <gtest/gtest.h> +#include <log/log.h> #include <chrono> @@ -47,7 +48,6 @@ #include "mock_csis_client.h" #include "mock_device_groups.h" #include "mock_state_machine.h" -#include "os/log.h" #include "test/common/mock_functions.h" #include "test/mock/mock_main_shim_entry.h" #include "test/mock/mock_stack_btm_iso.h" @@ -983,13 +983,13 @@ class UnicastTestNoInit : public Test { stream_conf->stream_params.source.num_of_devices++; stream_conf->stream_params.source.num_of_channels += - core_config.GetChannelCountPerIsoStream(); + ase.channel_count; log::info( "Added Source Stream Configuration. CIS Connection Handle: " "{}, Audio Channel Allocation: {}, Source Number Of " "Devices: {}, Source Number Of Channels: {}", - ase.cis_conn_hdl, (*core_config.audio_channel_allocation), + ase.cis_conn_hdl, *core_config.audio_channel_allocation, stream_conf->stream_params.source.num_of_devices, stream_conf->stream_params.source.num_of_channels); } @@ -1009,13 +1009,13 @@ class UnicastTestNoInit : public Test { stream_conf->stream_params.sink.num_of_devices++; stream_conf->stream_params.sink.num_of_channels += - core_config.GetChannelCountPerIsoStream(); + ase.channel_count; log::info( "Added Sink Stream Configuration. CIS Connection Handle: " "{}, Audio Channel Allocation: {}, Sink Number Of Devices: " "{}, Sink Number Of Channels: {}", - ase.cis_conn_hdl, (*core_config.audio_channel_allocation), + ase.cis_conn_hdl, *core_config.audio_channel_allocation, stream_conf->stream_params.sink.num_of_devices, stream_conf->stream_params.sink.num_of_channels); } @@ -1114,7 +1114,7 @@ class UnicastTestNoInit : public Test { stream_conf->stream_params.source.num_of_devices++; stream_conf->stream_params.source.num_of_channels += - core_config.GetChannelCountPerIsoStream(); + ase.channel_count; stream_conf->stream_params.source.audio_channel_allocation |= *core_config.audio_channel_allocation; @@ -1165,7 +1165,7 @@ class UnicastTestNoInit : public Test { "Added Source Stream Configuration. CIS Connection " "Handle: {}, Audio Channel Allocation: {}, Source Number " "Of Devices: {}, Source Number Of Channels: {}", - ase.cis_conn_hdl, (*core_config.audio_channel_allocation), + ase.cis_conn_hdl, *core_config.audio_channel_allocation, stream_conf->stream_params.source.num_of_devices, stream_conf->stream_params.source.num_of_channels); } @@ -1185,7 +1185,7 @@ class UnicastTestNoInit : public Test { stream_conf->stream_params.sink.num_of_devices++; stream_conf->stream_params.sink.num_of_channels += - core_config.GetChannelCountPerIsoStream(); + ase.channel_count; stream_conf->stream_params.sink.audio_channel_allocation |= *core_config.audio_channel_allocation; @@ -1237,7 +1237,7 @@ class UnicastTestNoInit : public Test { "Added Sink Stream Configuration. CIS Connection Handle: " "{}, Audio Channel Allocation: {}, Sink Number Of " "Devices: {}, Sink Number Of Channels: {}", - ase.cis_conn_hdl, (*core_config.audio_channel_allocation), + ase.cis_conn_hdl, *core_config.audio_channel_allocation, stream_conf->stream_params.sink.num_of_devices, stream_conf->stream_params.sink.num_of_channels); } @@ -1310,12 +1310,11 @@ class UnicastTestNoInit : public Test { if (ases.sink) { stream_conf->stream_params.sink.num_of_devices--; stream_conf->stream_params.sink.num_of_channels -= - ases.sink->codec_config.GetAsCoreCodecConfig() - .GetChannelCountPerIsoStream(); + ases.sink->channel_count; log::info( - ", Source Number Of Devices: {}, Source Number Of " - "Channels: {}", + ", Source Number Of Devices: {}" + ", Source Number Of Channels: {}", stream_conf->stream_params.source.num_of_devices, stream_conf->stream_params.source.num_of_channels); } @@ -1333,8 +1332,7 @@ class UnicastTestNoInit : public Test { if (ases.source) { stream_conf->stream_params.source.num_of_devices--; stream_conf->stream_params.source.num_of_channels -= - ases.source->codec_config.GetAsCoreCodecConfig() - .GetChannelCountPerIsoStream(); + ases.source->channel_count; log::info( ", Source Number Of Devices: {}, Source Number Of " @@ -1390,8 +1388,7 @@ class UnicastTestNoInit : public Test { if (ases.sink) { stream_conf->stream_params.sink.num_of_devices--; stream_conf->stream_params.sink.num_of_channels -= - ases.sink->codec_config.GetAsCoreCodecConfig() - .GetChannelCountPerIsoStream(); + ases.sink->channel_count; log::info( "Sink Number Of Devices: {}, Sink Number Of " @@ -1417,8 +1414,7 @@ class UnicastTestNoInit : public Test { if (ases.source) { stream_conf->stream_params.source.num_of_devices--; stream_conf->stream_params.source.num_of_channels -= - ases.source->codec_config.GetAsCoreCodecConfig() - .GetChannelCountPerIsoStream(); + ases.source->channel_count; log::info( ", Source Number Of Devices: {}, Source Number Of " @@ -1456,8 +1452,7 @@ class UnicastTestNoInit : public Test { if (ases.sink) { stream_conf->stream_params.sink.num_of_devices--; stream_conf->stream_params.sink.num_of_channels -= - ases.sink->codec_config.GetAsCoreCodecConfig() - .GetChannelCountPerIsoStream(); + ases.sink->channel_count; log::info( "Sink Number Of Devices: {}, Sink Number Of " @@ -1484,8 +1479,7 @@ class UnicastTestNoInit : public Test { if (ases.source) { stream_conf->stream_params.source.num_of_devices--; stream_conf->stream_params.source.num_of_channels -= - ases.source->codec_config.GetAsCoreCodecConfig() - .GetChannelCountPerIsoStream(); + ases.source->channel_count; log::info( ", Source Number Of Devices: {}, Source Number " @@ -1530,6 +1524,7 @@ class UnicastTestNoInit : public Test { } void SetUp() override { + __android_log_set_minimum_priority(ANDROID_LOG_VERBOSE); init_message_loop_thread(); ON_CALL(controller_, SupportsBleConnectedIsochronousStreamCentral) .WillByDefault(Return(true)); @@ -1588,18 +1583,36 @@ class UnicastTestNoInit : public Test { ASSERT_NE(mock_codec_manager_, nullptr); ON_CALL(*mock_codec_manager_, GetCodecLocation()) .WillByDefault(Return(location)); + // Turn on the dual bidir SWB support + ON_CALL(*mock_codec_manager_, IsDualBiDirSwbSupported) + .WillByDefault(Return(true)); // Regardless of the codec location, return all the possible configurations ON_CALL(*mock_codec_manager_, GetCodecConfig) .WillByDefault( Invoke([](const CodecManager::UnicastConfigurationRequirements& requirements, CodecManager::UnicastConfigurationVerifier verifier) { - auto configs = - le_audio::AudioSetConfigurationProvider::Get() - ->GetConfigurations(requirements.audio_context_type); - return std::make_unique< - set_configurations::AudioSetConfiguration>( - *verifier(requirements, configs)); + auto filtered = + *le_audio::AudioSetConfigurationProvider::Get() + ->GetConfigurations(requirements.audio_context_type); + // Filter out the dual bidir SWB configurations + if (!bluetooth::le_audio::CodecManager::GetInstance() + ->IsDualBiDirSwbSupported()) { + filtered.erase( + std::remove_if(filtered.begin(), filtered.end(), + [](auto const& el) { + if (el->confs.source.empty()) return false; + return AudioSetConfigurationProvider::Get() + ->CheckConfigurationIsDualBiDirSwb( + *el); + }), + filtered.end()); + } + auto cptr = verifier(requirements, &filtered); + return cptr + ? std::make_unique< + set_configurations::AudioSetConfiguration>(*cptr) + : nullptr; })); } @@ -2685,15 +2698,17 @@ class UnicastTestNoInit : public Test { // Expect two channels ISO Data to be sent std::vector<uint16_t> handles; - EXPECT_CALL(*mock_iso_manager_, SendIsoData(_, _, _)) - .Times(cis_count_out) - .WillRepeatedly( - [&handles](uint16_t iso_handle, const uint8_t* data, - uint16_t data_len) { handles.push_back(iso_handle); }); + if (cis_count_out) { + EXPECT_CALL(*mock_iso_manager_, SendIsoData(_, _, _)) + .Times(cis_count_out) + .WillRepeatedly( + [&handles](uint16_t iso_handle, const uint8_t* data, + uint16_t data_len) { handles.push_back(iso_handle); }); + } std::vector<uint8_t> data(data_len); unicast_source_hal_cb_->OnAudioDataReady(data); - // Inject microphone data from group + // Inject microphone data from group (2 CISes - pass stereo data in 1 call) if (decoded_in_data_len) { EXPECT_CALL(*mock_le_audio_sink_hal_client_, SendData(_, decoded_in_data_len)) @@ -2707,6 +2722,7 @@ class UnicastTestNoInit : public Test { if (cis_count_in) { ASSERT_NE(unicast_sink_hal_cb_, nullptr); + ASSERT_NE(0lu, streaming_groups.count(group_id)); auto group = streaming_groups.at(group_id); for (LeAudioDevice* device = group->GetFirstDevice(); device != nullptr; device = group->GetNextDevice(device)) { @@ -2728,6 +2744,7 @@ class UnicastTestNoInit : public Test { handles.clear(); Mock::VerifyAndClearExpectations(mock_iso_manager_); + Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_); } void InjectIncomingIsoData(uint16_t cig_id, uint16_t cis_con_hdl, @@ -4775,7 +4792,7 @@ TEST_F_WITH_FLAGS(UnicastTest, GroupSetActive_CurrentCodecSentOfActive, .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3, .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_48000HZ, .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16, - .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_2, + .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1, .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US, .octets_per_frame = 120}; @@ -4973,6 +4990,7 @@ TEST_F(UnicastTest, ChangeAvailableContextTypeWhenInCodecConfigured) { TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 0, 40); // Remember group to set the state after stopping the stream + ASSERT_NE(0lu, streaming_groups.count(group_id)); auto group = streaming_groups.at(group_id); SyncOnMainLoop(); @@ -5764,6 +5782,7 @@ TEST_F(UnicastTest, DisconnecteWhileAlmostStreaming) { /* This is test code, which will change the group state to the one which * is required by test */ + ASSERT_NE(0lu, streaming_groups.count(group_id)); auto group_inject = streaming_groups.at(group_id); group_inject->SetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_ENABLING); @@ -5803,9 +5822,10 @@ TEST_F(UnicastTest, EarbudsTwsStyleStreaming) { SetSampleDatabaseEarbudsValid( 1, test_address0, codec_spec_conf::kLeAudioLocationStereo, - codec_spec_conf::kLeAudioLocationStereo, 0x01, 0x01, 0x0004, - /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, - true /*add_pacs*/, 2 /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/); + codec_spec_conf::kLeAudioLocationStereo, 0x01, 0x01, + codec_spec_caps::kLeAudioSamplingFreq16000Hz, false /*add_csis*/, + true /*add_cas*/, true /*add_pacs*/, 2 /*add_asc_cnt*/, 1 /*set_size*/, + 0 /*rank*/); EXPECT_CALL(mock_audio_hal_client_callbacks_, OnConnectionState(ConnectionState::CONNECTED, test_address0)) .Times(1); @@ -6230,6 +6250,7 @@ TEST_F(UnicastTest, SpeakerStreamingAutonomousRelease) { 1920); // Inject the IDLE state as if an autonomous release happened + ASSERT_NE(0lu, streaming_groups.count(group_id)); auto group = streaming_groups.at(group_id); ASSERT_NE(group, nullptr); for (LeAudioDevice* device = group->GetFirstDevice(); device != nullptr; @@ -6288,7 +6309,7 @@ TEST_F(UnicastTest, TwoEarbudsStreaming) { .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3, .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ, .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16, - .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_2, + .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1, .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US, .octets_per_frame = 40}; @@ -6321,6 +6342,7 @@ TEST_F(UnicastTest, TwoEarbudsStreaming) { // Verify Data transfer still works TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40); + ASSERT_NE(0lu, streaming_groups.count(group_id)); auto group = streaming_groups.at(group_id); // Stop @@ -7251,6 +7273,7 @@ TEST_F(UnicastTest, TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920); /* Get group and Device A */ + ASSERT_NE(0lu, streaming_groups.count(group_id)); auto group = streaming_groups.at(group_id); ASSERT_NE(group, nullptr); auto device = group->GetFirstDevice(); @@ -7352,6 +7375,7 @@ TEST_F(UnicastTest, TwoEarbuds2ndReleaseAseRemoveAvailableContextAndBack) { TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920); /* Get group and Device A */ + ASSERT_NE(0lu, streaming_groups.count(group_id)); auto group = streaming_groups.at(group_id); ASSERT_NE(group, nullptr); auto device = group->GetFirstDevice(); @@ -7643,7 +7667,7 @@ TEST_F(UnicastTest, StartStreamToUnsupportedContextTypeUsingUnspecified) { } TEST_F(UnicastTest, - StartStreamToUnsupportedContextTypeUnspecifiedNotSupported) { + StartStreamToUnsupportedContextTypeUnspecifiedNotAvailable) { uint8_t group_size = 2; int group_id = 2; @@ -7790,6 +7814,7 @@ TEST_F(UnicastTest, StartStreamToSupportedContextTypeThenMixUnavailable) { Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_); Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_); + ASSERT_NE(0lu, streaming_groups.count(group_id)); auto group = streaming_groups.at(group_id); // Expect two iso channel to be fed with data @@ -7914,6 +7939,7 @@ TEST_F(UnicastTest, TwoEarbuds2ndDisconnected) { SyncOnMainLoop(); StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id); + ASSERT_NE(0lu, streaming_groups.count(group_id)); auto group = streaming_groups.at(group_id); Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_); @@ -8118,6 +8144,7 @@ TEST_F(UnicastTest, TwoEarbudsStreamingProfileDisconnectStreamStopTimeout) { EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(0); EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(_, _)).Times(2); + ASSERT_NE(0lu, streaming_groups.count(group_id)); auto group = streaming_groups.at(group_id); ASSERT_TRUE(group != nullptr); ASSERT_TRUE(group->NumOfConnected() > 0); @@ -9277,6 +9304,7 @@ TEST_F(UnicastTest, SpeakerStreamingTimeout) { SyncOnMainLoop(); /* No assigned cises should remain when transition remains in IDLE state */ + ASSERT_NE(0lu, streaming_groups.count(group_id)); auto group = streaming_groups.at(group_id); ASSERT_EQ(0, static_cast<int>(group->cig.cises.size())); } @@ -9912,6 +9940,7 @@ TEST_F_WITH_FLAGS(UnicastTestHandoverMode, bluetooth::le_audio::types::kLeAudioDirectionSink, true /* enable */)); + ASSERT_NE(0lu, streaming_groups.count(group_id)); auto group = streaming_groups.at(group_id); // Stop streaming and expect Service to be informed about straming suspension @@ -10083,6 +10112,7 @@ TEST_F_WITH_FLAGS(UnicastTestHandoverMode, uint8_t cis_count_in = 2; TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40); + ASSERT_NE(0lu, streaming_groups.count(group_id)); auto group = streaming_groups.at(group_id); // Stop streaming and expect Service to be informed about straming suspension @@ -10195,6 +10225,7 @@ TEST_F_WITH_FLAGS(UnicastTestHandoverMode, uint8_t cis_count_in = 2; TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40); + ASSERT_NE(0lu, streaming_groups.count(group_id)); auto group = streaming_groups.at(group_id); // De-activate monitoring mode @@ -10393,6 +10424,7 @@ TEST_F_WITH_FLAGS(UnicastTestHandoverMode, SyncOnMainLoop(); Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_); + ASSERT_NE(0lu, streaming_groups.count(group_id)); auto group = streaming_groups.at(group_id); // Stop streaming and expect Service to be informed about straming suspension 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 ea3a70b94d..cfed55c8d5 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 @@ -83,8 +83,6 @@ struct AudioSetConfigurationProviderJson { static constexpr auto kDefaultScenario = "Media"; AudioSetConfigurationProviderJson(types::CodecLocation location) { - dual_bidirection_swb_supported_ = osi_property_get_bool( - "bluetooth.leaudio.dual_bidirection_swb.supported", false); log::assert_that( LoadContent(kLeAudioSetConfigs, kLeAudioSetScenarios, location), ": Unable to load le audio set configuration files."); @@ -176,24 +174,6 @@ struct AudioSetConfigurationProviderJson { AudioSetConfigurations> context_configurations_; - /* property to check if bidirectional sampling frequency >= 32k dual mic is - * supported or not - */ - bool dual_bidirection_swb_supported_; - - static const fbs::le_audio::CodecSpecificConfiguration* - LookupCodecSpecificParam( - const flatbuffers::Vector< - flatbuffers::Offset<fbs::le_audio::CodecSpecificConfiguration>>* - flat_codec_specific_params, - fbs::le_audio::CodecSpecificLtvGenericTypes type) { - auto it = std::find_if( - flat_codec_specific_params->cbegin(), - flat_codec_specific_params->cend(), - [&type](const auto& csc) { return (csc->type() == type); }); - return (it != flat_codec_specific_params->cend()) ? *it : nullptr; - } - static CodecConfigSetting CodecConfigSettingFromFlat( const fbs::le_audio::CodecId* flat_codec_id, const flatbuffers::Vector< @@ -215,38 +195,21 @@ struct AudioSetConfigurationProviderJson { param->type(), std::vector<uint8_t>(value->data(), value->data() + value->size())); } - - auto param = codec.params.Find( - fbs::le_audio:: - CodecSpecificLtvGenericTypes_SUPPORTED_AUDIO_CHANNEL_ALLOCATION); - if (param) { - auto ptr = param->data(); - uint32_t audio_channel_allocation; - - log::assert_that((param->size() == sizeof(audio_channel_allocation)), - "invalid channel allocation value {}", - (int)param->size()); - STREAM_TO_UINT32(audio_channel_allocation, ptr); - codec.channel_count_per_iso_stream = - std::bitset<32>(audio_channel_allocation).count(); - } else { - // TODO: Add support for channel count in the json configurations file, - // keeping support for the allocations for compatibility. - } - return codec; } void SetConfigurationFromFlatSubconfig( const fbs::le_audio::AudioSetSubConfiguration* flat_subconfig, - QosConfigSetting qos, bool& dual_dev_one_chan_stereo_swb, - bool& single_dev_one_chan_stereo_swb, - std::vector<AseConfiguration>& subconfigs, + QosConfigSetting qos, std::vector<AseConfiguration>& subconfigs, types::CodecLocation location) { - auto config = AseConfiguration( - CodecConfigSettingFromFlat(flat_subconfig->codec_id(), - flat_subconfig->codec_configuration()), - qos); + auto codec_config = CodecConfigSettingFromFlat( + flat_subconfig->codec_id(), flat_subconfig->codec_configuration()); + + // Fill in the remaining params + codec_config.channel_count_per_iso_stream = + flat_subconfig->ase_channel_cnt(); + + auto config = AseConfiguration(codec_config, qos); // Note that these parameters are set here since for now, we are using the // common configuration source for all the codec locations. @@ -267,17 +230,6 @@ struct AudioSetConfigurationProviderJson { break; } - // Check for SWB support - if (config.codec.GetSamplingFrequencyHz() >= - le_audio::LeAudioCodecConfiguration::kSampleRate32000) { - if (flat_subconfig->device_cnt() == 2 && flat_subconfig->ase_cnt() == 2) { - dual_dev_one_chan_stereo_swb |= true; - } - if (flat_subconfig->device_cnt() == 1 && flat_subconfig->ase_cnt() == 2) { - single_dev_one_chan_stereo_swb |= true; - } - } - // Store each ASE configuration for (auto i = flat_subconfig->ase_cnt(); i; --i) { subconfigs.push_back(std::move(config)); @@ -373,34 +325,11 @@ struct AudioSetConfigurationProviderJson { } types::BidirectionalPair<std::vector<AseConfiguration>> subconfigs; - types::BidirectionalPair<bool> dual_dev_one_chan_stereo_swb; - types::BidirectionalPair<bool> single_dev_one_chan_stereo_swb; - types::BidirectionalPair<uint8_t> device_cnt; - types::BidirectionalPair<types::LeAudioConfigurationStrategy> strategy = { - le_audio::types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE, - le_audio::types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE}; - if (codec_cfg != nullptr && codec_cfg->subconfigurations()) { /* Load subconfigurations */ for (auto subconfig : *codec_cfg->subconfigurations()) { auto direction = subconfig->direction(); - - auto strategy_int = - static_cast<int>(subconfig->configuration_strategy()); - bool valid_strategy = - (strategy_int >= (int)types::LeAudioConfigurationStrategy:: - MONO_ONE_CIS_PER_DEVICE) && - strategy_int < (int)types::LeAudioConfigurationStrategy::RFU; - - strategy.get(direction) = - valid_strategy - ? static_cast<types::LeAudioConfigurationStrategy>(strategy_int) - : types::LeAudioConfigurationStrategy::RFU; - device_cnt.get(direction) = subconfig->device_cnt(); - processSubconfig(*subconfig, qos.get(direction), - dual_dev_one_chan_stereo_swb.get(direction), - single_dev_one_chan_stereo_swb.get(direction), subconfigs.get(direction), location); } } else { @@ -412,37 +341,30 @@ struct AudioSetConfigurationProviderJson { } } - if (!dual_bidirection_swb_supported_) { - if ((dual_dev_one_chan_stereo_swb.sink && - dual_dev_one_chan_stereo_swb.source) || - (single_dev_one_chan_stereo_swb.sink && - single_dev_one_chan_stereo_swb.source)) { - return { - .name = flat_cfg->name()->c_str(), - .packing = bluetooth::hci::kIsoCigPackingSequential, - .confs = {}, - .topology_info = {{device_cnt, strategy}}, - }; - } - } - return { .name = flat_cfg->name()->c_str(), .packing = bluetooth::hci::kIsoCigPackingSequential, .confs = std::move(subconfigs), - .topology_info = {{device_cnt, strategy}}, }; } void processSubconfig( const fbs::le_audio::AudioSetSubConfiguration& subconfig, - const QosConfigSetting& qos_setting, bool& dual_dev_one_chan_stereo_swb, - bool& single_dev_one_chan_stereo_swb, + const QosConfigSetting& qos_setting, std::vector<AseConfiguration>& subconfigs, types::CodecLocation location) { - SetConfigurationFromFlatSubconfig( - &subconfig, qos_setting, dual_dev_one_chan_stereo_swb, - single_dev_one_chan_stereo_swb, subconfigs, location); + SetConfigurationFromFlatSubconfig(&subconfig, qos_setting, subconfigs, + location); + + // Recalculate some qos params based on the Core Codec Configuration + for (auto& subconfig : subconfigs) { + const auto& core_config = subconfig.codec.params.GetAsCoreCodecConfig(); + subconfig.qos.maxSdu = + subconfig.codec.GetChannelCountPerIsoStream() * + core_config.octets_per_codec_frame.value_or(0) * + core_config.codec_frames_blocks_per_sdu.value_or(1); + subconfig.qos.sduIntervalUs = core_config.GetFrameDurationUs(); + } } bool LoadConfigurationsFromFiles(const char* schema_file, @@ -629,14 +551,6 @@ struct AudioSetConfigurationProvider::impl { << (direction == types::kLeAudioDirectionSink ? "Sink (speaker)\n" : "Source (microphone)\n"); - if (conf->topology_info.has_value()) { - stream << " number of devices: " - << +conf->topology_info->device_count.get(direction) - << " \n" - << " strategy: " - << (int)(conf->topology_info->strategy.get(direction)) - << " \n"; - } for (const auto& ent : conf->confs.get(direction)) { stream << " ASE config: " << " qos->target latency: " << +ent.qos.target_latency @@ -729,38 +643,20 @@ bool AudioSetConfigurationProvider::CheckConfigurationIsBiDirSwb( bool AudioSetConfigurationProvider::CheckConfigurationIsDualBiDirSwb( const set_configurations::AudioSetConfiguration& set_configuration) const { - /* Check both directions for dual channel SWB */ - uint8_t single_dev_dual_bidir_swb = 0; - uint8_t dual_dev_dual_bidir_swb = 0; + types::BidirectionalPair<uint8_t> swb_direction_counter = {0, 0}; for (auto direction : {le_audio::types::kLeAudioDirectionSink, le_audio::types::kLeAudioDirectionSource}) { - uint8_t ase_cnt = 0; - for (auto const& conf : set_configuration.confs.get(direction)) { - if (conf.codec.GetSamplingFrequencyHz() < - bluetooth::le_audio::LeAudioCodecConfiguration::kSampleRate32000) { - return false; - } - ++ase_cnt; - } - - log::assert_that( - set_configuration.topology_info.has_value(), - "No topology info, which is required to properly configure the ASEs"); - if (set_configuration.topology_info->device_count.get(direction) == 1 && - ase_cnt == 2) { - single_dev_dual_bidir_swb |= direction; - } - if (set_configuration.topology_info->device_count.get(direction) == 2 && - ase_cnt == 2) { - dual_dev_dual_bidir_swb |= direction; - } + auto const& confs = set_configuration.confs.get(direction); + swb_direction_counter.get(direction) += + std::count_if(confs.begin(), confs.end(), [](auto const& cfg) { + return cfg.codec.GetSamplingFrequencyHz() >= + bluetooth::le_audio::LeAudioCodecConfiguration:: + kSampleRate32000; + }); } - return single_dev_dual_bidir_swb == - bluetooth::le_audio::types::kLeAudioDirectionBoth || - dual_dev_dual_bidir_swb == - bluetooth::le_audio::types::kLeAudioDirectionBoth; + return (swb_direction_counter.sink > 1) && (swb_direction_counter.source > 1); } } // namespace bluetooth::le_audio diff --git a/system/bta/le_audio/le_audio_types.cc b/system/bta/le_audio/le_audio_types.cc index c27136a7cd..89afe107bd 100644 --- a/system/bta/le_audio/le_audio_types.cc +++ b/system/bta/le_audio/le_audio_types.cc @@ -43,28 +43,6 @@ using types::kLeAudioDirectionSink; using types::kLeAudioDirectionSource; using types::LeAudioCoreCodecConfig; -static uint8_t min_req_devices_cnt( - const AudioSetConfiguration* audio_set_conf) { - log::assert_that( - audio_set_conf->topology_info.has_value(), - "No topology info, which is required to properly configure the ASEs"); - return std::max(audio_set_conf->topology_info->device_count.sink, - audio_set_conf->topology_info->device_count.source); -} - -static uint8_t min_req_devices_cnt( - const AudioSetConfigurations* audio_set_confs) { - uint8_t curr_min_req_devices_cnt = 0xff; - - for (auto ent : *audio_set_confs) { - uint8_t req_devices_cnt = min_req_devices_cnt(ent); - if (req_devices_cnt < curr_min_req_devices_cnt) - curr_min_req_devices_cnt = req_devices_cnt; - } - - return curr_min_req_devices_cnt; -} - void get_cis_count(LeAudioContextType context_type, int expected_device_cnt, types::LeAudioConfigurationStrategy strategy, int avail_group_ase_snk_cnt, int avail_group_ase_src_count, @@ -109,6 +87,9 @@ void get_cis_count(LeAudioContextType context_type, int expected_device_cnt, if (is_bidirectional) { if ((avail_group_ase_snk_cnt > 0) && (avail_group_ase_src_count) > 0) { /* Prepare CIG to enable all microphones per device */ + /* TODO: Support TWS style device with two source ASEs - two + * bidirectional CISes + */ out_cis_count_bidir = expected_device_cnt; out_cis_count_unidir_sink = expected_device_cnt; } else { @@ -134,31 +115,6 @@ void get_cis_count(LeAudioContextType context_type, int expected_device_cnt, out_cis_count_unidir_source); } -bool check_if_may_cover_scenario(const AudioSetConfigurations* audio_set_confs, - uint8_t group_size) { - if (!audio_set_confs) { - log::error("no audio requirements for group"); - return false; - } - - return group_size >= min_req_devices_cnt(audio_set_confs); -} - -bool check_if_may_cover_scenario(const AudioSetConfiguration* audio_set_conf, - uint8_t group_size) { - if (!audio_set_conf) { - log::error("no audio requirement for group"); - return false; - } - - return group_size >= min_req_devices_cnt(audio_set_conf); -} - -uint8_t get_num_of_devices_in_configuration( - const AudioSetConfiguration* audio_set_conf) { - return min_req_devices_cnt(audio_set_conf); -} - uint16_t CodecConfigSetting::GetOctectsPerFrame() const { switch (id.coding_format) { case kLeAudioCodingFormatLC3: diff --git a/system/bta/le_audio/le_audio_types.h b/system/bta/le_audio/le_audio_types.h index eac9985bb8..9bb315b7fe 100644 --- a/system/bta/le_audio/le_audio_types.h +++ b/system/bta/le_audio/le_audio_types.h @@ -33,10 +33,10 @@ #include <vector> #include "bluetooth/uuid.h" -#include "bta_le_audio_uuids.h" -#include "btm_iso_api_types.h" +#include "bta/include/bta_le_audio_uuids.h" #include "osi/include/alarm.h" #include "stack/include/bt_types.h" +#include "stack/include/btm_iso_api_types.h" namespace bluetooth::le_audio { @@ -556,8 +556,6 @@ struct LeAudioCoreCodecConfig { std::optional<uint16_t> octets_per_codec_frame; std::optional<uint8_t> codec_frames_blocks_per_sdu; - uint8_t allocated_channel_count = 1; - static uint32_t GetSamplingFrequencyHz(uint8_t sample_freq) { return sampling_freq_map.count(sample_freq) ? sampling_freq_map.at(sample_freq) @@ -592,16 +590,6 @@ struct LeAudioCoreCodecConfig { return 0; } - - /** Channel count per CIS or BIS */ - uint8_t GetChannelCountPerIsoStream(void) const { - return allocated_channel_count; - } - - uint16_t CalculateMaxSduSize() const { - return GetChannelCountPerIsoStream() * octets_per_codec_frame.value_or(0) * - codec_frames_blocks_per_sdu.value_or(1); - } }; struct LeAudioCoreCodecCapabilities { @@ -822,10 +810,6 @@ class LeAudioLtvMap { sizeof(decltype(core.audio_channel_allocation)::value_type))) { auto ptr = vec_opt->data(); STREAM_TO_UINT32(core.audio_channel_allocation, ptr); - core.allocated_channel_count = - std::bitset<32>(core.audio_channel_allocation.value()).count(); - } else { - core.allocated_channel_count = 1; } vec_opt = ltvs.Find(codec_spec_conf::kLeAudioLtvTypeOctetsPerCodecFrame); @@ -1079,6 +1063,7 @@ struct ase { /* Codec configuration */ LeAudioCodecId codec_id; LeAudioLtvMap codec_config; + uint8_t channel_count; /* Set to true, if the codec is implemented in BT controller, false if it's * implemented in host, or in separate DSP @@ -1170,6 +1155,8 @@ struct QosConfigSetting { uint8_t target_latency; uint8_t retransmission_number; uint16_t max_transport_latency; + int sduIntervalUs; + int maxSdu; bool operator!=(const QosConfigSetting& other) { return !(*this == other); } @@ -1219,18 +1206,6 @@ struct AudioSetConfiguration { // (codec_flags == other.codec_flags) && (confs == other.confs)); } - struct TopologyInfo { - /* How many sink and source devices must be in the set */ - types::BidirectionalPair<uint8_t> device_count; - /* Note: Strategy is used for selecting a particular configuration from the - * set of configurations if the configuration provider did not select a - * single configuration for us (json file configuration provider). - */ - types::BidirectionalPair<types::LeAudioConfigurationStrategy> strategy = { - types::LeAudioConfigurationStrategy::RFU, - types::LeAudioConfigurationStrategy::RFU}; - }; - std::optional<TopologyInfo> topology_info = std::nullopt; }; using AudioSetConfigurations = std::vector<const AudioSetConfiguration*>; @@ -1251,12 +1226,6 @@ void get_cis_count(types::LeAudioContextType context_type, int group_ase_snk_cnt, int group_ase_src_count, uint8_t& cis_count_bidir, uint8_t& cis_count_unidir_sink, uint8_t& cis_count_unidir_source); -bool check_if_may_cover_scenario( - const AudioSetConfigurations* audio_set_configurations, uint8_t group_size); -bool check_if_may_cover_scenario( - const AudioSetConfiguration* audio_set_configuration, uint8_t group_size); -uint8_t get_num_of_devices_in_configuration( - const AudioSetConfiguration* audio_set_configuration); } // namespace set_configurations struct stream_parameters { diff --git a/system/bta/le_audio/le_audio_types_test.cc b/system/bta/le_audio/le_audio_types_test.cc index c4b1a82672..86d1a81971 100644 --- a/system/bta/le_audio/le_audio_types_test.cc +++ b/system/bta/le_audio/le_audio_types_test.cc @@ -250,8 +250,6 @@ TEST(LeAudioLtvMapTest, test_configuration_valid) { // kLeAudioLocationFrontRight ASSERT_TRUE(config.audio_channel_allocation.has_value()); ASSERT_EQ(0x00000003u, config.audio_channel_allocation.value()); - // Check if allocated channel count matches the number of allocation bits - ASSERT_EQ(2u, config.GetChannelCountPerIsoStream()); // OctetsPerCodecFrame = 40 ASSERT_TRUE(config.octets_per_codec_frame.has_value()); diff --git a/system/bta/le_audio/le_audio_utils.cc b/system/bta/le_audio/le_audio_utils.cc index 007287efa5..273af7e52a 100644 --- a/system/bta/le_audio/le_audio_utils.cc +++ b/system/bta/le_audio/le_audio_utils.cc @@ -342,14 +342,8 @@ void fillStreamParamsToBtLeAudioCodecConfig( out_config.frame_duration = translateToBtLeAudioCodecConfigFrameDuration(config.GetDataIntervalUs()); out_config.octets_per_frame = config.GetOctectsPerFrame(); - - int num_of_channels = 0; - for (auto const& c : confs) { - num_of_channels += c.codec.GetChannelCountPerIsoStream(); - } - - out_config.channel_count = - translateToBtLeAudioCodecConfigChannelCount(num_of_channels); + out_config.channel_count = translateToBtLeAudioCodecConfigChannelCount( + config.GetChannelCountPerIsoStream()); } static bool is_known_codec(const types::LeAudioCodecId& codec_id) { @@ -401,6 +395,8 @@ static void fillRemotePacsCapabitiliesToBtLeAudioCodecConfig( if (!capa.IsAudioChannelCountsSupported(chan_bit)) continue; bluetooth::le_audio::btle_audio_codec_config_t config = { + .codec_type = utils::translateBluetoothCodecFormatToCodecType( + record.codec_id.coding_format), .sample_rate = utils::translateToBtLeAudioCodecConfigSampleRate( types::LeAudioCoreCodecConfig::GetSamplingFrequencyHz( freq_bit)), @@ -482,21 +478,48 @@ GetAudioSessionCodecConfigFromAudioSetConfiguration( break; } group_config.bits_per_sample = conf.codec.GetBitsPerSample(); - - log::assert_that( - audio_set_conf.topology_info.has_value(), - "No topology info, which is required to properly configure the ASEs"); - group_config.num_channels += - conf.codec.GetChannelCountPerIsoStream() * - audio_set_conf.topology_info->device_count.get(remote_direction); + group_config.num_channels += conf.codec.GetChannelCountPerIsoStream(); } + if (group_config.num_channels > 2) group_config.num_channels = 2; return group_config; } -static bool IsCodecConfigCoreSupported(const types::LeAudioLtvMap& pacs, - const types::LeAudioLtvMap& reqs, - uint8_t channel_cnt_per_ase) { +types::LeAudioConfigurationStrategy GetStrategyForAseConfig( + const std::vector<le_audio::set_configurations::AseConfiguration>& cfgs, + uint8_t device_cnt) { + if (cfgs.size() == 0) { + return types::LeAudioConfigurationStrategy::RFU; + } + + /* Banded headphones or the Classic TWS style topology (a single device) */ + if (device_cnt == 1) { + if (cfgs.at(0).codec.GetChannelCountPerIsoStream() == 1) { + /* One mono ASE - could be a single channel microphone */ + if (cfgs.size() == 1) { + return types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE; + } + + /* Each channel on a dedicated ASE - TWS style split channel re-routing */ + return types::LeAudioConfigurationStrategy::STEREO_TWO_CISES_PER_DEVICE; + } + + /* Banded headphones with 1 ASE - requires two channels per CIS */ + return types::LeAudioConfigurationStrategy::STEREO_ONE_CIS_PER_DEVICE; + } + + // We need at least 2 ASEs in the group config to set up more than one device + if (cfgs.size() == 1) { + return types::LeAudioConfigurationStrategy::RFU; + } + + /* The common one channel per device topology */ + return types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE; +} + +static bool IsCodecConfigSupported(const types::LeAudioLtvMap& pacs, + const types::LeAudioLtvMap& reqs, + uint8_t channel_cnt_per_ase) { auto caps = pacs.GetAsCoreCodecCapabilities(); auto config = reqs.GetAsCoreCodecConfig(); @@ -570,7 +593,7 @@ static bool IsCodecConfigSettingSupported( log::assert_that( !pac.codec_spec_caps.IsEmpty(), "Codec specific capabilities are not parsed approprietly."); - return IsCodecConfigCoreSupported( + return IsCodecConfigSupported( pac.codec_spec_caps, codec_config_setting.params, codec_config_setting.GetChannelCountPerIsoStream()); } diff --git a/system/bta/le_audio/le_audio_utils.h b/system/bta/le_audio/le_audio_utils.h index b676dbe0ce..6e6c2ee521 100644 --- a/system/bta/le_audio/le_audio_utils.h +++ b/system/bta/le_audio/le_audio_utils.h @@ -59,6 +59,9 @@ std::vector<bluetooth::le_audio::btle_audio_codec_config_t> GetRemoteBtLeAudioCodecConfigFromPac( const types::PublishedAudioCapabilities& group_pacs); bool IsCodecUsingLtvFormat(const types::LeAudioCodecId& codec_id); +types::LeAudioConfigurationStrategy GetStrategyForAseConfig( + const std::vector<le_audio::set_configurations::AseConfiguration>& cfgs, + uint8_t device_cnt); ::bluetooth::le_audio::LeAudioCodecConfiguration GetAudioSessionCodecConfigFromAudioSetConfiguration( const ::bluetooth::le_audio::set_configurations::AudioSetConfiguration& diff --git a/system/bta/le_audio/mock_codec_manager.cc b/system/bta/le_audio/mock_codec_manager.cc index 8abc4ecf49..cfdd4207ac 100644 --- a/system/bta/le_audio/mock_codec_manager.cc +++ b/system/bta/le_audio/mock_codec_manager.cc @@ -17,6 +17,7 @@ #include "mock_codec_manager.h" #include "broadcaster/broadcast_configuration_provider.h" +#include "le_audio/codec_manager.h" MockCodecManager* mock_codec_manager_pimpl_; MockCodecManager* MockCodecManager::GetInstance() { @@ -85,6 +86,13 @@ bool CodecManager::CheckCodecConfigIsBiDirSwb( return pimpl_->CheckCodecConfigIsBiDirSwb(config); } +bool CodecManager::CheckCodecConfigIsDualBiDirSwb( + const bluetooth::le_audio::set_configurations::AudioSetConfiguration& + config) const { + if (!pimpl_) return false; + return pimpl_->CheckCodecConfigIsDualBiDirSwb(config); +} + std::vector<bluetooth::le_audio::btle_audio_codec_config_t> CodecManager::GetLocalAudioOutputCodecCapa() { if (!pimpl_) diff --git a/system/bta/le_audio/mock_codec_manager.h b/system/bta/le_audio/mock_codec_manager.h index 1debbe4f4f..f398ab290c 100644 --- a/system/bta/le_audio/mock_codec_manager.h +++ b/system/bta/le_audio/mock_codec_manager.h @@ -53,7 +53,13 @@ class MockCodecManager { (const)); MOCK_METHOD( (bool), CheckCodecConfigIsBiDirSwb, - (const bluetooth::le_audio::set_configurations::AudioSetConfiguration&), + (const bluetooth::le_audio::set_configurations::AudioSetConfiguration& + config), + (const)); + MOCK_METHOD( + (bool), CheckCodecConfigIsDualBiDirSwb, + (const bluetooth::le_audio::set_configurations::AudioSetConfiguration& + config), (const)); MOCK_METHOD((std::unique_ptr< bluetooth::le_audio::broadcaster::BroadcastConfiguration>), diff --git a/system/bta/le_audio/state_machine.cc b/system/bta/le_audio/state_machine.cc index 02ac297e5e..84409a20a8 100644 --- a/system/bta/le_audio/state_machine.cc +++ b/system/bta/le_audio/state_machine.cc @@ -728,13 +728,13 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine { uint32_t crcErrorPackets, uint32_t rxUnreceivedPackets, uint32_t duplicatePackets) { log::info( - "conn_handle: {}, txUnackedPackets: {}, txFlushedPackets: {}, " - "txLastSubeventPackets: {}, retransmittedPackets: {}, crcErrorPackets: " - "{}, rxUnreceivedPackets: {}, duplicatePackets: {}", - loghex(conn_handle), loghex(txUnackedPackets), loghex(txFlushedPackets), - loghex(txLastSubeventPackets), loghex(retransmittedPackets), - loghex(crcErrorPackets), loghex(rxUnreceivedPackets), - loghex(duplicatePackets)); + "conn_handle: 0x{:x}, txUnackedPackets: 0x{:x}, txFlushedPackets: " + "0x{:x}, txLastSubeventPackets: 0x{:x}, retransmittedPackets: 0x{:x}, " + "crcErrorPackets: 0x{:x}, rxUnreceivedPackets: 0x{:x}, " + "duplicatePackets: 0x{:x}", + conn_handle, txUnackedPackets, txFlushedPackets, txLastSubeventPackets, + retransmittedPackets, crcErrorPackets, rxUnreceivedPackets, + duplicatePackets); } void ReleaseCisIds(LeAudioDeviceGroup* group) { @@ -1067,7 +1067,7 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine { if (value.size() > (leAudioDevice->mtu_ - 3)) { log::warn("{}, using long write procedure ({} > {})", leAudioDevice->address_, static_cast<int>(value.size()), - (leAudioDevice->mtu_ - 3)); + leAudioDevice->mtu_ - 3); /* Note, that this type is actually LONG WRITE. * Meaning all the Prepare Writes plus Execute is handled in the stack @@ -1348,7 +1348,7 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine { auto core_config = ase->codec_config.GetAsCoreCodecConfig(); params.num_of_devices++; - params.num_of_channels += core_config.GetChannelCountPerIsoStream(); + params.num_of_channels += ase->channel_count; if (!core_config.audio_channel_allocation.has_value()) { log::warn("ASE has invalid audio location"); @@ -1700,8 +1700,8 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine { BTM_GetHCIConnHandle(leAudioDevice->address_, BT_TRANSPORT_LE); conn_pairs.push_back({.cis_conn_handle = ase->cis_conn_hdl, .acl_conn_handle = acl_handle}); - log::debug("cis handle: {} acl handle : {}", ase->cis_conn_hdl, - loghex(+acl_handle)); + log::debug("cis handle: {} acl handle : 0x{:x}", ase->cis_conn_hdl, + acl_handle); } while ((ase = leAudioDevice->GetNextActiveAse(ase))); } while ((leAudioDevice = group->GetNextActiveDevice(leAudioDevice))); diff --git a/system/bta/le_audio/state_machine_test.cc b/system/bta/le_audio/state_machine_test.cc index ff428f8403..c41b001fd5 100644 --- a/system/bta/le_audio/state_machine_test.cc +++ b/system/bta/le_audio/state_machine_test.cc @@ -20,6 +20,7 @@ #include <bluetooth/log.h> #include <gmock/gmock.h> #include <gtest/gtest.h> +#include <log/log.h> #include <functional> @@ -32,6 +33,7 @@ #include "fake_osi.h" #include "hci/controller_interface_mock.h" #include "internal_include/stack_config.h" +#include "le_audio/le_audio_types.h" #include "le_audio_set_configuration_provider.h" #include "mock_codec_manager.h" #include "mock_csis_client.h" @@ -245,7 +247,14 @@ class StateMachineTestBase : public Test { uint8_t additional_snk_ases = 0; uint8_t additional_src_ases = 0; uint8_t channel_count_ = kLeAudioCodecChannelCountSingleChannel; - uint16_t sample_freq_ = codec_specific::kCapSamplingFrequency16000Hz; + uint16_t sample_freq_ = codec_specific::kCapSamplingFrequency16000Hz | + codec_specific::kCapSamplingFrequency32000Hz; + uint8_t channel_allocations_sink_ = + ::bluetooth::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft | + ::bluetooth::le_audio::codec_spec_conf::kLeAudioLocationFrontRight; + uint8_t channel_allocations_source_ = + ::bluetooth::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft | + ::bluetooth::le_audio::codec_spec_conf::kLeAudioLocationFrontRight; /* Use to simulated error status on Cis creation */ bool overwrite_cis_status_; @@ -262,6 +271,7 @@ class StateMachineTestBase : public Test { bool stop_inject_configured_ase_after_first_ase_configured_; virtual void SetUp() override { + __android_log_set_minimum_priority(ANDROID_LOG_DEBUG); reset_mock_function_count_map(); bluetooth::manager::SetMockBtmInterface(&btm_interface); gatt::SetMockBtaGattInterface(&gatt_interface); @@ -598,6 +608,15 @@ class StateMachineTestBase : public Test { ON_CALL(*mock_codec_manager_, GetCodecLocation()) .WillByDefault(Return(location)); // Regardless of the codec location, return all the possible configurations + ON_CALL(*mock_codec_manager_, IsDualBiDirSwbSupported) + .WillByDefault(Return(true)); + ON_CALL(*mock_codec_manager_, CheckCodecConfigIsBiDirSwb) + .WillByDefault( + Invoke([](const set_configurations::AudioSetConfiguration& config) + -> bool { + return AudioSetConfigurationProvider::Get() + ->CheckConfigurationIsBiDirSwb(config); + })); ON_CALL(*mock_codec_manager_, GetCodecConfig) .WillByDefault(Invoke([](const bluetooth::le_audio::CodecManager:: UnicastConfigurationRequirements& @@ -605,9 +624,22 @@ class StateMachineTestBase : public Test { bluetooth::le_audio::CodecManager:: UnicastConfigurationVerifier verifier) { auto configs = - bluetooth::le_audio::AudioSetConfigurationProvider::Get() - ->GetConfigurations(requirements.audio_context_type); - auto cfg = verifier(requirements, configs); + *bluetooth::le_audio::AudioSetConfigurationProvider::Get() + ->GetConfigurations(requirements.audio_context_type); + // Note: This dual bidir SWB exclusion logic has to match the + // CodecManager::GetCodecConfig() implementation. + if (!CodecManager::GetInstance()->IsDualBiDirSwbSupported()) { + configs.erase( + std::remove_if(configs.begin(), configs.end(), + [](auto const& el) { + if (el->confs.source.empty()) return false; + return AudioSetConfigurationProvider::Get() + ->CheckConfigurationIsDualBiDirSwb(*el); + }), + configs.end()); + } + + auto cfg = verifier(requirements, &configs); if (cfg == nullptr) { return std::unique_ptr< bluetooth::le_audio::set_configurations::AudioSetConfiguration>( @@ -671,7 +703,7 @@ class StateMachineTestBase : public Test { ase.hdls.val_hdl = attr_handle++; ase.hdls.ccc_hdl = attr_handle++; - leAudioDevice->ases_.emplace_back(std::move(ase)); + leAudioDevice->ases_.push_back(std::move(ase)); num_ase_snk--; } @@ -681,7 +713,7 @@ class StateMachineTestBase : public Test { ase.hdls.val_hdl = attr_handle++; ase.hdls.ccc_hdl = attr_handle++; - leAudioDevice->ases_.emplace_back(std::move(ase)); + leAudioDevice->ases_.push_back(std::move(ase)); num_ase_src--; } @@ -1015,11 +1047,7 @@ class StateMachineTestBase : public Test { std::make_tuple(std::move(handle_pair), pac_recs)); snk_context_type.set(context_type); - leAudioDevice->snk_audio_locations_ = - ::bluetooth::le_audio::codec_spec_conf:: - kLeAudioLocationFrontLeft | - ::bluetooth::le_audio::codec_spec_conf:: - kLeAudioLocationFrontRight; + leAudioDevice->snk_audio_locations_ = channel_allocations_sink_; } // Prepare Source Published Audio Capability records @@ -1029,7 +1057,8 @@ class StateMachineTestBase : public Test { std::vector<types::acs_ac_record> pac_recs; InsertPacRecord(pac_recs, - codec_specific::kCapSamplingFrequency16000Hz, + codec_specific::kCapSamplingFrequency16000Hz | + codec_specific::kCapSamplingFrequency32000Hz, codec_specific::kCapFrameDuration10ms | codec_specific::kCapFrameDuration7p5ms | codec_specific::kCapFrameDuration10msPreferred, @@ -1043,11 +1072,7 @@ class StateMachineTestBase : public Test { std::make_tuple(std::move(handle_pair), pac_recs)); src_context_type.set(context_type); - leAudioDevice->src_audio_locations_ = - ::bluetooth::le_audio::codec_spec_conf:: - kLeAudioLocationFrontLeft | - ::bluetooth::le_audio::codec_spec_conf:: - kLeAudioLocationFrontRight; + leAudioDevice->src_audio_locations_ = channel_allocations_source_; } leAudioDevice->SetSupportedContexts( @@ -1578,6 +1603,17 @@ class StateMachineTest : public StateMachineTestBase { } }; +class StateMachineTestNoSwb : public StateMachineTestBase { + void SetUp() override { + ConfigCodecManagerMock(types::CodecLocation::HOST); + ::bluetooth::le_audio::AudioSetConfigurationProvider::Initialize( + ::bluetooth::le_audio::types::CodecLocation::HOST); + ON_CALL(*mock_codec_manager_, IsDualBiDirSwbSupported) + .WillByDefault(Return(false)); + StateMachineTestBase::SetUp(); + } +}; + class StateMachineTestAdsp : public StateMachineTestBase { void SetUp() override { ConfigCodecManagerMock(types::CodecLocation::ADSP); @@ -5478,6 +5514,264 @@ TEST_F(StateMachineTest, testReconfigureAfterLateDeviceAttached) { ASSERT_NE(ase->qos_config.retrans_nb, 0); } +TEST_F(StateMachineTest, + testReconfigureAfterLateDeviceAttachedConversationalSwb) { + const auto context_type = kContextTypeConversational; + const auto leaudio_group_id = 6; + const auto num_devices = 2; + + ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid); + + // Prepare multiple fake connected devices in a group + auto* group = + PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices); + ASSERT_EQ(group->Size(), num_devices); + + PrepareConfigureCodecHandler(group, 0, true); + PrepareConfigureQosHandler(group); + PrepareEnableHandler(group); + PrepareReceiverStartReadyHandler(group); + PrepareDisableHandler(group); + PrepareReleaseHandler(group); + + auto* leAudioDevice = group->GetFirstDevice(); + LeAudioDevice* lastDevice; + LeAudioDevice* fistDevice = leAudioDevice; + + while (leAudioDevice) { + lastDevice = leAudioDevice; + leAudioDevice = group->GetNextDevice(leAudioDevice); + } + + InjectInitialIdleNotification(group); + + // Inject CIS and ACL disconnection of first device + InjectCisDisconnected(group, lastDevice, HCI_ERR_CONNECTION_TOUT); + InjectAclDisconnected(group, lastDevice); + + /* First device connected. Configure it to stream media */ + EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1); + EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1); + EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2); + + types::BidirectionalPair<std::vector<uint8_t>> ccids_list = { + .sink = {media_ccid}, .source = {media_ccid}}; + + // Start the configuration and stream Media content + LeAudioGroupStateMachine::Get()->StartStream( + group, context_type, + {.sink = types::AudioContexts(context_type), + .source = types::AudioContexts(context_type)}, + ccids_list); + + auto current_config = group->GetCachedConfiguration(context_type); + ASSERT_NE(nullptr, current_config.get()); + // With a single device there will be no dual bidir SWB but a single bidir SWB + ASSERT_TRUE( + AudioSetConfigurationProvider::Get()->CheckConfigurationIsBiDirSwb( + *current_config.get())); + ASSERT_FALSE( + AudioSetConfigurationProvider::Get()->CheckConfigurationIsDualBiDirSwb( + *current_config.get())); + + // Check if group has transitioned to a proper state + ASSERT_EQ(group->GetState(), + types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING); + testing::Mock::VerifyAndClearExpectations(mock_iso_manager_); + + /* Stop the stream and let first device to stay in configured state (caching + * is on)*/ + LeAudioGroupStateMachine::Get()->StopStream(group); + testing::Mock::VerifyAndClearExpectations(&mock_callbacks_); + + /* Verify state in the configured state */ + ASSERT_EQ(group->GetState(), + types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED); + + /* Now when stream is stopped, connect second device. */ + lastDevice->conn_id_ = 3; + lastDevice->SetConnectionState(DeviceConnectState::CONNECTED); + + group->UpdateAudioContextAvailability(); + group->UpdateAudioSetConfigurationCache(context_type); + + /* Start stream, make sure 2 devices are started. */ + EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1); + EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1); + EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(4); + + // Start the configuration and stream Media content + LeAudioGroupStateMachine::Get()->StartStream( + group, context_type, + {.sink = types::AudioContexts(context_type), + .source = types::AudioContexts(context_type)}, + ccids_list); + + // Check if group keeps streaming + ASSERT_EQ(group->GetState(), + types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING); + + // Verify that both devicse receives the right CCID list and both are + // streaming + auto ase = lastDevice->GetFirstActiveAse(); + + // No ASE was activated - that's bad + ASSERT_NE(nullptr, ase); + auto lastMeta = ase->metadata; + bool parsedOk = false; + auto ltv = bluetooth::le_audio::types::LeAudioLtvMap::Parse( + lastMeta.data(), lastMeta.size(), parsedOk); + ASSERT_TRUE(parsedOk); + + auto ccids = + ltv.Find(bluetooth::le_audio::types::kLeAudioMetadataTypeCcidList); + ASSERT_TRUE(ccids.has_value()); + ASSERT_NE(std::find(ccids->begin(), ccids->end(), media_ccid), ccids->end()); + + /* Verify that ASE of first device are still good*/ + ase = fistDevice->GetFirstActiveAse(); + ASSERT_NE(nullptr, ase); + ASSERT_NE(ase->qos_config.max_transport_latency, 0); + ASSERT_NE(ase->qos_config.retrans_nb, 0); + + // With both devices we should get the dual bidir SWB configuration + current_config = group->GetCachedConfiguration(context_type); + ASSERT_NE(nullptr, current_config.get()); + ASSERT_TRUE( + AudioSetConfigurationProvider::Get()->CheckConfigurationIsDualBiDirSwb( + *current_config.get())); +} + +TEST_F(StateMachineTestNoSwb, + testReconfigureAfterLateDeviceAttachedConversationalNoSwb) { + const auto context_type = kContextTypeConversational; + const auto leaudio_group_id = 6; + const auto num_devices = 2; + + ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid); + + // Prepare multiple fake connected devices in a group + auto* group = + PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices); + ASSERT_EQ(group->Size(), num_devices); + + PrepareConfigureCodecHandler(group, 0, true); + PrepareConfigureQosHandler(group); + PrepareEnableHandler(group); + PrepareReceiverStartReadyHandler(group); + PrepareDisableHandler(group); + PrepareReleaseHandler(group); + + auto* leAudioDevice = group->GetFirstDevice(); + LeAudioDevice* lastDevice; + LeAudioDevice* fistDevice = leAudioDevice; + + while (leAudioDevice) { + lastDevice = leAudioDevice; + leAudioDevice = group->GetNextDevice(leAudioDevice); + } + + InjectInitialIdleNotification(group); + + // Inject CIS and ACL disconnection of first device + InjectCisDisconnected(group, lastDevice, HCI_ERR_CONNECTION_TOUT); + InjectAclDisconnected(group, lastDevice); + + /* First device connected. Configure it to stream media */ + EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1); + EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1); + EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2); + + types::BidirectionalPair<std::vector<uint8_t>> ccids_list = { + .sink = {media_ccid}, .source = {media_ccid}}; + + // Start the configuration and stream Media content + LeAudioGroupStateMachine::Get()->StartStream( + group, context_type, + {.sink = types::AudioContexts(context_type), + .source = types::AudioContexts(context_type)}, + ccids_list); + + auto current_config = group->GetCachedConfiguration(context_type); + ASSERT_NE(nullptr, current_config.get()); + // With a single device there shall be no bidir SWB, as we expect the 2nd + // device to join the stream seamlessly while dual bidir SWB is disabled. + ASSERT_FALSE( + AudioSetConfigurationProvider::Get()->CheckConfigurationIsBiDirSwb( + *current_config.get())); + ASSERT_FALSE( + AudioSetConfigurationProvider::Get()->CheckConfigurationIsDualBiDirSwb( + *current_config.get())); + + // Check if group has transitioned to a proper state + ASSERT_EQ(group->GetState(), + types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING); + testing::Mock::VerifyAndClearExpectations(mock_iso_manager_); + + /* Stop the stream and let first device to stay in configured state (caching + * is on)*/ + LeAudioGroupStateMachine::Get()->StopStream(group); + testing::Mock::VerifyAndClearExpectations(&mock_callbacks_); + + /* Verify state in the configured state */ + ASSERT_EQ(group->GetState(), + types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED); + + /* Now when stream is stopped, connect second device. */ + lastDevice->conn_id_ = 3; + lastDevice->SetConnectionState(DeviceConnectState::CONNECTED); + + group->UpdateAudioContextAvailability(); + group->UpdateAudioSetConfigurationCache(context_type); + + /* Start stream, make sure 2 devices are started. */ + EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1); + EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1); + EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(4); + + // Start the configuration and stream Media content + LeAudioGroupStateMachine::Get()->StartStream( + group, context_type, + {.sink = types::AudioContexts(context_type), + .source = types::AudioContexts(context_type)}, + ccids_list); + + // Check if group keeps streaming + ASSERT_EQ(group->GetState(), + types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING); + + // Verify that both devicse receives the right CCID list and both are + // streaming + auto ase = lastDevice->GetFirstActiveAse(); + + // No ASE was activated - that's bad + ASSERT_NE(nullptr, ase); + auto lastMeta = ase->metadata; + bool parsedOk = false; + auto ltv = bluetooth::le_audio::types::LeAudioLtvMap::Parse( + lastMeta.data(), lastMeta.size(), parsedOk); + ASSERT_TRUE(parsedOk); + + auto ccids = + ltv.Find(bluetooth::le_audio::types::kLeAudioMetadataTypeCcidList); + ASSERT_TRUE(ccids.has_value()); + ASSERT_NE(std::find(ccids->begin(), ccids->end(), media_ccid), ccids->end()); + + /* Verify that ASE of first device are still good*/ + ase = fistDevice->GetFirstActiveAse(); + ASSERT_NE(nullptr, ase); + ASSERT_NE(ase->qos_config.max_transport_latency, 0); + ASSERT_NE(ase->qos_config.retrans_nb, 0); + + // With both devices we still should not get the dual bidir SWB configuration + // as it is currently disabled. + current_config = group->GetCachedConfiguration(context_type); + ASSERT_NE(nullptr, current_config.get()); + ASSERT_FALSE( + AudioSetConfigurationProvider::Get()->CheckConfigurationIsDualBiDirSwb( + *current_config.get())); +} + TEST_F(StateMachineTest, testStreamToGettingReadyDevice) { const auto context_type = kContextTypeLive; const auto leaudio_group_id = 666; @@ -6050,6 +6344,11 @@ TEST_F(StateMachineTest, BoundedHeadphonesConversationalToMediaChannelCount_2) { testing::Mock::VerifyAndClearExpectations(&mock_callbacks_); + auto current_config = group->GetCachedConfiguration(initial_context_type); + ASSERT_NE(nullptr, current_config); + ASSERT_EQ(1lu, current_config->confs.sink.size()); + ASSERT_EQ(1lu, current_config->confs.source.size()); + // Validate GroupStreamStatus EXPECT_CALL( mock_callbacks_, @@ -6079,13 +6378,22 @@ TEST_F(StateMachineTest, BoundedHeadphonesConversationalToMediaChannelCount_2) { .source = types::AudioContexts(new_context_type)}); testing::Mock::VerifyAndClearExpectations(&mock_callbacks_); + + current_config = group->GetCachedConfiguration(new_context_type); + ASSERT_NE(nullptr, current_config); + ASSERT_EQ(1lu, current_config->confs.sink.size()); + ASSERT_EQ(0lu, current_config->confs.source.size()); } -TEST_F(StateMachineTest, BoundedHeadphonesConversationalToMediaChannelCount_1) { +TEST_F(StateMachineTest, + BoundedHeadphonesConversationalToMediaChannelCount_1_MonoMic) { const auto initial_context_type = kContextTypeConversational; const auto new_context_type = kContextTypeMedia; const auto leaudio_group_id = 6; const auto num_devices = 1; + // Single audio allocation for the mono source + channel_allocations_source_ = + ::bluetooth::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft; channel_count_ = kLeAudioCodecChannelCountSingleChannel; sample_freq_ |= codec_specific::kCapSamplingFrequency48000Hz | @@ -6146,6 +6454,13 @@ TEST_F(StateMachineTest, BoundedHeadphonesConversationalToMediaChannelCount_1) { testing::Mock::VerifyAndClearExpectations(&mock_callbacks_); + auto current_config = group->GetCachedConfiguration(initial_context_type); + ASSERT_NE(nullptr, current_config); + // sink has two locations + ASSERT_EQ(2lu, current_config->confs.sink.size()); + // source has a single location + ASSERT_EQ(1lu, current_config->confs.source.size()); + ASSERT_EQ(1, get_func_call_count("alarm_cancel")); reset_mock_function_count_map(); @@ -6181,6 +6496,128 @@ TEST_F(StateMachineTest, BoundedHeadphonesConversationalToMediaChannelCount_1) { testing::Mock::VerifyAndClearExpectations(&mock_callbacks_); ASSERT_EQ(1, get_func_call_count("alarm_cancel")); + + current_config = group->GetCachedConfiguration(new_context_type); + ASSERT_NE(nullptr, current_config); + ASSERT_EQ(2lu, current_config->confs.sink.size()); + ASSERT_EQ(0lu, current_config->confs.source.size()); +} + +TEST_F( + StateMachineTest, + DISABLED_BoundedHeadphonesConversationalToMediaChannelCount_1_StereoMic) { + const auto initial_context_type = kContextTypeConversational; + const auto new_context_type = kContextTypeMedia; + const auto leaudio_group_id = 6; + const auto num_devices = 1; + channel_allocations_source_ = + ::bluetooth::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft | + ::bluetooth::le_audio::codec_spec_conf::kLeAudioLocationFrontRight; + channel_count_ = kLeAudioCodecChannelCountSingleChannel; + + sample_freq_ |= codec_specific::kCapSamplingFrequency48000Hz | + codec_specific::kCapSamplingFrequency32000Hz; + additional_snk_ases = 3; + additional_src_ases = 1; + + ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid); + ContentControlIdKeeper::GetInstance()->SetCcid(call_context, call_ccid); + + // Prepare one fake connected devices in a group + auto* group = PrepareSingleTestDeviceGroup( + leaudio_group_id, initial_context_type, num_devices, + kContextTypeConversational | kContextTypeMedia); + ASSERT_EQ(group->Size(), num_devices); + + // Cannot verify here as we will change the number of ases on reconfigure + PrepareConfigureCodecHandler(group, 0, true); + PrepareConfigureQosHandler(group); + PrepareEnableHandler(group); + PrepareDisableHandler(group); + PrepareReleaseHandler(group); + PrepareReceiverStartReadyHandler(group); + + InjectInitialIdleNotification(group); + + auto* leAudioDevice = group->GetFirstDevice(); + auto expected_devices_written = 0; + while (leAudioDevice) { + /* 8 Writes: + * 1: Codec config (+1 after reconfig) + * 2: Codec QoS (+1 after reconfig) + * 3: Enabling (+1 after reconfig) + * 4: ReceiverStartReady (only for conversational) + * 5: Release + */ + EXPECT_CALL(gatt_queue, + WriteCharacteristic(leAudioDevice->conn_id_, + leAudioDevice->ctp_hdls_.val_hdl, _, + GATT_WRITE_NO_RSP, _, _)) + .Times(8); + expected_devices_written++; + leAudioDevice = group->GetNextDevice(leAudioDevice); + } + ASSERT_EQ(expected_devices_written, num_devices); + + // Validate GroupStreamStatus + EXPECT_CALL( + mock_callbacks_, + StatusReportCb(leaudio_group_id, + bluetooth::le_audio::GroupStreamStatus::STREAMING)); + + // Start the configuration and stream Media content + LeAudioGroupStateMachine::Get()->StartStream( + group, initial_context_type, + {.sink = types::AudioContexts(initial_context_type), + .source = types::AudioContexts(initial_context_type)}); + + testing::Mock::VerifyAndClearExpectations(&mock_callbacks_); + + ASSERT_EQ(1, get_func_call_count("alarm_cancel")); + reset_mock_function_count_map(); + + auto current_config = group->GetCachedConfiguration(initial_context_type); + ASSERT_NE(nullptr, current_config); + ASSERT_EQ(2lu, current_config->confs.sink.size()); + ASSERT_EQ(2lu, current_config->confs.source.size()); + + // Validate GroupStreamStatus + EXPECT_CALL( + mock_callbacks_, + StatusReportCb(leaudio_group_id, + bluetooth::le_audio::GroupStreamStatus::RELEASING)); + + EXPECT_CALL( + mock_callbacks_, + StatusReportCb( + leaudio_group_id, + bluetooth::le_audio::GroupStreamStatus::CONFIGURED_AUTONOMOUS)); + // Start the configuration and stream Media content + LeAudioGroupStateMachine::Get()->StopStream(group); + + testing::Mock::VerifyAndClearExpectations(&mock_callbacks_); + ASSERT_EQ(1, get_func_call_count("alarm_cancel")); + reset_mock_function_count_map(); + + // Restart stream + EXPECT_CALL( + mock_callbacks_, + StatusReportCb(leaudio_group_id, + bluetooth::le_audio::GroupStreamStatus::STREAMING)); + + // Start the configuration and stream Media content + LeAudioGroupStateMachine::Get()->StartStream( + group, new_context_type, + {.sink = types::AudioContexts(new_context_type), + .source = types::AudioContexts(new_context_type)}); + + testing::Mock::VerifyAndClearExpectations(&mock_callbacks_); + ASSERT_EQ(1, get_func_call_count("alarm_cancel")); + + current_config = group->GetCachedConfiguration(new_context_type); + ASSERT_NE(nullptr, current_config); + ASSERT_EQ(2lu, current_config->confs.sink.size()); + ASSERT_EQ(0lu, current_config->confs.source.size()); } TEST_F(StateMachineTest, lateCisDisconnectedEvent_DuringReconfiguration) { diff --git a/system/bta/test/bta_disc_test.cc b/system/bta/test/bta_disc_test.cc index bab8857dab..fa48131dc0 100644 --- a/system/bta/test/bta_disc_test.cc +++ b/system/bta/test/bta_disc_test.cc @@ -19,8 +19,9 @@ #include <gtest/gtest.h> #include <sys/socket.h> +#include "bta/dm/bta_dm_device_search.h" +#include "bta/dm/bta_dm_device_search_int.h" #include "bta/dm/bta_dm_disc.h" -#include "bta/dm/bta_dm_disc_int.h" #include "bta/test/bta_test_fixtures.h" #include "stack/btm/neighbor_inquiry.h" #include "stack/include/gatt_api.h" @@ -41,7 +42,6 @@ bool bta_dm_read_remote_device_name(const RawAddress& bd_addr, tBT_TRANSPORT transport); tBTA_DM_SEARCH_CB& bta_dm_disc_search_cb(); void bta_dm_discover_next_device(); -void bta_dm_execute_queued_request(); void bta_dm_find_services(const RawAddress& bd_addr); void bta_dm_inq_cmpl(); void bta_dm_inq_cmpl_cb(void* p_result); @@ -52,10 +52,7 @@ void bta_dm_opportunistic_observe_results_cb(tBTM_INQ_RESULTS* p_inq, const uint8_t* p_eir, uint16_t eir_len); void bta_dm_queue_search(tBTA_DM_API_SEARCH& search); -void bta_dm_service_search_remname_cback(const RawAddress& bd_addr, - DEV_CLASS dc, BD_NAME bd_name); void bta_dm_start_scan(uint8_t duration_sec, bool low_latency_scan = false); -void store_avrcp_profile_feature(tSDP_DISC_REC* sdp_rec); } // namespace testing } // namespace legacy @@ -113,10 +110,6 @@ TEST_F(BtaInitializedTest, bta_dm_discover_next_device) { bluetooth::legacy::testing::bta_dm_discover_next_device(); } -TEST_F(BtaInitializedTest, bta_dm_execute_queued_request) { - bluetooth::legacy::testing::bta_dm_execute_queued_request(); -} - TEST_F(BtaInitializedTest, bta_dm_find_services) { bluetooth::legacy::testing::bta_dm_find_services(kRawAddress); } @@ -163,27 +156,6 @@ TEST_F(BtaInitializedTest, bta_dm_read_remote_device_name) { kRawAddress, BT_TRANSPORT_BR_EDR); } -TEST_F(BtaInitializedTest, bta_dm_service_search_remname_cback__expected_name) { - DEV_CLASS dc; - BD_NAME bd_name; - tBTA_DM_SEARCH_CB& search_cb = - bluetooth::legacy::testing::bta_dm_disc_search_cb(); - search_cb.peer_bdaddr = kRawAddress, - bluetooth::legacy::testing::bta_dm_service_search_remname_cback(kRawAddress, - dc, bd_name); -} - -TEST_F(BtaInitializedTest, - bta_dm_service_search_remname_cback__unexpected_name) { - DEV_CLASS dc; - BD_NAME bd_name; - tBTA_DM_SEARCH_CB& search_cb = - bluetooth::legacy::testing::bta_dm_disc_search_cb(); - search_cb.peer_bdaddr = RawAddress::kAny; - bluetooth::legacy::testing::bta_dm_service_search_remname_cback(kRawAddress, - dc, bd_name); -} - TEST_F(BtaInitializedTest, bta_dm_start_scan) { constexpr bool kLowLatencyScan = true; constexpr bool kHighLatencyScan = false; @@ -192,11 +164,6 @@ TEST_F(BtaInitializedTest, bta_dm_start_scan) { bluetooth::legacy::testing::bta_dm_start_scan(duration_sec, kHighLatencyScan); } -TEST_F(BtaInitializedTest, store_avrcp_profile_feature) { - tSDP_DISC_REC sdp_rec = {}; - bluetooth::legacy::testing::store_avrcp_profile_feature(&sdp_rec); -} - TEST_F(BtaInitializedTest, bta_dm_disc_start_device_discovery) { bta_dm_disc_start_device_discovery( [](tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH* p_data) {}); @@ -210,8 +177,8 @@ TEST_F(BtaInitializedTest, bta_dm_disc_start_service_discovery__BT_TRANSPORT_AUTO) { bta_dm_disc_start_service_discovery( {nullptr, nullptr, nullptr, - [](RawAddress, tBTA_SERVICE_MASK, tBT_DEVICE_TYPE, - const std::vector<bluetooth::Uuid>&, tBTA_STATUS, tHCI_STATUS) {}}, + [](RawAddress, tBTA_SERVICE_MASK, const std::vector<bluetooth::Uuid>&, + tBTA_STATUS, tHCI_STATUS) {}}, kRawAddress, BT_TRANSPORT_AUTO); } @@ -219,8 +186,8 @@ TEST_F(BtaInitializedTest, bta_dm_disc_start_service_discovery__BT_TRANSPORT_BR_EDR) { bta_dm_disc_start_service_discovery( {nullptr, nullptr, nullptr, - [](RawAddress, tBTA_SERVICE_MASK, tBT_DEVICE_TYPE, - const std::vector<bluetooth::Uuid>&, tBTA_STATUS, tHCI_STATUS) {}}, + [](RawAddress, tBTA_SERVICE_MASK, const std::vector<bluetooth::Uuid>&, + tBTA_STATUS, tHCI_STATUS) {}}, kRawAddress, BT_TRANSPORT_BR_EDR); } @@ -228,21 +195,19 @@ TEST_F(BtaInitializedTest, bta_dm_disc_start_service_discovery__BT_TRANSPORT_LE) { bta_dm_disc_start_service_discovery( {nullptr, nullptr, nullptr, - [](RawAddress, tBTA_SERVICE_MASK, tBT_DEVICE_TYPE, - const std::vector<bluetooth::Uuid>&, tBTA_STATUS, tHCI_STATUS) {}}, + [](RawAddress, tBTA_SERVICE_MASK, const std::vector<bluetooth::Uuid>&, + tBTA_STATUS, tHCI_STATUS) {}}, kRawAddress, BT_TRANSPORT_LE); } TEST_F(BtaInitializedTest, init_bta_dm_search_cb__conn_id) { - constexpr uint16_t kConnId = 123; - // Set the global search block target field to some non-reset value tBTA_DM_SEARCH_CB& search_cb = bluetooth::legacy::testing::bta_dm_disc_search_cb(); - search_cb.conn_id = kConnId; + search_cb.name_discover_done = true; bluetooth::legacy::testing::bta_dm_disc_init_search_cb(search_cb); // Verify global search block field reset value is correct - ASSERT_EQ(search_cb.conn_id, GATT_INVALID_CONN_ID); + ASSERT_EQ(search_cb.name_discover_done, false); } diff --git a/system/bta/test/bta_dm_test.cc b/system/bta/test/bta_dm_test.cc index c6c9dd1281..fe32258a95 100644 --- a/system/bta/test/bta_dm_test.cc +++ b/system/bta/test/bta_dm_test.cc @@ -24,8 +24,9 @@ #include <string> +#include "bta/dm/bta_dm_device_search.h" +#include "bta/dm/bta_dm_device_search_int.h" #include "bta/dm/bta_dm_disc.h" -#include "bta/dm/bta_dm_disc_int.h" #include "bta/dm/bta_dm_int.h" #include "bta/dm/bta_dm_pm.cc" #include "bta/dm/bta_dm_sec_int.h" @@ -315,47 +316,6 @@ TEST_F(BtaDmTest, bta_dm_encrypt_cback) { ASSERT_EQ(BTA_FAILURE, params_BTM_ILLEGAL_VALUE.result); } -TEST_F(BtaDmTest, bta_dm_event_text) { - std::vector<std::pair<tBTA_DM_EVT, std::string>> events = { - std::make_pair(BTA_DM_API_SEARCH_EVT, "BTA_DM_API_SEARCH_EVT"), - std::make_pair(BTA_DM_API_DISCOVER_EVT, "BTA_DM_API_DISCOVER_EVT"), - std::make_pair(BTA_DM_INQUIRY_CMPL_EVT, "BTA_DM_INQUIRY_CMPL_EVT"), - std::make_pair(BTA_DM_REMT_NAME_EVT, "BTA_DM_REMT_NAME_EVT"), - std::make_pair(BTA_DM_SDP_RESULT_EVT, "BTA_DM_SDP_RESULT_EVT"), - std::make_pair(BTA_DM_SEARCH_CMPL_EVT, "BTA_DM_SEARCH_CMPL_EVT"), - std::make_pair(BTA_DM_DISCOVERY_RESULT_EVT, - "BTA_DM_DISCOVERY_RESULT_EVT"), - std::make_pair(BTA_DM_DISC_CLOSE_TOUT_EVT, "BTA_DM_DISC_CLOSE_TOUT_EVT"), - }; - for (const auto& event : events) { - ASSERT_STREQ(event.second.c_str(), bta_dm_event_text(event.first).c_str()); - } - ASSERT_STREQ(base::StringPrintf("UNKNOWN[0x%04x]", - std::numeric_limits<uint16_t>::max()) - .c_str(), - bta_dm_event_text(static_cast<tBTA_DM_EVT>( - std::numeric_limits<uint16_t>::max())) - .c_str()); -} - -TEST_F(BtaDmTest, bta_dm_state_text) { - std::vector<std::pair<tBTA_DM_STATE, std::string>> states = { - std::make_pair(BTA_DM_SEARCH_IDLE, "BTA_DM_SEARCH_IDLE"), - std::make_pair(BTA_DM_SEARCH_ACTIVE, "BTA_DM_SEARCH_ACTIVE"), - std::make_pair(BTA_DM_SEARCH_CANCELLING, "BTA_DM_SEARCH_CANCELLING"), - std::make_pair(BTA_DM_DISCOVER_ACTIVE, "BTA_DM_DISCOVER_ACTIVE"), - }; - for (const auto& state : states) { - ASSERT_STREQ(state.second.c_str(), bta_dm_state_text(state.first).c_str()); - } - auto unknown = - base::StringPrintf("UNKNOWN[%d]", std::numeric_limits<int>::max()); - ASSERT_STREQ(unknown.c_str(), - bta_dm_state_text( - static_cast<tBTA_DM_STATE>(std::numeric_limits<int>::max())) - .c_str()); -} - TEST_F(BtaDmTest, bta_dm_remname_cback__typical) { tBTA_DM_SEARCH_CB& search_cb = bluetooth::legacy::testing::bta_dm_disc_search_cb(); @@ -370,16 +330,10 @@ TEST_F(BtaDmTest, bta_dm_remname_cback__typical) { }; bd_name_from_char_pointer(name.remote_bd_name, kRemoteName); - mock_btm_client_interface.security.BTM_SecDeleteRmtNameNotifyCallback = - [](tBTM_RMT_NAME_CALLBACK*) -> bool { - inc_func_call_count("BTM_SecDeleteRmtNameNotifyCallback"); - return true; - }; bluetooth::legacy::testing::bta_dm_remname_cback(&name); sync_main_handler(); - ASSERT_EQ(1, get_func_call_count("BTM_SecDeleteRmtNameNotifyCallback")); ASSERT_TRUE( bluetooth::legacy::testing::bta_dm_disc_search_cb().name_discover_done); } @@ -388,7 +342,6 @@ TEST_F(BtaDmTest, bta_dm_remname_cback__wrong_address) { tBTA_DM_SEARCH_CB& search_cb = bluetooth::legacy::testing::bta_dm_disc_search_cb(); search_cb.p_device_search_cback = nullptr; - search_cb.service_search_cbacks = {}; search_cb.peer_bdaddr = kRawAddress; search_cb.name_discover_done = false; @@ -400,16 +353,9 @@ TEST_F(BtaDmTest, bta_dm_remname_cback__wrong_address) { }; bd_name_from_char_pointer(name.remote_bd_name, kRemoteName); - mock_btm_client_interface.security.BTM_SecDeleteRmtNameNotifyCallback = - [](tBTM_RMT_NAME_CALLBACK*) -> bool { - inc_func_call_count("BTM_SecDeleteRmtNameNotifyCallback"); - return true; - }; bluetooth::legacy::testing::bta_dm_remname_cback(&name); sync_main_handler(); - - ASSERT_EQ(0, get_func_call_count("BTM_SecDeleteRmtNameNotifyCallback")); } TEST_F(BtaDmTest, bta_dm_remname_cback__HCI_ERR_CONNECTION_EXISTS) { @@ -426,45 +372,17 @@ TEST_F(BtaDmTest, bta_dm_remname_cback__HCI_ERR_CONNECTION_EXISTS) { }; bd_name_from_char_pointer(name.remote_bd_name, kRemoteName); - mock_btm_client_interface.security.BTM_SecDeleteRmtNameNotifyCallback = - [](tBTM_RMT_NAME_CALLBACK*) -> bool { - inc_func_call_count("BTM_SecDeleteRmtNameNotifyCallback"); - return true; - }; bluetooth::legacy::testing::bta_dm_remname_cback(&name); sync_main_handler(); - ASSERT_EQ(1, get_func_call_count("BTM_SecDeleteRmtNameNotifyCallback")); ASSERT_TRUE( bluetooth::legacy::testing::bta_dm_disc_search_cb().name_discover_done); } -TEST_F(BtaDmTest, bta_dm_determine_discovery_transport__BT_TRANSPORT_BR_EDR) { - tBTA_DM_SEARCH_CB& search_cb = - bluetooth::legacy::testing::bta_dm_disc_search_cb(); - search_cb.transport = BT_TRANSPORT_BR_EDR; - - ASSERT_EQ(BT_TRANSPORT_BR_EDR, - bluetooth::legacy::testing::bta_dm_determine_discovery_transport( - kRawAddress)); -} - -TEST_F(BtaDmTest, bta_dm_determine_discovery_transport__BT_TRANSPORT_LE) { - tBTA_DM_SEARCH_CB& search_cb = - bluetooth::legacy::testing::bta_dm_disc_search_cb(); - search_cb.transport = BT_TRANSPORT_LE; - - ASSERT_EQ(BT_TRANSPORT_LE, - bluetooth::legacy::testing::bta_dm_determine_discovery_transport( - kRawAddress)); -} - -TEST_F(BtaDmTest, - bta_dm_determine_discovery_transport__BT_TRANSPORT_AUTO__BR_EDR) { +TEST_F(BtaDmTest, bta_dm_determine_discovery_transport__BR_EDR) { tBTA_DM_SEARCH_CB& search_cb = bluetooth::legacy::testing::bta_dm_disc_search_cb(); - search_cb.transport = BT_TRANSPORT_AUTO; mock_btm_client_interface.peer.BTM_ReadDevInfo = [](const RawAddress& remote_bda, tBT_DEVICE_TYPE* p_dev_type, @@ -478,11 +396,9 @@ TEST_F(BtaDmTest, kRawAddress)); } -TEST_F(BtaDmTest, - bta_dm_determine_discovery_transport__BT_TRANSPORT_AUTO__BLE__PUBLIC) { +TEST_F(BtaDmTest, bta_dm_determine_discovery_transport__BLE__PUBLIC) { tBTA_DM_SEARCH_CB& search_cb = bluetooth::legacy::testing::bta_dm_disc_search_cb(); - search_cb.transport = BT_TRANSPORT_AUTO; mock_btm_client_interface.peer.BTM_ReadDevInfo = [](const RawAddress& remote_bda, tBT_DEVICE_TYPE* p_dev_type, @@ -496,11 +412,9 @@ TEST_F(BtaDmTest, kRawAddress)); } -TEST_F(BtaDmTest, - bta_dm_determine_discovery_transport__BT_TRANSPORT_AUTO__DUMO) { +TEST_F(BtaDmTest, bta_dm_determine_discovery_transport__DUMO) { tBTA_DM_SEARCH_CB& search_cb = bluetooth::legacy::testing::bta_dm_disc_search_cb(); - search_cb.transport = BT_TRANSPORT_AUTO; mock_btm_client_interface.peer.BTM_ReadDevInfo = [](const RawAddress& remote_bda, tBT_DEVICE_TYPE* p_dev_type, diff --git a/system/bta/test/bta_sdp_test.cc b/system/bta/test/bta_sdp_test.cc index 6da30a0e6e..efee90e3c0 100644 --- a/system/bta/test/bta_sdp_test.cc +++ b/system/bta/test/bta_sdp_test.cc @@ -37,8 +37,8 @@ namespace bluetooth { namespace legacy { namespace testing { -tBTA_DM_SEARCH_CB& bta_dm_disc_search_cb(); -void bta_dm_sdp_result(tBTA_DM_SDP_RESULT& sdp_event); +tBTA_DM_SERVICE_DISCOVERY_CB& bta_dm_discovery_cb(); +void bta_dm_sdp_result(tSDP_STATUS sdp_status); } // namespace testing } // namespace legacy @@ -69,14 +69,11 @@ class BtaSdpRegisteredTest : public BtaSdpTest { TEST_F(BtaSdpTest, nop) {} TEST_F(BtaSdpRegisteredTest, bta_dm_sdp_result_SDP_SUCCESS) { - tBTA_DM_SEARCH_CB& search_cb = - bluetooth::legacy::testing::bta_dm_disc_search_cb(); - search_cb.service_index = BTA_MAX_SERVICE_ID; + tBTA_DM_SERVICE_DISCOVERY_CB& discovery_cb = + bluetooth::legacy::testing::bta_dm_discovery_cb(); + discovery_cb.service_index = BTA_MAX_SERVICE_ID; mock_btm_client_interface.security.BTM_SecReadDevName = [](const RawAddress& bd_addr) -> const char* { return kName; }; - mock_btm_client_interface.security.BTM_SecDeleteRmtNameNotifyCallback = - [](tBTM_RMT_NAME_CALLBACK*) -> bool { return true; }; - tBTA_DM_SDP_RESULT result{.sdp_result = SDP_SUCCESS}; - bluetooth::legacy::testing::bta_dm_sdp_result(result); + bluetooth::legacy::testing::bta_dm_sdp_result(SDP_SUCCESS); } diff --git a/system/bta/vc/device.cc b/system/bta/vc/device.cc index d47eb5a91b..8294dfc8f3 100644 --- a/system/bta/vc/device.cc +++ b/system/bta/vc/device.cc @@ -71,7 +71,7 @@ uint16_t VolumeControlDevice::find_ccc_handle(uint16_t chrc_handle) { const gatt::Characteristic* p_char = BTA_GATTC_GetCharacteristic(connection_id, chrc_handle); if (!p_char) { - log::warn("no such handle={}", loghex(chrc_handle)); + log::warn("no such handle=0x{:x}", chrc_handle); return 0; } @@ -157,9 +157,9 @@ void VolumeControlDevice::set_volume_offset_control_service_handles( GATT_HANDLE_IS_VALID(offset.audio_descr_handle) /* audio_descr_ccc_handle is optional */) { audio_offsets.Add(offset); - log::info("Offset added id={}", loghex(offset.id)); + log::info("Offset added id=0x{:x}", offset.id); } else { - log::warn("Ignoring offset handle={}", loghex(service.handle)); + log::warn("Ignoring offset handle=0x{:x}", service.handle); } } @@ -176,7 +176,7 @@ bool VolumeControlDevice::UpdateHandles(void) { for (auto const& service : *services) { if (service.uuid == kVolumeControlUuid) { - log::info("Found VCS, handle={}", loghex(service.handle)); + log::info("Found VCS, handle=0x{:x}", service.handle); vcs_found = set_volume_control_service_handles(service); if (!vcs_found) break; @@ -187,7 +187,7 @@ bool VolumeControlDevice::UpdateHandles(void) { if (service == nullptr) continue; if (included.uuid == kVolumeOffsetUuid) { - log::info("Found VOCS, handle={}", loghex(service->handle)); + log::info("Found VOCS, handle=0x{:x}", service->handle); set_volume_offset_control_service_handles(*service); } else { @@ -235,7 +235,7 @@ bool VolumeControlDevice::subscribe_for_notifications(tGATT_IF gatt_if, tGATT_STATUS status = BTA_GATTC_RegisterForNotifications(gatt_if, address, handle); if (status != GATT_SUCCESS) { - log::error("failed, status={}", loghex(+status)); + log::error("failed, status=0x{:x}", status); return false; } diff --git a/system/bta/vc/types.h b/system/bta/vc/types.h index 6a2cd753ad..2096b45e1d 100644 --- a/system/bta/vc/types.h +++ b/system/bta/vc/types.h @@ -89,6 +89,12 @@ struct VolumeOperation { }; ~VolumeOperation() { + if (operation_timeout_ == nullptr) { + log::warn("operation_timeout_ should not be null, id {}, device cnt {}", + operation_id_, devices_.size()); + return; + } + if (alarm_is_scheduled(operation_timeout_)) alarm_cancel(operation_timeout_); diff --git a/system/bta/vc/vc.cc b/system/bta/vc/vc.cc index c01f679d9b..c60998d580 100644 --- a/system/bta/vc/vc.cc +++ b/system/bta/vc/vc.cc @@ -272,8 +272,8 @@ class VolumeControlImpl : public VolumeControl { VolumeControlDevice* device = volume_control_devices_.FindByConnId(connection_id); if (!device) { - log::error("Skipping unknown device, connection_id={}", - loghex(connection_id)); + log::error("Skipping unknown device, connection_id=0x{:x}", + connection_id); return; } @@ -309,7 +309,7 @@ class VolumeControlImpl : public VolumeControl { bool is_notification) { VolumeControlDevice* device = volume_control_devices_.FindByConnId(conn_id); if (!device) { - log::info("unknown conn_id={}", loghex(conn_id)); + log::info("unknown conn_id=0x{:x}", conn_id); return; } @@ -346,7 +346,7 @@ class VolumeControlImpl : public VolumeControl { } else if (handle == offset->audio_descr_handle) { OnOffsetOutputDescChanged(device, offset, len, value); } else { - log::error("unknown offset handle={}", loghex(handle)); + log::error("unknown offset handle=0x{:x}", handle); return; } @@ -354,12 +354,12 @@ class VolumeControlImpl : public VolumeControl { return; } - log::error("unknown handle={}", loghex(handle)); + log::error("unknown handle=0x{:x}", handle); } void OnNotificationEvent(uint16_t conn_id, uint16_t handle, uint16_t len, uint8_t* value) { - log::info("handle={}", loghex(handle)); + log::info("handle=0x{:x}", handle); OnCharacteristicValueChanged(conn_id, GATT_SUCCESS, handle, len, value, nullptr, true); } @@ -433,7 +433,7 @@ class VolumeControlImpl : public VolumeControl { uint16_t len, uint8_t* value, bool is_notification) { if (len != 3) { - log::info("malformed len={}", loghex(len)); + log::info("malformed len=0x{:x}", len); return; } @@ -450,8 +450,8 @@ class VolumeControlImpl : public VolumeControl { bool is_mute_change = (device->mute != mute); device->mute = mute; - log::info("volume {} mute {} change_counter {}", loghex(device->volume), - loghex(device->mute), loghex(device->change_counter)); + log::info("volume 0x{:x} mute 0x{:x} change_counter 0x{:x}", device->volume, + device->mute, device->change_counter); if (!device->IsReady()) { log::info("Device: {} is not ready yet.", device->address); @@ -506,14 +506,14 @@ class VolumeControlImpl : public VolumeControl { uint8_t* value) { device->flags = *value; - log::info("flags {}", loghex(device->flags)); + log::info("flags 0x{:x}", device->flags); } void OnExtAudioOutStateChanged(VolumeControlDevice* device, VolumeOffset* offset, uint16_t len, uint8_t* value) { if (len != 3) { - log::info("malformed len={}", loghex(len)); + log::info("malformed len=0x{:x}", len); return; } @@ -522,8 +522,8 @@ class VolumeControlImpl : public VolumeControl { STREAM_TO_UINT8(offset->change_counter, pp); log::info("{}", base::HexEncode(value, len)); - log::info("id: {} offset: {} counter: {}", loghex(offset->id), - loghex(offset->offset), loghex(offset->change_counter)); + log::info("id: 0x{:x} offset: 0x{:x} counter: 0x{:x}", offset->id, + offset->offset, offset->change_counter); if (!device->IsReady()) { log::info("Device: {} is not ready yet.", device->address); @@ -538,7 +538,7 @@ class VolumeControlImpl : public VolumeControl { VolumeOffset* offset, uint16_t len, uint8_t* value) { if (len != 4) { - log::info("malformed len={}", loghex(len)); + log::info("malformed len=0x{:x}", len); return; } @@ -546,7 +546,7 @@ class VolumeControlImpl : public VolumeControl { STREAM_TO_UINT32(offset->location, pp); log::info("{}", base::HexEncode(value, len)); - log::info("id {}location {}", loghex(offset->id), loghex(offset->location)); + log::info("id 0x{:x}location 0x{:x}", offset->id, offset->location); if (!device->IsReady()) { log::info("Device: {} is not ready yet.", device->address); @@ -562,13 +562,13 @@ class VolumeControlImpl : public VolumeControl { VolumeControlDevice* device = volume_control_devices_.FindByConnId(connection_id); if (!device) { - log::error("Skipping unknown device disconnect, connection_id={}", - loghex(connection_id)); + log::error("Skipping unknown device disconnect, connection_id=0x{:x}", + connection_id); return; } - log::info("Offset Control Point write response handle{} status: {}", - loghex(handle), loghex((int)(status))); + log::info("Offset Control Point write response handle0x{:x} status: 0x{:x}", + handle, (int)(status)); /* TODO Design callback API to notify about changes */ } @@ -596,7 +596,7 @@ class VolumeControlImpl : public VolumeControl { VolumeControlDevice* device = volume_control_devices_.FindByConnId(connection_id); if (!device) { - log::info("unknown connection_id={}", loghex(connection_id)); + log::info("unknown connection_id=0x{:x}", connection_id); BtaGattQueue::Clean(connection_id); return; } @@ -668,19 +668,21 @@ class VolumeControlImpl : public VolumeControl { VolumeControlDevice* device = volume_control_devices_.FindByConnId(connection_id); if (!device) { - log::error("Skipping unknown device disconnect, connection_id={}", - loghex(connection_id)); + log::error("Skipping unknown device disconnect, connection_id=0x{:x}", + connection_id); return; } if (!device->IsConnected()) { log::error( "Skipping disconnect of the already disconnected device, " - "connection_id={}", - loghex(connection_id)); + "connection_id=0x{:x}", + connection_id); return; } + log::info("{}", remote_bda); + bool notify = device->IsReady() || device->connecting_actively; device_cleanup_helper(device, notify); @@ -772,13 +774,13 @@ class VolumeControlImpl : public VolumeControl { VolumeControlDevice* device = volume_control_devices_.FindByConnId(connection_id); if (!device) { - log::error("Skipping unknown device disconnect, connection_id={}", - loghex(connection_id)); + log::error("Skipping unknown device disconnect, connection_id=0x{:x}", + connection_id); return; } - log::info("Write response handle: {} status: {}", loghex(handle), - loghex((int)(status))); + log::info("Write response handle: 0x{:x} status: 0x{:x}", handle, + (int)(status)); if (status == GATT_SUCCESS) return; @@ -851,8 +853,7 @@ class VolumeControlImpl : public VolumeControl { log::debug( "num of devices: {}, group_id: {}, is_autonomous: {} opcode: {}, arg " "size: {}", - devices.size(), group_id, is_autonomous ? "true" : "false", opcode, - arguments.size()); + devices.size(), group_id, is_autonomous, opcode, arguments.size()); if (std::find_if(ongoing_operations_.begin(), ongoing_operations_.end(), [opcode, &devices, &arguments](const VolumeOperation& op) { @@ -887,8 +888,7 @@ class VolumeControlImpl : public VolumeControl { VolumeControlDevice* dev = volume_control_devices_.FindByAddress( std::get<RawAddress>(addr_or_group_id)); if (dev != nullptr) { - log::debug("Address: {}: isReady: {}", dev->address, - dev->IsReady() ? "true" : "false"); + log::debug("Address: {}: isReady: {}", dev->address, dev->IsReady()); if (dev->IsReady() && (dev->mute != mute)) { std::vector<RawAddress> devices = {dev->address}; PrepareVolumeControlOperation( @@ -965,8 +965,7 @@ class VolumeControlImpl : public VolumeControl { VolumeControlDevice* dev = volume_control_devices_.FindByAddress( std::get<RawAddress>(addr_or_group_id)); if (dev != nullptr) { - log::debug("Address: {}: isReady: {}", dev->address, - dev->IsReady() ? "true" : "false"); + log::debug("Address: {}: isReady: {}", dev->address, dev->IsReady()); if (dev->IsReady() && (dev->volume != volume)) { std::vector<RawAddress> devices = {dev->address}; RemovePendingVolumeControlOperations( @@ -1176,7 +1175,7 @@ class VolumeControlImpl : public VolumeControl { void ext_audio_out_control_point_helper(const RawAddress& address, uint8_t ext_output_id, uint8_t opcode, const std::vector<uint8_t>* arg) { - log::info("{} id={} op={}", address, loghex(ext_output_id), loghex(opcode)); + log::info("{} id=0x{:x} op=0x{:x}", address, ext_output_id, opcode); VolumeControlDevice* device = volume_control_devices_.FindByAddress(address); if (!device) { diff --git a/system/btif/Android.bp b/system/btif/Android.bp index 6873b6b55a..76f528bd58 100644 --- a/system/btif/Android.bp +++ b/system/btif/Android.bp @@ -636,9 +636,6 @@ cc_test { "libprotobuf-cpp-lite", "libstatslog_bt", ], - cflags: [ - "-Wno-unused-parameter", - ], target: { android: { static_libs: [ @@ -759,9 +756,6 @@ cc_test { "libprotobuf-cpp-lite", "libstatslog_bt", ], - cflags: [ - "-Wno-unused-parameter", - ], target: { android: { static_libs: [ diff --git a/system/btif/avrcp/avrcp_service.cc b/system/btif/avrcp/avrcp_service.cc index e5d575a953..98a4a2d4b9 100644 --- a/system/btif/avrcp/avrcp_service.cc +++ b/system/btif/avrcp/avrcp_service.cc @@ -28,6 +28,8 @@ #include "btif_av.h" #include "btif_common.h" #include "device.h" +#include "osi/include/osi.h" +#include "stack/include/a2dp_api.h" #include "stack/include/bt_hdr.h" #include "stack/include/bt_uuid16.h" #include "stack/include/main_thread.h" @@ -53,6 +55,28 @@ class A2dpInterfaceImpl : public A2dpInterface { bool is_peer_in_silence_mode(const RawAddress& peer_address) override { return btif_av_is_peer_silenced(peer_address); } + + void connect_audio_sink_delayed(uint8_t handle, + const RawAddress& peer_address) override { + btif_av_connect_sink_delayed(handle, peer_address); + } + + uint16_t find_audio_sink_service(const RawAddress& peer_address, + tA2DP_FIND_CBACK p_cback) override { + uint16_t attr_list[] = {ATTR_ID_SERVICE_CLASS_ID_LIST, + ATTR_ID_BT_PROFILE_DESC_LIST, + ATTR_ID_SUPPORTED_FEATURES}; + + tA2DP_SDP_DB_PARAMS db_params = { + .db_len = BT_DEFAULT_BUFFER_SIZE, + .num_attr = ARRAY_SIZE(attr_list), + .p_attrs = attr_list, + }; + + return A2DP_FindService(UUID_SERVCLASS_AUDIO_SINK, peer_address, &db_params, + p_cback); + } + } a2dp_interface_; class AvrcpInterfaceImpl : public AvrcpInterface { @@ -638,6 +662,27 @@ bool AvrcpService::ServiceInterfaceImpl::DisconnectDevice( return true; } +bool AvrcpService::IsDeviceConnected(const RawAddress& bdaddr) { + if (instance_ == nullptr) { + log::warn("AVRCP Target Service not started"); + return false; + } + + auto handler = instance_->connection_handler_; + if (handler == nullptr) { + log::warn("AVRCP connection handler is null"); + return false; + } + + for (const auto& device : handler->GetListOfDevices()) { + if (bdaddr == device->GetAddress()) { + return true; + } + } + + return false; +} + void AvrcpService::ServiceInterfaceImpl::SetBipClientStatus( const RawAddress& bdaddr, bool connected) { std::lock_guard<std::mutex> lock(service_interface_lock_); diff --git a/system/btif/avrcp/avrcp_service.h b/system/btif/avrcp/avrcp_service.h index 7bd9081e00..bb8fcd5f5b 100644 --- a/system/btif/avrcp/avrcp_service.h +++ b/system/btif/avrcp/avrcp_service.h @@ -76,6 +76,8 @@ class AvrcpService : public MediaCallbacks { void SendPlayerSettingsChanged(std::vector<PlayerAttribute> attributes, std::vector<uint8_t> values) override; + bool IsDeviceConnected(const RawAddress& bdaddr); + /** when a2dp connected, btif will start register vol changed, so we need a * interface for it. */ void RegisterVolChanged(const RawAddress& bdaddr); diff --git a/system/btif/co/bta_av_co.cc b/system/btif/co/bta_av_co.cc index 9ac30cfdfb..f9a1cb2390 100644 --- a/system/btif/co/bta_av_co.cc +++ b/system/btif/co/bta_av_co.cc @@ -321,8 +321,7 @@ tA2DP_STATUS BtaAvCo::ProcessSourceGetConfig( // If acceptor -> reconfig otherwise reply for configuration *p_sep_info_idx = p_sink->sep_info_idx; log::verbose("peer {} acceptor:{} reconfig_needed:{}", p_peer->addr, - (p_peer->acceptor) ? "true" : "false", - (p_peer->reconfig_needed) ? "true" : "false"); + p_peer->acceptor, p_peer->reconfig_needed); if (p_peer->acceptor) { if (p_peer->reconfig_needed) { log::verbose("call BTA_AvReconfig(0x{:x}) for peer {}", bta_av_handle, @@ -433,8 +432,7 @@ tA2DP_STATUS BtaAvCo::ProcessSinkGetConfig(tBTA_AV_HNDL bta_av_handle, // If acceptor -> reconfig otherwise reply for configuration *p_sep_info_idx = p_source->sep_info_idx; log::verbose("peer {} acceptor:{} reconfig_needed:{}", p_peer->addr, - (p_peer->acceptor) ? "true" : "false", - (p_peer->reconfig_needed) ? "true" : "false"); + p_peer->acceptor, p_peer->reconfig_needed); if (p_peer->acceptor) { if (p_peer->reconfig_needed) { log::verbose("call BTA_AvReconfig(0x{:x}) for peer {}", bta_av_handle, @@ -638,7 +636,7 @@ void BtaAvCo::ProcessStart(tBTA_AV_HNDL bta_av_handle, A2DP_UsesRtpHeader(p_peer->ContentProtectActive(), p_codec_info); log::verbose("bta_av_handle: 0x{:x} add_rtp_header: {}", bta_av_handle, - add_rtp_header ? "true" : "false"); + add_rtp_header); *p_no_rtp_header = !add_rtp_header; } @@ -715,15 +713,15 @@ void BtaAvCo::ProcessAudioDelay(tBTA_AV_HNDL bta_av_handle, void BtaAvCo::UpdateMtu(tBTA_AV_HNDL bta_av_handle, const RawAddress& peer_address, uint16_t mtu) { - log::info("peer {} bta_av_handle: {} mtu: {}", peer_address, - loghex(bta_av_handle), mtu); + log::info("peer {} bta_av_handle: 0x{:x} mtu: {}", peer_address, + bta_av_handle, mtu); // Find the peer BtaAvCoPeer* p_peer = peer_cache_->FindPeerAndUpdate(bta_av_handle, peer_address); if (p_peer == nullptr) { - log::error("could not find peer entry for bta_av_handle {} peer {}", - loghex(bta_av_handle), peer_address); + log::error("could not find peer entry for bta_av_handle 0x{:x} peer {}", + bta_av_handle, peer_address); return; } p_peer->mtu = mtu; @@ -893,7 +891,7 @@ bool BtaAvCo::SetCodecUserConfig( } p_peer->acceptor = false; - log::verbose("call BTA_AvReconfig({})", loghex(p_peer->BtaAvHandle())); + log::verbose("call BTA_AvReconfig(0x{:x})", p_peer->BtaAvHandle()); BTA_AvReconfig(p_peer->BtaAvHandle(), true, p_sink->sep_info_idx, p_peer->codec_config, num_protect, bta_av_co_cp_scmst); *p_restart_output = true; @@ -977,7 +975,7 @@ bool BtaAvCo::SetCodecAudioConfig( p_sink->protect_info, AVDT_TSEP_SRC); p_peer->acceptor = false; - log::verbose("call BTA_AvReconfig({})", loghex(p_peer->BtaAvHandle())); + log::verbose("call BTA_AvReconfig(0x{:x})", p_peer->BtaAvHandle()); BTA_AvReconfig(p_peer->BtaAvHandle(), true, p_sink->sep_info_idx, p_peer->codec_config, num_protect, bta_av_co_cp_scmst); } diff --git a/system/btif/co/bta_hh_co.cc b/system/btif/co/bta_hh_co.cc index 6c93ef7e6b..b7d7bbcea7 100644 --- a/system/btif/co/bta_hh_co.cc +++ b/system/btif/co/bta_hh_co.cc @@ -24,7 +24,6 @@ #include <poll.h> #include <pthread.h> #include <stdint.h> -#include <stdio.h> #include <string.h> #include <unistd.h> diff --git a/system/btif/include/btif_av.h b/system/btif/include/btif_av.h index 44b5a237d2..d1aa353942 100644 --- a/system/btif/include/btif_av.h +++ b/system/btif/include/btif_av.h @@ -277,6 +277,14 @@ void btif_av_set_dynamic_audio_buffer_size(uint8_t dynamic_audio_buffer_size); void btif_av_set_low_latency(bool is_low_latency); /** + * Initiate an AV connection after 3s timeout to peer audio sink + * @param handle bta handle + * @param peer_addr peer address + */ +void btif_av_connect_sink_delayed(uint8_t handle, + const RawAddress& peer_address); + +/** * Check whether A2DP Source is enabled. */ extern bool btif_av_is_source_enabled(void); diff --git a/system/btif/include/btif_common.h b/system/btif/include/btif_common.h index 3a357ffdf4..055ded0fa4 100644 --- a/system/btif/include/btif_common.h +++ b/system/btif/include/btif_common.h @@ -154,8 +154,7 @@ void invoke_device_found_cb(int num_properties, bt_property_t* properties); void invoke_discovery_state_changed_cb(bt_discovery_state_t state); void invoke_pin_request_cb(RawAddress bd_addr, bt_bdname_t bd_name, uint32_t cod, bool min_16_digit); -void invoke_ssp_request_cb(RawAddress bd_addr, bt_bdname_t bd_name, - uint32_t cod, bt_ssp_variant_t pairing_variant, +void invoke_ssp_request_cb(RawAddress bd_addr, bt_ssp_variant_t pairing_variant, uint32_t pass_key); void invoke_oob_data_request_cb(tBT_TRANSPORT t, bool valid, Octet16 c, Octet16 r, RawAddress raw_address, diff --git a/system/btif/include/core_callbacks.h b/system/btif/include/core_callbacks.h index 4bf555c268..5dab0f5263 100644 --- a/system/btif/include/core_callbacks.h +++ b/system/btif/include/core_callbacks.h @@ -39,8 +39,8 @@ struct EventCallbacks { void (*invoke_discovery_state_changed_cb)(bt_discovery_state_t state); void (*invoke_pin_request_cb)(RawAddress bd_addr, bt_bdname_t bd_name, uint32_t cod, bool min_16_digit); - void (*invoke_ssp_request_cb)(RawAddress bd_addr, bt_bdname_t bd_name, - uint32_t cod, bt_ssp_variant_t pairing_variant, + void (*invoke_ssp_request_cb)(RawAddress bd_addr, + bt_ssp_variant_t pairing_variant, uint32_t pass_key); void (*invoke_oob_data_request_cb)(tBT_TRANSPORT t, bool valid, Octet16 c, Octet16 r, RawAddress raw_address, diff --git a/system/btif/include/mock_core_callbacks.h b/system/btif/include/mock_core_callbacks.h index b589e3f49e..900bf5aa1a 100644 --- a/system/btif/include/mock_core_callbacks.h +++ b/system/btif/include/mock_core_callbacks.h @@ -44,7 +44,6 @@ EventCallbacks mock_event_callbacks = { bt_bdname_t /* bd_name */, uint32_t /* cod */, bool /* min_16_digit */) {}, .invoke_ssp_request_cb = [](RawAddress /* bd_addr */, - bt_bdname_t /* bd_name */, uint32_t /* cod */, bt_ssp_variant_t /* pairing_variant */, uint32_t /* pass_key */) {}, .invoke_oob_data_request_cb = [](tBT_TRANSPORT /* t */, bool /* valid */, @@ -73,6 +72,7 @@ EventCallbacks mock_event_callbacks = { int /* snr */, int /* retransmission_count */, int /* packets_not_receive_count */, int /* negative_acknowledgement_count */) {}, + .invoke_key_missing_cb = [](RawAddress /* bd_addr */) {}, }; // This interface lets us query for configuration properties of the stack that diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc index 4c197af89f..b68ba21bac 100644 --- a/system/btif/src/bluetooth.cc +++ b/system/btif/src/bluetooth.cc @@ -45,7 +45,6 @@ #include <hardware/bt_sdp.h> #include <hardware/bt_sock.h> #include <hardware/bt_vc.h> -#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> @@ -675,11 +674,7 @@ static int get_connection_state(const RawAddress* bd_addr) { if (bd_addr == nullptr) return 0; - if (IS_FLAG_ENABLED(api_get_connection_state_sync_on_main)) { - return btif_dm_get_connection_state_sync(*bd_addr); - } else { - return btif_dm_get_connection_state(*bd_addr); - } + return btif_dm_get_connection_state(*bd_addr); } static int pin_reply(const RawAddress* bd_addr, uint8_t accept, uint8_t pin_len, @@ -1340,17 +1335,16 @@ void invoke_pin_request_cb(RawAddress bd_addr, bt_bdname_t bd_name, bd_addr, bd_name, cod, min_16_digit)); } -void invoke_ssp_request_cb(RawAddress bd_addr, bt_bdname_t bd_name, - uint32_t cod, bt_ssp_variant_t pairing_variant, +void invoke_ssp_request_cb(RawAddress bd_addr, bt_ssp_variant_t pairing_variant, uint32_t pass_key) { do_in_jni_thread(FROM_HERE, base::BindOnce( - [](RawAddress bd_addr, bt_bdname_t bd_name, uint32_t cod, - bt_ssp_variant_t pairing_variant, uint32_t pass_key) { + [](RawAddress bd_addr, bt_ssp_variant_t pairing_variant, + uint32_t pass_key) { HAL_CBACK(bt_hal_cbacks, ssp_request_cb, &bd_addr, - &bd_name, cod, pairing_variant, pass_key); + pairing_variant, pass_key); }, - bd_addr, bd_name, cod, pairing_variant, pass_key)); + bd_addr, pairing_variant, pass_key)); } void invoke_oob_data_request_cb(tBT_TRANSPORT t, bool valid, Octet16 c, diff --git a/system/btif/src/btif_a2dp_sink.cc b/system/btif/src/btif_a2dp_sink.cc index 0311a29cfc..94cdd796a2 100644 --- a/system/btif/src/btif_a2dp_sink.cc +++ b/system/btif/src/btif_a2dp_sink.cc @@ -583,7 +583,7 @@ static void btif_a2dp_sink_avk_handle_timer() { /* when true media task discards any rx frames */ void btif_a2dp_sink_set_rx_flush(bool enable) { - log::info("enable={}", (enable) ? "true" : "false"); + log::info("enable={}", enable); LockGuard lock(g_mutex); btif_a2dp_sink_cb.rx_flush = enable; diff --git a/system/btif/src/btif_a2dp_source.cc b/system/btif/src/btif_a2dp_source.cc index 7195342010..a055dfe668 100644 --- a/system/btif/src/btif_a2dp_source.cc +++ b/system/btif/src/btif_a2dp_source.cc @@ -673,7 +673,7 @@ static void btif_a2dp_source_encoder_user_config_update_event( log::info( "peer_address={} state={} codec_preference=[{}] restart_output={}", peer_address, btif_a2dp_source_cb.StateStr(), - codec_user_config.ToString(), (restart_output ? "true" : "false")); + codec_user_config.ToString(), restart_output); break; } } @@ -730,8 +730,7 @@ void btif_a2dp_source_on_stopped(tBTA_AV_SUSPEND* p_av_suspend) { // than suspend if (p_av_suspend != nullptr && p_av_suspend->status != BTA_AV_SUCCESS) { log::error("A2DP stop failed: status={}, initiator={}", - p_av_suspend->status, - (p_av_suspend->initiator ? "true" : "false")); + p_av_suspend->status, p_av_suspend->initiator); if (p_av_suspend->initiator) { if (bluetooth::audio::a2dp::is_hal_enabled()) { bluetooth::audio::a2dp::ack_stream_suspended(A2DP_CTRL_ACK_FAILURE); @@ -768,8 +767,7 @@ void btif_a2dp_source_on_suspended(tBTA_AV_SUSPEND* p_av_suspend) { // check for status failures if (p_av_suspend->status != BTA_AV_SUCCESS) { log::warn("A2DP suspend failed: status={}, initiator={}", - p_av_suspend->status, - (p_av_suspend->initiator ? "true" : "false")); + p_av_suspend->status, p_av_suspend->initiator); if (p_av_suspend->initiator) { if (bluetooth::audio::a2dp::is_hal_enabled()) { bluetooth::audio::a2dp::ack_stream_suspended(A2DP_CTRL_ACK_FAILURE); @@ -793,14 +791,12 @@ void btif_a2dp_source_on_suspended(tBTA_AV_SUSPEND* p_av_suspend) { /* when true media task discards any tx frames */ void btif_a2dp_source_set_tx_flush(bool enable) { - log::info("enable={} state={}", (enable) ? "true" : "false", - btif_a2dp_source_cb.StateStr()); + log::info("enable={} state={}", enable, btif_a2dp_source_cb.StateStr()); btif_a2dp_source_cb.tx_flush = enable; } static void btif_a2dp_source_audio_tx_start_event(void) { - log::info("streaming {} state={}", - btif_a2dp_source_is_streaming() ? "true" : "false", + log::info("streaming {} state={}", btif_a2dp_source_is_streaming(), btif_a2dp_source_cb.StateStr()); if (btif_av_is_a2dp_offload_running()) return; @@ -843,8 +839,7 @@ static void btif_a2dp_source_audio_tx_start_event(void) { } static void btif_a2dp_source_audio_tx_stop_event(void) { - log::info("streaming {} state={}", - btif_a2dp_source_is_streaming() ? "true" : "false", + log::info("streaming {} state={}", btif_a2dp_source_is_streaming(), btif_a2dp_source_cb.StateStr()); if (btif_av_is_a2dp_offload_running()) return; diff --git a/system/btif/src/btif_av.cc b/system/btif/src/btif_av.cc index 5de6116bf4..684ac263a5 100644 --- a/system/btif/src/btif_av.cc +++ b/system/btif/src/btif_av.cc @@ -35,6 +35,7 @@ #include <vector> #include "audio_hal_interface/a2dp_encoding.h" +#include "btif/avrcp/avrcp_service.h" #include "btif/include/btif_a2dp.h" #include "btif/include/btif_a2dp_control.h" #include "btif/include/btif_a2dp_sink.h" @@ -2392,7 +2393,7 @@ bool BtifAvStateMachine::StateOpened::ProcessEvent(uint32_t event, const btif_av_start_stream_req_t* p_start_steam_req = static_cast<const btif_av_start_stream_req_t*>(p_data); log::info("Stream use_latency_mode={}", - p_start_steam_req->use_latency_mode ? "true" : "false"); + p_start_steam_req->use_latency_mode); peer_.SetUseLatencyMode(p_start_steam_req->use_latency_mode); } @@ -2529,8 +2530,8 @@ bool BtifAvStateMachine::StateOpened::ProcessEvent(uint32_t event, std::move(peer_ready_promise)); } if (peer_.CheckFlags(BtifAvPeer::kFlagPendingStart)) { - log::info("Peer {} : Reconfig done - calling BTA_AvStart({})", - peer_.PeerAddress(), loghex(peer_.BtaHandle())); + log::info("Peer {} : Reconfig done - calling BTA_AvStart(0x{:x})", + peer_.PeerAddress(), peer_.BtaHandle()); BTA_AvStart(peer_.BtaHandle(), peer_.UseLatencyMode()); } break; @@ -2562,8 +2563,7 @@ bool BtifAvStateMachine::StateOpened::ProcessEvent(uint32_t event, static_cast<const btif_av_set_latency_req_t*>(p_data); log::info("Peer {} : event={} flags={} is_low_latency={}", peer_.PeerAddress(), BtifAvEvent::EventName(event), - peer_.FlagsToString(), - p_set_latency_req->is_low_latency ? "true" : "false"); + peer_.FlagsToString(), p_set_latency_req->is_low_latency); BTA_AvSetLatency(peer_.BtaHandle(), p_set_latency_req->is_low_latency); } break; @@ -2795,8 +2795,7 @@ bool BtifAvStateMachine::StateStarted::ProcessEvent(uint32_t event, static_cast<const btif_av_set_latency_req_t*>(p_data); log::info("Peer {} : event={} flags={} is_low_latency={}", peer_.PeerAddress(), BtifAvEvent::EventName(event), - peer_.FlagsToString(), - p_set_latency_req->is_low_latency ? "true" : "false"); + peer_.FlagsToString(), p_set_latency_req->is_low_latency); BTA_AvSetLatency(peer_.BtaHandle(), p_set_latency_req->is_low_latency); } break; @@ -2897,11 +2896,23 @@ bool BtifAvStateMachine::StateClosing::ProcessEvent(uint32_t event, */ static void btif_av_source_initiate_av_open_timer_timeout(void* data) { BtifAvPeer* peer = (BtifAvPeer*)data; + bool device_connected = false; + + if (IS_FLAG_ENABLED(avrcp_connect_a2dp_delayed) && is_new_avrcp_enabled()) { + // check if device is connected + if (bluetooth::avrcp::AvrcpService::Get() != nullptr) { + device_connected = + bluetooth::avrcp::AvrcpService::Get()->IsDeviceConnected( + peer->PeerAddress()); + } + } else { + device_connected = btif_rc_is_connected_peer(peer->PeerAddress()); + } log::verbose("Peer {}", peer->PeerAddress()); // Check if AVRCP is connected to the peer - if (!btif_rc_is_connected_peer(peer->PeerAddress())) { + if (!device_connected) { log::error("AVRCP peer {} is not connected", peer->PeerAddress()); return; } @@ -3592,8 +3603,7 @@ static bt_status_t connect_int(RawAddress* peer_address, uint16_t uuid) { static void set_source_silence_peer_int(const RawAddress& peer_address, bool silence) { - log::verbose("peer_address={}, silence={}", peer_address, - silence ? "true" : "false"); + log::verbose("peer_address={}, silence={}", peer_address, silence); if (!btif_av_source.SetSilencePeer(peer_address, silence)) { log::error("Error setting silence state to {}", peer_address); } @@ -3838,7 +3848,7 @@ void btif_av_stream_start_with_latency(bool use_latency_mode) { sizeof(start_stream_req)); log::info("peer_address={} event={} use_latency_mode={}", btif_av_source_active_peer(), btif_av_event.ToString(), - use_latency_mode ? "true" : "false"); + use_latency_mode); do_in_main_thread( FROM_HERE, base::BindOnce(&btif_av_handle_event, @@ -4282,7 +4292,7 @@ void btif_av_set_dynamic_audio_buffer_size(uint8_t dynamic_audio_buffer_size) { } void btif_av_set_low_latency(bool is_low_latency) { - log::info("is_low_latency: {}", is_low_latency ? "true" : "false"); + log::info("is_low_latency: {}", is_low_latency); btif_av_set_latency_req_t set_latency_req; set_latency_req.is_low_latency = is_low_latency; @@ -4364,3 +4374,13 @@ bool btif_av_peer_is_source(const RawAddress& peer_address) { return true; } + +void btif_av_connect_sink_delayed(uint8_t handle, + const RawAddress& peer_address) { + log::debug("Peer {} : handle: {}", ADDRESS_TO_LOGGABLE_CSTR(peer_address), + handle); + + if (btif_av_source.Enabled()) { + btif_av_source_dispatch_sm_event(peer_address, BTIF_AV_AVRCP_OPEN_EVT); + } +} diff --git a/system/btif/src/btif_bqr.cc b/system/btif/src/btif_bqr.cc index 7a22097f74..f7a141d6f4 100644 --- a/system/btif/src/btif_bqr.cc +++ b/system/btif/src/btif_bqr.cc @@ -19,7 +19,6 @@ #include <statslog_bt.h> #endif #include <bluetooth/log.h> -#include <stdio.h> #include <sys/stat.h> #include <cerrno> @@ -371,10 +370,9 @@ void EnableBtQualityReport(bool is_enable) { vendor_cap_supported_version = cmn_vsc_cb.version_supported; log::info( - "Event Mask: {}, Interval: {}, Multiple: {}, " + "Event Mask: 0x{:x}, Interval: {}, Multiple: {}, " "vendor_cap_supported_version: {}", - loghex(bqr_config.quality_event_mask), - bqr_config.minimum_report_interval_ms, + bqr_config.quality_event_mask, bqr_config.minimum_report_interval_ms, bqr_config.report_interval_multiple, vendor_cap_supported_version); ConfigureBqr(bqr_config); } @@ -385,8 +383,9 @@ void ConfigureBqr(const BqrConfiguration& bqr_config) { bqr_config.quality_event_mask > kQualityEventMaskAll || bqr_config.minimum_report_interval_ms > kMinReportIntervalMaxMs) { log::fatal( - "Invalid Parameter, Action: {}, Mask: {}, Interval: {} Multiple: {}", - bqr_config.report_action, loghex(bqr_config.quality_event_mask), + "Invalid Parameter, Action: {}, Mask: 0x{:x}, Interval: {} Multiple: " + "{}", + bqr_config.report_action, bqr_config.quality_event_mask, bqr_config.minimum_report_interval_ms, bqr_config.report_interval_multiple); return; @@ -394,18 +393,17 @@ void ConfigureBqr(const BqrConfiguration& bqr_config) { if (bqr_config.report_action > REPORT_ACTION_CLEAR || bqr_config.quality_event_mask > kQualityEventMaskAll || bqr_config.minimum_report_interval_ms > kMinReportIntervalMaxMs) { - log::fatal("Invalid Parameter, Action: {}, Mask: {}, Interval: {}", - bqr_config.report_action, - loghex(bqr_config.quality_event_mask), + log::fatal("Invalid Parameter, Action: {}, Mask: 0x{:x}, Interval: {}", + bqr_config.report_action, bqr_config.quality_event_mask, bqr_config.minimum_report_interval_ms); return; } } } - log::info("Action: {}, Mask: {}, Interval: {} Multiple: {}", - loghex(static_cast<uint8_t>(bqr_config.report_action)), - loghex(bqr_config.quality_event_mask), + log::info("Action: 0x{:x}, Mask: 0x{:x}, Interval: {} Multiple: {}", + static_cast<uint8_t>(bqr_config.report_action), + bqr_config.quality_event_mask, bqr_config.minimum_report_interval_ms, bqr_config.report_interval_multiple); @@ -447,7 +445,7 @@ void BqrVscCompleteCallback(tBTM_VSC_CMPL* p_vsc_cmpl_params) { STREAM_TO_UINT8(status, p_event_param_buf); if (status != HCI_SUCCESS) { - log::error("Fail to configure BQR. status: {}", loghex(status)); + log::error("Fail to configure BQR. status: 0x{:x}", status); return; } @@ -478,10 +476,10 @@ void BqrVscCompleteCallback(tBTM_VSC_CMPL* p_vsc_cmpl_params) { } log::info( - "current event mask: {}, vendor quality: {}, vendor trace: {}, report " - "interval: {}", - loghex(current_quality_event_mask), loghex(current_vnd_quality_mask), - loghex(current_vnd_trace_mask), loghex(bqr_report_interval)); + "current event mask: 0x{:x}, vendor quality: 0x{:x}, vendor trace: " + "0x{:x}, report interval: 0x{:x}", + current_quality_event_mask, current_vnd_quality_mask, + current_vnd_trace_mask, bqr_report_interval); ConfigureBqrCmpl(current_quality_event_mask); } @@ -525,7 +523,7 @@ void ConfigBqrA2dpScoThreshold() { } void ConfigureBqrCmpl(uint32_t current_evt_mask) { - log::info("current_evt_mask: {}", loghex(current_evt_mask)); + log::info("current_evt_mask: 0x{:x}", current_evt_mask); // (Un)Register for VSE of Bluetooth Quality Report sub event tBTM_STATUS btm_status = BTM_BT_Quality_Report_VSE_Register( current_evt_mask > kQualityEventMaskAllOff, CategorizeBqrEvent); @@ -589,11 +587,11 @@ void CategorizeBqrEvent(uint8_t length, const uint8_t* p_bqr_event) { case QUALITY_REPORT_ID_BT_SCHEDULING_TRACE: case QUALITY_REPORT_ID_CONTROLLER_DBG_INFO: case QUALITY_REPORT_ID_VENDOR_SPECIFIC_TRACE: - log::warn("Unexpected ID: {}", loghex(quality_report_id)); + log::warn("Unexpected ID: 0x{:x}", quality_report_id); break; default: - log::warn("Unknown ID: {}", loghex(quality_report_id)); + log::warn("Unknown ID: 0x{:x}", quality_report_id); break; } } diff --git a/system/btif/src/btif_debug_conn.cc b/system/btif/src/btif_debug_conn.cc index fdddb7265a..c73d7cccd8 100644 --- a/system/btif/src/btif_debug_conn.cc +++ b/system/btif/src/btif_debug_conn.cc @@ -18,7 +18,6 @@ #include "btif/include/btif_debug_conn.h" -#include <stdio.h> #include <time.h> #include "common/time_util.h" diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc index a3f477b622..fb6e8d176c 100644 --- a/system/btif/src/btif_dm.cc +++ b/system/btif/src/btif_dm.cc @@ -41,7 +41,6 @@ #include <hardware/bt_le_audio.h> #include <hardware/bt_vc.h> #include <signal.h> -#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> @@ -298,6 +297,9 @@ static void btif_stats_add_bond_event(const RawAddress& bd_addr, bt_bond_function_t function, bt_bond_state_t state); +static void btif_on_name_read(RawAddress bd_addr, tHCI_ERROR_CODE hci_status, + const BD_NAME bd_name, bool during_device_search); + /****************************************************************************** * Externs *****************************************************************************/ @@ -468,7 +470,7 @@ static bool check_eir_appearance(tBTA_DM_SEARCH* p_search_data, /******************************************************************************* * - * Function check_cached_remote_name + * Function get_cached_remote_name * * Description Check if remote name is in the NVRAM cache * @@ -476,9 +478,9 @@ static bool check_eir_appearance(tBTA_DM_SEARCH* p_search_data, * Populate p_remote_name, if provided and remote name found * ******************************************************************************/ -static bool check_cached_remote_name(tBTA_DM_SEARCH* p_search_data, - uint8_t* p_remote_name, - uint8_t* p_remote_name_len) { +static bool get_cached_remote_name(const RawAddress& bd_addr, + uint8_t* p_remote_name, + uint8_t* p_remote_name_len) { bt_bdname_t bdname; bt_property_t prop_name; @@ -486,8 +488,8 @@ static bool check_cached_remote_name(tBTA_DM_SEARCH* p_search_data, BTIF_STORAGE_FILL_PROPERTY(&prop_name, BT_PROPERTY_BDNAME, sizeof(bt_bdname_t), &bdname); - if (btif_storage_get_remote_device_property( - &p_search_data->inq_res.bd_addr, &prop_name) == BT_STATUS_SUCCESS) { + if (btif_storage_get_remote_device_property(&bd_addr, &prop_name) == + BT_STATUS_SUCCESS) { if (p_remote_name && p_remote_name_len) { strcpy((char*)p_remote_name, (char*)bdname.name); *p_remote_name_len = strlen((char*)p_remote_name); @@ -659,7 +661,7 @@ static void btif_update_remote_version_property(RawAddress* p_bd) { BTM_ReadRemoteVersion(*p_bd, &lmp_ver, &mfct_set, &lmp_subver); log::info("Remote version info valid:{} [{}]:0x{:x},0x{:x},0x{:x}", - version_info_valid, (*p_bd), lmp_ver, mfct_set, lmp_subver); + version_info_valid, *p_bd, lmp_ver, mfct_set, lmp_subver); if (version_info_valid) { // Always update cache to ensure we have availability whenever BTM API is @@ -1066,9 +1068,7 @@ static void btif_dm_pin_req_evt(tBTA_DM_PIN_REQ* p_pin_req) { * ******************************************************************************/ static void btif_dm_ssp_cfm_req_evt(tBTA_DM_SP_CFM_REQ* p_ssp_cfm_req) { - bt_bdname_t bd_name; bool is_incoming = !(pairing_cb.state == BT_BOND_STATE_BONDING); - uint32_t cod; int dev_type; log::verbose("addr:{}, just_works:{}, loc_auth_req={}, rmt_auth_req={}", @@ -1087,7 +1087,6 @@ static void btif_dm_ssp_cfm_req_evt(tBTA_DM_SP_CFM_REQ* p_ssp_cfm_req) { (tBT_DEVICE_TYPE)dev_type); RawAddress bd_addr = p_ssp_cfm_req->bd_addr; - bd_name_copy(bd_name.name, p_ssp_cfm_req->bd_name); if (pairing_cb.state == BT_BOND_STATE_BONDING && bd_addr != pairing_cb.bd_addr) { @@ -1126,29 +1125,19 @@ static void btif_dm_ssp_cfm_req_evt(tBTA_DM_SP_CFM_REQ* p_ssp_cfm_req) { } } - cod = devclass2uint(p_ssp_cfm_req->dev_class); - - if (cod == 0) { - log::warn("cod is 0, set as unclassified"); - cod = COD_UNCLASSIFIED; - } - pairing_cb.sdp_attempts = 0; BTM_LogHistory(kBtmLogTagCallback, bd_addr, "Ssp request", - base::StringPrintf("name:\"%s\" just_works:%c pin:%u", - PRIVATE_NAME(bd_name.name), + base::StringPrintf("just_works:%c pin:%u", (p_ssp_cfm_req->just_works) ? 'T' : 'F', p_ssp_cfm_req->num_val)); GetInterfaceToProfiles()->events->invoke_ssp_request_cb( - bd_addr, bd_name, cod, + bd_addr, (p_ssp_cfm_req->just_works ? BT_SSP_VARIANT_CONSENT : BT_SSP_VARIANT_PASSKEY_CONFIRMATION), p_ssp_cfm_req->num_val); } static void btif_dm_ssp_key_notif_evt(tBTA_DM_SP_KEY_NOTIF* p_ssp_key_notif) { - bt_bdname_t bd_name; - uint32_t cod; int dev_type; log::verbose("addr:{}", p_ssp_key_notif->bd_addr); @@ -1166,24 +1155,14 @@ static void btif_dm_ssp_key_notif_evt(tBTA_DM_SP_KEY_NOTIF* p_ssp_key_notif) { p_ssp_key_notif->dev_class, (tBT_DEVICE_TYPE)dev_type); RawAddress bd_addr = p_ssp_key_notif->bd_addr; - bd_name_copy(bd_name.name, p_ssp_key_notif->bd_name); bond_state_changed(BT_STATUS_SUCCESS, bd_addr, BT_BOND_STATE_BONDING); pairing_cb.is_ssp = true; - cod = devclass2uint(p_ssp_key_notif->dev_class); - if (cod == 0) { - log::warn("cod is 0, set as unclassified"); - cod = COD_UNCLASSIFIED; - } - - BTM_LogHistory( - kBtmLogTagCallback, bd_addr, "Ssp request", - base::StringPrintf("name:'%s' passkey:%u", PRIVATE_NAME(bd_name.name), - p_ssp_key_notif->passkey)); + BTM_LogHistory(kBtmLogTagCallback, bd_addr, "Ssp request", + base::StringPrintf("passkey:%u", p_ssp_key_notif->passkey)); GetInterfaceToProfiles()->events->invoke_ssp_request_cb( - bd_addr, bd_name, cod, BT_SSP_VARIANT_PASSKEY_NOTIFICATION, - p_ssp_key_notif->passkey); + bd_addr, BT_SSP_VARIANT_PASSKEY_NOTIFICATION, p_ssp_key_notif->passkey); } /******************************************************************************* * @@ -1426,40 +1405,9 @@ static void btif_dm_search_devices_evt(tBTA_DM_SEARCH_EVT event, switch (event) { case BTA_DM_NAME_READ_EVT: { - /* Remote name update */ - if (strlen((const char*)p_search_data->name_res.bd_name)) { - /** Fix inquiry time too long @{ */ - bt_property_t properties[3]; - /** @} */ - bt_status_t status; - - properties[0].type = BT_PROPERTY_BDNAME; - properties[0].val = p_search_data->name_res.bd_name; - properties[0].len = strlen((char*)p_search_data->name_res.bd_name); - RawAddress& bdaddr = p_search_data->name_res.bd_addr; - - status = - btif_storage_set_remote_device_property(&bdaddr, &properties[0]); - ASSERTC(status == BT_STATUS_SUCCESS, - "failed to save remote device property", status); - GetInterfaceToProfiles()->events->invoke_remote_device_properties_cb( - status, bdaddr, 1, properties); - /** Fix inquiry time too long @{ */ - uint32_t cod = get_cod(&bdaddr); - if (cod != 0) { - BTIF_STORAGE_FILL_PROPERTY(&properties[1], BT_PROPERTY_BDADDR, sizeof(bdaddr), &bdaddr); - BTIF_STORAGE_FILL_PROPERTY(&properties[2], BT_PROPERTY_CLASS_OF_DEVICE, sizeof(uint32_t), &cod); - log::debug("report new device to JNI"); - GetInterfaceToProfiles()->events->invoke_device_found_cb(3, properties); - } else { - log::info("Skipping RNR callback because cod is zero addr:{} name:{}", - bdaddr, - PRIVATE_NAME(reinterpret_cast<char const*>( - p_search_data->name_res.bd_name))); - } - /** @} */ - } - /* TODO: Services? */ + btif_on_name_read(p_search_data->name_res.bd_addr, HCI_SUCCESS, + p_search_data->name_res.bd_name, + true /* duirng_device_search */); } break; case BTA_DM_INQ_RES_EVT: { @@ -1480,7 +1428,8 @@ static void btif_dm_search_devices_evt(tBTA_DM_SEARCH_EVT event, bdname.name[0] = 0; if (!check_eir_remote_name(p_search_data, bdname.name, &remote_name_len)) - check_cached_remote_name(p_search_data, bdname.name, &remote_name_len); + get_cached_remote_name(p_search_data->inq_res.bd_addr, bdname.name, + &remote_name_len); /* Check EIR for services */ if (p_search_data->inq_res.p_eir) { @@ -1514,7 +1463,19 @@ static void btif_dm_search_devices_evt(tBTA_DM_SEARCH_EVT event, uint32_t cod = devclass2uint(p_search_data->inq_res.dev_class); if (cod != 0) { + /* Use the existing class of device when the one reported from inquiry + is unclassified. Inquiry results coming from BLE can have an + inferred device class based on the service uuids or appearence. We + don't want this to replace the existing value below when we call + btif_storage_add_remote_device */ uint32_t old_cod = get_cod(&bdaddr); + if (IS_FLAG_ENABLED( + do_not_replace_existing_cod_with_uncategorized_cod)) { + if (cod == COD_UNCLASSIFIED && old_cod != 0) { + cod = old_cod; + } + } + if (old_cod != cod) log::info("{} CoD: 0x{:06x} -> 0x{:06x}", bdaddr, old_cod, cod); @@ -1730,7 +1691,7 @@ static bool btif_is_gatt_service_discovery_post_pairing(const RawAddress bd_addr } static void btif_on_service_discovery_results( - RawAddress bd_addr, tBTA_SERVICE_MASK services, tBT_DEVICE_TYPE device_type, + RawAddress bd_addr, tBTA_SERVICE_MASK services, const std::vector<bluetooth::Uuid>& uuids_param, tBTA_STATUS result, tHCI_STATUS hci_status) { bt_property_t prop; @@ -2020,7 +1981,8 @@ void btif_on_gatt_results(RawAddress bd_addr, BD_NAME bd_name, num_properties++; /* Remote name update */ - if (strnlen((const char*)bd_name, BD_NAME_LEN)) { + if (!IS_FLAG_ENABLED(separate_service_and_device_discovery) && + strnlen((const char*)bd_name, BD_NAME_LEN)) { prop[1].type = BT_PROPERTY_BDNAME; prop[1].val = bd_name; prop[1].len = strnlen((char*)bd_name, BD_NAME_LEN); @@ -2042,9 +2004,16 @@ void btif_on_gatt_results(RawAddress bd_addr, BD_NAME bd_name, BT_STATUS_SUCCESS, bd_addr, num_properties, prop); } -void btif_on_name_read(RawAddress bd_addr, tHCI_ERROR_CODE hci_status, - const BD_NAME bd_name) { - if (!IS_FLAG_ENABLED(rnr_present_during_service_discovery)) { +static void btif_on_name_read(RawAddress bd_addr, tHCI_ERROR_CODE hci_status, + const BD_NAME bd_name, + bool during_device_search) { + // Differentiate between merged callbacks + if (!during_device_search + // New fix after refactor, this callback is needed for the fix to work + && !IS_FLAG_ENABLED(separate_service_and_device_discovery) + // Original fix, this callback should not be called if RNR should not be + // called + && !IS_FLAG_ENABLED(rnr_present_during_service_discovery)) { log::info("Skipping name read event - called on bad callback."); return; } @@ -2058,21 +2027,48 @@ void btif_on_name_read(RawAddress bd_addr, tHCI_ERROR_CODE hci_status, log::warn("Received RNR event without valid name addr:{}", bd_addr); return; } - bt_property_t properties[] = {{ + + // Needs 3 properties if during_device_search is true + bt_property_t properties[3] = {{ .type = BT_PROPERTY_BDNAME, .len = (int)strnlen((char*)bd_name, BD_NAME_LEN), .val = (void*)bd_name, }}; + const bt_status_t status = btif_storage_set_remote_device_property(&bd_addr, properties); log::assert_that(status == BT_STATUS_SUCCESS, "Failed to save remote device property status:{}", bt_status_text(status)); - const size_t num_props = sizeof(properties) / sizeof(bt_property_t); GetInterfaceToProfiles()->events->invoke_remote_device_properties_cb( - status, bd_addr, (int)num_props, properties); + status, bd_addr, 1, properties); log::info("Callback for read name event addr:{} name:{}", bd_addr, PRIVATE_NAME(reinterpret_cast<char const*>(bd_name))); + + if (!during_device_search) { + return; + } + + uint32_t cod = get_cod(&bd_addr); + if (cod != 0) { + BTIF_STORAGE_FILL_PROPERTY(&properties[1], BT_PROPERTY_BDADDR, + sizeof(bd_addr), &bd_addr); + BTIF_STORAGE_FILL_PROPERTY(&properties[2], BT_PROPERTY_CLASS_OF_DEVICE, + sizeof(uint32_t), &cod); + log::debug("report new device to JNI"); + GetInterfaceToProfiles()->events->invoke_device_found_cb(3, properties); + } else { + log::info( + "Skipping device found callback because cod is zero addr:{} name:{}", + bd_addr, PRIVATE_NAME(reinterpret_cast<char const*>(bd_name))); + } +} + +void btif_on_name_read_from_btm(const RawAddress& bd_addr, DEV_CLASS /* dc */, + BD_NAME bd_name) { + log::info("{} {}", bd_addr, reinterpret_cast<char const*>(bd_name)); + btif_on_name_read(bd_addr, HCI_SUCCESS, bd_name, + false /* duirng_device_search */); } void btif_on_did_received(RawAddress bd_addr, uint8_t vendor_id_src, @@ -2178,6 +2174,10 @@ void BTIF_dm_enable() { log::info("Local BLE Privacy enabled:{}", ble_privacy_enabled); BTA_DmBleConfigLocalPrivacy(ble_privacy_enabled); + if (IS_FLAG_ENABLED(separate_service_and_device_discovery)) { + BTM_SecAddRmtNameNotifyCallback(btif_on_name_read_from_btm); + } + /* for each of the enabled services in the mask, trigger the profile * enable */ tBTA_SERVICE_MASK service_mask = btif_get_enabled_services_mask(); @@ -2203,6 +2203,10 @@ void BTIF_dm_enable() { } void BTIF_dm_disable() { + if (IS_FLAG_ENABLED(separate_service_and_device_discovery)) { + BTM_SecDeleteRmtNameNotifyCallback(&btif_on_name_read_from_btm); + } + /* for each of the enabled services in the mask, trigger the profile * disable */ tBTA_SERVICE_MASK service_mask = btif_get_enabled_services_mask(); @@ -3076,6 +3080,13 @@ bt_status_t btif_dm_get_adapter_property(bt_property_t* prop) { return BT_STATUS_SUCCESS; } +static void btif_on_name_read_legacy(RawAddress bd_addr, + tHCI_ERROR_CODE hci_status, + const BD_NAME bd_name) { + btif_on_name_read(bd_addr, hci_status, bd_name, + false /* during_device_search */); +}; + /******************************************************************************* * * Function btif_dm_get_remote_services @@ -3098,7 +3109,7 @@ void btif_dm_get_remote_services(RawAddress remote_addr, const int transport) { service_discovery_callbacks{ .on_gatt_results = btif_on_gatt_results, .on_did_received = btif_on_did_received, - .on_name_read = btif_on_name_read, + .on_name_read = btif_on_name_read_legacy, .on_service_discovery_results = btif_on_service_discovery_results}, transport); } @@ -3503,8 +3514,6 @@ bool btif_dm_proc_rmt_oob(const RawAddress& bd_addr, Octet16* p_c, static void btif_dm_ble_key_notif_evt(tBTA_DM_SP_KEY_NOTIF* p_ssp_key_notif) { RawAddress bd_addr; - bt_bdname_t bd_name; - uint32_t cod; int dev_type; log::verbose("addr:{}", p_ssp_key_notif->bd_addr); @@ -3517,20 +3526,15 @@ static void btif_dm_ble_key_notif_evt(tBTA_DM_SP_KEY_NOTIF* p_ssp_key_notif) { p_ssp_key_notif->bd_name, kDevClassEmpty, (tBT_DEVICE_TYPE)dev_type); bd_addr = p_ssp_key_notif->bd_addr; - bd_name_copy(bd_name.name, p_ssp_key_notif->bd_name); bond_state_changed(BT_STATUS_SUCCESS, bd_addr, BT_BOND_STATE_BONDING); pairing_cb.is_ssp = false; - cod = COD_UNCLASSIFIED; - BTM_LogHistory( - kBtmLogTagCallback, bd_addr, "Ssp request", - base::StringPrintf("name:'%s' passkey:%u", PRIVATE_NAME(bd_name.name), - p_ssp_key_notif->passkey)); + BTM_LogHistory(kBtmLogTagCallback, bd_addr, "Ssp request", + base::StringPrintf("passkey:%u", p_ssp_key_notif->passkey)); GetInterfaceToProfiles()->events->invoke_ssp_request_cb( - bd_addr, bd_name, cod, BT_SSP_VARIANT_PASSKEY_NOTIFICATION, - p_ssp_key_notif->passkey); + bd_addr, BT_SSP_VARIANT_PASSKEY_NOTIFICATION, p_ssp_key_notif->passkey); } static bool btif_dm_ble_is_temp_pairing(RawAddress& bd_addr, bool ctkd) { @@ -3752,8 +3756,6 @@ static void btif_dm_remove_ble_bonding_keys(void) { ******************************************************************************/ static void btif_dm_ble_sec_req_evt(tBTA_DM_BLE_SEC_REQ* p_ble_req, bool is_consent) { - bt_bdname_t bd_name; - uint32_t cod; int dev_type; log::verbose("addr:{}", p_ble_req->bd_addr); @@ -3772,7 +3774,6 @@ static void btif_dm_ble_sec_req_evt(tBTA_DM_BLE_SEC_REQ* p_ble_req, (tBT_DEVICE_TYPE)dev_type); RawAddress bd_addr = p_ble_req->bd_addr; - bd_name_copy(bd_name.name, p_ble_req->bd_name); bond_state_changed(BT_STATUS_SUCCESS, bd_addr, BT_BOND_STATE_BONDING); @@ -3782,14 +3783,11 @@ static void btif_dm_ble_sec_req_evt(tBTA_DM_BLE_SEC_REQ* p_ble_req, pairing_cb.is_ssp = true; btm_set_bond_type_dev(p_ble_req->bd_addr, pairing_cb.bond_type); - cod = COD_UNCLASSIFIED; - BTM_LogHistory(kBtmLogTagCallback, bd_addr, "SSP ble request", - base::StringPrintf("name:'%s' BT_SSP_VARIANT_CONSENT", - PRIVATE_NAME(bd_name.name))); + "BT_SSP_VARIANT_CONSENT"); GetInterfaceToProfiles()->events->invoke_ssp_request_cb( - bd_addr, bd_name, cod, BT_SSP_VARIANT_CONSENT, 0); + bd_addr, BT_SSP_VARIANT_CONSENT, 0); } /******************************************************************************* @@ -3830,30 +3828,20 @@ static void btif_dm_ble_passkey_req_evt(tBTA_DM_PIN_REQ* p_pin_req) { } static void btif_dm_ble_key_nc_req_evt(tBTA_DM_SP_KEY_NOTIF* p_notif_req) { /* TODO implement key notification for numeric comparison */ - log::verbose("addr:{}", p_notif_req->bd_addr); - - /* Remote name update */ - btif_update_remote_properties(p_notif_req->bd_addr, p_notif_req->bd_name, - kDevClassEmpty, BT_DEVICE_TYPE_BLE); RawAddress bd_addr = p_notif_req->bd_addr; - - bt_bdname_t bd_name; - bd_name_copy(bd_name.name, p_notif_req->bd_name); + log::verbose("addr:{}", bd_addr); bond_state_changed(BT_STATUS_SUCCESS, bd_addr, BT_BOND_STATE_BONDING); pairing_cb.is_ssp = false; pairing_cb.is_le_only = true; pairing_cb.is_le_nc = true; - BTM_LogHistory( - kBtmLogTagCallback, bd_addr, "Ssp request", - base::StringPrintf("name:'%s' passkey:%u", PRIVATE_NAME(bd_name.name), - p_notif_req->passkey)); + BTM_LogHistory(kBtmLogTagCallback, bd_addr, "Ssp request", + base::StringPrintf("passkey:%u", p_notif_req->passkey)); GetInterfaceToProfiles()->events->invoke_ssp_request_cb( - bd_addr, bd_name, COD_UNCLASSIFIED, BT_SSP_VARIANT_PASSKEY_CONFIRMATION, - p_notif_req->passkey); + bd_addr, BT_SSP_VARIANT_PASSKEY_CONFIRMATION, p_notif_req->passkey); } static void btif_dm_ble_oob_req_evt(tBTA_DM_SP_RMT_OOB* req_oob_type) { @@ -4230,8 +4218,8 @@ void bta_energy_info_cb(tBTM_BLE_TX_TIME_MS tx_time, } void btif_on_name_read(RawAddress bd_addr, tHCI_ERROR_CODE hci_status, - const BD_NAME bd_name) { - ::btif_on_name_read(bd_addr, hci_status, bd_name); + const BD_NAME bd_name, bool during_device_search) { + ::btif_on_name_read(bd_addr, hci_status, bd_name, during_device_search); } } // namespace testing diff --git a/system/btif/src/btif_gatt.cc b/system/btif/src/btif_gatt.cc index 1bd5767328..3e77e98737 100644 --- a/system/btif/src/btif_gatt.cc +++ b/system/btif/src/btif_gatt.cc @@ -30,7 +30,6 @@ #include <hardware/bluetooth.h> #include <hardware/bt_gatt.h> -#include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/system/btif/src/btif_gatt_server.cc b/system/btif/src/btif_gatt_server.cc index f45a681585..43fdf6ed40 100644 --- a/system/btif/src/btif_gatt_server.cc +++ b/system/btif/src/btif_gatt_server.cc @@ -32,7 +32,6 @@ #include <hardware/bluetooth.h> #include <hardware/bt_gatt.h> #include <hardware/bt_gatt_types.h> -#include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/system/btif/src/btif_gatt_test.cc b/system/btif/src/btif_gatt_test.cc index a83e16854c..433686135b 100644 --- a/system/btif/src/btif_gatt_test.cc +++ b/system/btif/src/btif_gatt_test.cc @@ -21,7 +21,6 @@ #include <bluetooth/log.h> #include <hardware/bluetooth.h> #include <hardware/bt_gatt.h> -#include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/system/btif/src/btif_gatt_util.cc b/system/btif/src/btif_gatt_util.cc index 288fb4b73f..e3a33e06f0 100644 --- a/system/btif/src/btif_gatt_util.cc +++ b/system/btif/src/btif_gatt_util.cc @@ -18,17 +18,16 @@ #define LOG_TAG "bt_btif_gatt" -#include <algorithm> - #include "btif_gatt_util.h" #include <bluetooth/log.h> #include <hardware/bluetooth.h> #include <hardware/bt_gatt.h> -#include <stdio.h> #include <stdlib.h> #include <string.h> +#include <algorithm> + #include "bta/include/bta_api_data_types.h" #include "bta/include/bta_sec_api.h" #include "btif_storage.h" diff --git a/system/btif/src/btif_hf.cc b/system/btif/src/btif_hf.cc index c6ffd4dd84..9f48956676 100644 --- a/system/btif/src/btif_hf.cc +++ b/system/btif/src/btif_hf.cc @@ -1263,7 +1263,7 @@ bt_status_t HeadsetInterface::PhoneStateChange( log::debug( "bd_addr:{} active_bda:{} num_active:{} prev_num_active:{} num_held:{} " "prev_num_held:{} call_state:{} prev_call_state:{}", - (*bd_addr), active_bda, num_active, control_block.num_active, num_held, + *bd_addr, active_bda, num_active, control_block.num_active, num_held, control_block.num_held, dump_hf_call_state(call_setup_state), dump_hf_call_state(control_block.call_setup_state)); tBTA_AG_RES res = BTA_AG_UNKNOWN; diff --git a/system/btif/src/btif_hh.cc b/system/btif/src/btif_hh.cc index d4938c76ad..46428e3341 100644 --- a/system/btif/src/btif_hh.cc +++ b/system/btif/src/btif_hh.cc @@ -1208,6 +1208,12 @@ static void btif_hh_upstreams_evt(uint16_t event, char* p_param) { p_data->dscp_info.ssr_max_latency, p_data->dscp_info.ssr_min_tout, len, p_data->dscp_info.descriptor.dsc_list); + // Allow incoming connections + if (IS_FLAG_ENABLED(allow_switching_hid_and_hogp) && + IS_FLAG_ENABLED(save_initial_hid_connection_policy)) { + btif_storage_set_hid_connection_policy(p_dev->link_spec, true); + } + ASSERTC(ret == BT_STATUS_SUCCESS, "storing hid info failed", ret); log::warn("BTA_HH_GET_DSCP_EVT: Called add device"); diff --git a/system/btif/src/btif_rc.cc b/system/btif/src/btif_rc.cc index a7905cc8ca..3b6e545243 100644 --- a/system/btif/src/btif_rc.cc +++ b/system/btif/src/btif_rc.cc @@ -2313,7 +2313,7 @@ static bt_status_t get_folder_items_list_rsp(const RawAddress& bd_addr, log::verbose("item_cnt: {} len: {}", item_cnt, len_before); status = AVRC_BldResponse(p_dev->rc_handle, &avrc_rsp, &p_msg); log::verbose("Build rsp status: {} len: {}", status, - (p_msg ? p_msg->len : 0)); + p_msg ? p_msg->len : 0); int len_after = p_msg ? p_msg->len : 0; if (status != AVRC_STS_NO_ERROR || len_before == len_after) { /* Error occured in build response or we ran out of buffer so break the diff --git a/system/btif/src/btif_sock_l2cap.cc b/system/btif/src/btif_sock_l2cap.cc index 77af902a76..04d3738dd4 100644 --- a/system/btif/src/btif_sock_l2cap.cc +++ b/system/btif/src/btif_sock_l2cap.cc @@ -260,7 +260,7 @@ static void btsock_l2cap_free_l(l2cap_socket* sock) { BTA_JvL2capClose(sock->handle); } if ((sock->channel >= 0) && (sock->server)) { - BTA_JvFreeChannel(sock->channel, BTA_JV_CONN_TYPE_L2CAP_LE); + BTA_JvFreeChannel(sock->channel, tBTA_JV_CONN_TYPE::L2CAP_LE); log::info("Stopped L2CAP LE COC server socket_id:{} channel:{}", sock->id, sock->channel); BTA_JvL2capStopServer(sock->channel, sock->id); @@ -271,7 +271,7 @@ static void btsock_l2cap_free_l(l2cap_socket* sock) { BTA_JvL2capClose(sock->handle); } if ((sock->channel >= 0) && (sock->server)) { - BTA_JvFreeChannel(sock->channel, BTA_JV_CONN_TYPE_L2CAP); + BTA_JvFreeChannel(sock->channel, tBTA_JV_CONN_TYPE::L2CAP); BTA_JvL2capStopServer(sock->channel, sock->id); } } @@ -641,7 +641,7 @@ static void on_l2cap_close(tBTA_JV_L2CAP_CLOSE* p_close, uint32_t id) { // TODO: This does not seem to be called... // I'm not sure if this will be called for non-server sockets? if (sock->server) { - BTA_JvFreeChannel(sock->channel, BTA_JV_CONN_TYPE_L2CAP); + BTA_JvFreeChannel(sock->channel, tBTA_JV_CONN_TYPE::L2CAP); } btsock_l2cap_free_l(sock); } @@ -795,8 +795,8 @@ void on_l2cap_psm_assigned(int id, int psm) { } static void btsock_l2cap_server_listen(l2cap_socket* sock) { - int connection_type = - sock->is_le_coc ? BTA_JV_CONN_TYPE_L2CAP_LE : BTA_JV_CONN_TYPE_L2CAP; + tBTA_JV_CONN_TYPE connection_type = + sock->is_le_coc ? tBTA_JV_CONN_TYPE::L2CAP_LE : tBTA_JV_CONN_TYPE::L2CAP; /* If we have a channel specified in the request, just start the server, * else we request a PSM and start the server after we receive a PSM. */ @@ -814,9 +814,9 @@ static void btsock_l2cap_server_listen(l2cap_socket* sock) { ertm_info.reset(new tL2CAP_ERTM_INFO(obex_l2c_etm_opt)); } - BTA_JvL2capStartServer(connection_type, sock->security, 0, - std::move(ertm_info), sock->channel, sock->rx_mtu, - std::move(cfg), btsock_l2cap_cbk, sock->id); + BTA_JvL2capStartServer(connection_type, sock->security, std::move(ertm_info), + sock->channel, sock->rx_mtu, std::move(cfg), + btsock_l2cap_cbk, sock->id); } static bt_status_t btsock_l2cap_listen_or_connect(const char* name, @@ -865,21 +865,22 @@ static bt_status_t btsock_l2cap_listen_or_connect(const char* name, if (listen) { btsock_l2cap_server_listen(sock); } else { - int connection_type = - sock->is_le_coc ? BTA_JV_CONN_TYPE_L2CAP_LE : BTA_JV_CONN_TYPE_L2CAP; + tBTA_JV_CONN_TYPE connection_type = sock->is_le_coc + ? tBTA_JV_CONN_TYPE::L2CAP_LE + : tBTA_JV_CONN_TYPE::L2CAP; - /* Setup ETM settings: mtu will be set below */ - std::unique_ptr<tL2CAP_CFG_INFO> cfg = std::make_unique<tL2CAP_CFG_INFO>( - tL2CAP_CFG_INFO{.fcr_present = true, .fcr = kDefaultErtmOptions}); + /* Setup ETM settings: mtu will be set below */ + std::unique_ptr<tL2CAP_CFG_INFO> cfg = std::make_unique<tL2CAP_CFG_INFO>( + tL2CAP_CFG_INFO{.fcr_present = true, .fcr = kDefaultErtmOptions}); - std::unique_ptr<tL2CAP_ERTM_INFO> ertm_info; - if (!sock->is_le_coc) { - ertm_info.reset(new tL2CAP_ERTM_INFO(obex_l2c_etm_opt)); - } + std::unique_ptr<tL2CAP_ERTM_INFO> ertm_info; + if (!sock->is_le_coc) { + ertm_info.reset(new tL2CAP_ERTM_INFO(obex_l2c_etm_opt)); + } - BTA_JvL2capConnect( - connection_type, sock->security, 0, std::move(ertm_info), channel, - sock->rx_mtu, std::move(cfg), sock->addr, btsock_l2cap_cbk, sock->id); + BTA_JvL2capConnect(connection_type, sock->security, std::move(ertm_info), + channel, sock->rx_mtu, std::move(cfg), sock->addr, + btsock_l2cap_cbk, sock->id); } *sock_fd = sock->app_fd; diff --git a/system/btif/src/btif_sock_rfc.cc b/system/btif/src/btif_sock_rfc.cc index bd7d6897c6..0f427d604f 100644 --- a/system/btif/src/btif_sock_rfc.cc +++ b/system/btif/src/btif_sock_rfc.cc @@ -333,7 +333,7 @@ bt_status_t btsock_rfc_listen(const char* service_name, } log::info("Adding listening socket service_name: {} - channel: {}", service_name, channel); - BTA_JvGetChannelId(BTA_JV_CONN_TYPE_RFCOMM, slot->id, channel); + BTA_JvGetChannelId(tBTA_JV_CONN_TYPE::RFCOMM, slot->id, channel); *sock_fd = slot->app_fd; // Transfer ownership of fd to caller. /*TODO: * We are leaking one of the app_fd's - either the listen socket, or the @@ -381,9 +381,8 @@ bt_status_t btsock_rfc_connect(const RawAddress* bd_addr, } if (!service_uuid || service_uuid->IsEmpty()) { - tBTA_JV_STATUS ret = - BTA_JvRfcommConnect(slot->security, slot->role, slot->scn, slot->addr, - rfcomm_cback, slot->id); + tBTA_JV_STATUS ret = BTA_JvRfcommConnect( + slot->security, slot->scn, slot->addr, rfcomm_cback, slot->id); if (ret != tBTA_JV_STATUS::SUCCESS) { log::error( "unable to initiate RFCOMM connection. status:{}, scn:{}, bd_addr:{}", @@ -786,8 +785,8 @@ static void jv_dm_cback(tBTA_JV_EVT event, tBTA_JV* p_data, uint32_t id) { "Since UUID is not valid; not setting SDP-record and just starting " "the RFCOMM server"); // now start the rfcomm server after sdp & channel # assigned - BTA_JvRfcommStartServer(rs->security, rs->role, rs->scn, - MAX_RFC_SESSION, rfcomm_cback, id); + BTA_JvRfcommStartServer(rs->security, rs->scn, MAX_RFC_SESSION, + rfcomm_cback, id); } break; } @@ -815,8 +814,8 @@ static void jv_dm_cback(tBTA_JV_EVT event, tBTA_JV* p_data, uint32_t id) { } // Start the rfcomm server after sdp & channel # assigned. - BTA_JvRfcommStartServer(slot->security, slot->role, slot->scn, - MAX_RFC_SESSION, rfcomm_cback, id); + BTA_JvRfcommStartServer(slot->security, slot->scn, MAX_RFC_SESSION, + rfcomm_cback, id); break; } @@ -866,8 +865,8 @@ static void handle_discovery_comp(tBTA_JV_STATUS status, int scn, uint32_t id) { return; } - if (BTA_JvRfcommConnect(slot->security, slot->role, scn, slot->addr, - rfcomm_cback, slot->id) != tBTA_JV_STATUS::SUCCESS) { + if (BTA_JvRfcommConnect(slot->security, scn, slot->addr, rfcomm_cback, + slot->id) != tBTA_JV_STATUS::SUCCESS) { log::warn( "BTA_JvRfcommConnect() returned BTA_JV_FAILURE for RFCOMM slot with " "id: {}", diff --git a/system/btif/src/btif_sock_thread.cc b/system/btif/src/btif_sock_thread.cc index 885287ed8f..59a4dff65a 100644 --- a/system/btif/src/btif_sock_thread.cc +++ b/system/btif/src/btif_sock_thread.cc @@ -34,7 +34,6 @@ #include <features.h> #include <poll.h> #include <pthread.h> -#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/select.h> diff --git a/system/btif/src/btif_sock_util.cc b/system/btif/src/btif_sock_util.cc index 536f824d9e..ccdf71d155 100644 --- a/system/btif/src/btif_sock_util.cc +++ b/system/btif/src/btif_sock_util.cc @@ -26,7 +26,6 @@ #include <hardware/bt_sock.h> #include <netinet/in.h> #include <netinet/tcp.h> -#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/ioctl.h> diff --git a/system/btif/src/btif_util.cc b/system/btif/src/btif_util.cc index a72231a0b5..67f576cafc 100644 --- a/system/btif/src/btif_util.cc +++ b/system/btif/src/btif_util.cc @@ -33,7 +33,6 @@ #include <ctype.h> #include <hardware/bt_av.h> #include <netinet/in.h> -#include <stdio.h> #include <stdlib.h> #include <string> diff --git a/system/btif/test/btif_core_test.cc b/system/btif/test/btif_core_test.cc index 059efcbd69..a5d5c2f0fc 100644 --- a/system/btif/test/btif_core_test.cc +++ b/system/btif/test/btif_core_test.cc @@ -41,6 +41,12 @@ namespace bluetooth::testing { void set_hal_cbacks(bt_callbacks_t* callbacks); } // namespace bluetooth::testing +namespace bluetooth::legacy::testing { +void bta_dm_acl_down(const RawAddress& bd_addr, tBT_TRANSPORT transport); +void bta_dm_acl_up(const RawAddress& bd_addr, tBT_TRANSPORT transport, + uint16_t acl_handle); +} // namespace bluetooth::legacy::testing + const tBTA_AG_RES_DATA tBTA_AG_RES_DATA::kEmpty = {}; using testing::Return; @@ -53,6 +59,7 @@ module_t rust_module; namespace { const RawAddress kRawAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0x66}); +const uint16_t kHciHandle = 123; auto timeout_time = std::chrono::seconds(3); @@ -76,7 +83,6 @@ void pin_request_callback(RawAddress* /* remote_bd_addr */, bt_bdname_t* /* bd_name */, uint32_t /* cod */, bool /* min_16_digit */) {} void ssp_request_callback(RawAddress* /* remote_bd_addr */, - bt_bdname_t* /* bd_name */, uint32_t /* cod */, bt_ssp_variant_t /* pairing_variant */, uint32_t /* pass_key */) {} void bond_state_changed_callback(bt_status_t /* status */, @@ -174,6 +180,7 @@ class BtifCoreTest : public ::testing::Test { }; class BtifCoreWithControllerTest : public BtifCoreTest { + protected: void SetUp() override { BtifCoreTest::SetUp(); ON_CALL(controller_, SupportsSniffSubrating).WillByDefault(Return(true)); @@ -182,13 +189,27 @@ class BtifCoreWithControllerTest : public BtifCoreTest { void TearDown() override { BtifCoreTest::TearDown(); } }; +class BtifCoreWithConnectionTest : public BtifCoreWithControllerTest { + protected: + void SetUp() override { + BtifCoreWithControllerTest::SetUp(); + bluetooth::legacy::testing::bta_dm_acl_up(kRawAddress, BT_TRANSPORT_AUTO, + kHciHandle); + } + + void TearDown() override { + bluetooth::legacy::testing::bta_dm_acl_down(kRawAddress, BT_TRANSPORT_AUTO); + BtifCoreWithControllerTest::TearDown(); + } +}; + std::promise<int> promise0; void callback0(int val) { promise0.set_value(val); } TEST_F(BtifCoreTest, test_nop) {} TEST_F(BtifCoreTest, test_post_on_bt_simple0) { - const int val = 123; + const int val = kHciHandle; promise0 = std::promise<int>(); std::future<int> future0 = promise0.get_future(); post_on_bt_jni([=]() { callback0(val); }); @@ -646,17 +667,12 @@ TEST_F(BtifUtilsTest, dump_rc_pdu) { dump_rc_pdu(std::numeric_limits<uint8_t>::max()).starts_with("Unknown")); } -void bta_dm_acl_up(const RawAddress& bd_addr, tBT_TRANSPORT transport, - uint16_t acl_handle); - TEST_F(BtifCoreWithControllerTest, btif_dm_get_connection_state__unconnected) { ASSERT_EQ(0, btif_dm_get_connection_state(kRawAddress)); } -TEST_F(BtifCoreWithControllerTest, +TEST_F(BtifCoreWithConnectionTest, btif_dm_get_connection_state__connected_no_encryption) { - bta_dm_acl_up(kRawAddress, BT_TRANSPORT_AUTO, 0x123); - test::mock::stack_btm_sec::BTM_IsEncrypted.body = [](const RawAddress& /* bd_addr */, tBT_TRANSPORT transport) { switch (transport) { @@ -671,10 +687,8 @@ TEST_F(BtifCoreWithControllerTest, test::mock::stack_btm_sec::BTM_IsEncrypted = {}; } -TEST_F(BtifCoreWithControllerTest, +TEST_F(BtifCoreWithConnectionTest, btif_dm_get_connection_state__connected_classic_encryption) { - bta_dm_acl_up(kRawAddress, BT_TRANSPORT_AUTO, 0x123); - test::mock::stack_btm_sec::BTM_IsEncrypted.body = [](const RawAddress& /* bd_addr */, tBT_TRANSPORT transport) { switch (transport) { @@ -686,13 +700,12 @@ TEST_F(BtifCoreWithControllerTest, return false; }; ASSERT_EQ(3, btif_dm_get_connection_state(kRawAddress)); + test::mock::stack_btm_sec::BTM_IsEncrypted = {}; } -TEST_F(BtifCoreWithControllerTest, +TEST_F(BtifCoreWithConnectionTest, btif_dm_get_connection_state__connected_le_encryption) { - bta_dm_acl_up(kRawAddress, BT_TRANSPORT_AUTO, 0x123); - test::mock::stack_btm_sec::BTM_IsEncrypted.body = [](const RawAddress& /* bd_addr */, tBT_TRANSPORT transport) { switch (transport) { @@ -707,10 +720,8 @@ TEST_F(BtifCoreWithControllerTest, test::mock::stack_btm_sec::BTM_IsEncrypted = {}; } -TEST_F(BtifCoreWithControllerTest, +TEST_F(BtifCoreWithConnectionTest, btif_dm_get_connection_state__connected_both_encryption) { - bta_dm_acl_up(kRawAddress, BT_TRANSPORT_AUTO, 0x123); - test::mock::stack_btm_sec::BTM_IsEncrypted.body = [](const RawAddress& /* bd_addr */, tBT_TRANSPORT transport) { switch (transport) { @@ -725,9 +736,7 @@ TEST_F(BtifCoreWithControllerTest, test::mock::stack_btm_sec::BTM_IsEncrypted = {}; } -TEST_F(BtifCoreWithControllerTest, btif_dm_get_connection_state_sync) { - bta_dm_acl_up(kRawAddress, BT_TRANSPORT_AUTO, 0x123); - +TEST_F(BtifCoreWithConnectionTest, btif_dm_get_connection_state_sync) { test::mock::stack_btm_sec::BTM_IsEncrypted.body = [](const RawAddress& /* bd_addr */, tBT_TRANSPORT transport) { switch (transport) { diff --git a/system/btif/test/btif_dm_test.cc b/system/btif/test/btif_dm_test.cc index 51d830b3a9..1b1826be04 100644 --- a/system/btif/test/btif_dm_test.cc +++ b/system/btif/test/btif_dm_test.cc @@ -55,7 +55,7 @@ void bta_energy_info_cb(tBTM_BLE_TX_TIME_MS tx_time, tBTM_CONTRL_STATE ctrl_state, tBTA_STATUS status); void btif_on_name_read(RawAddress bd_addr, tHCI_ERROR_CODE hci_status, - const BD_NAME bd_name); + const BD_NAME bd_name, bool during_device_search); } // namespace testing } // namespace legacy @@ -68,18 +68,30 @@ constexpr tBTM_BLE_IDLE_TIME_MS idle_time = 0x2468acd0; constexpr tBTM_BLE_ENERGY_USED energy_used = 0x13579bdf; } // namespace -class BtifDmTest : public ::testing::Test { +class BtifDmWithMocksTest : public ::testing::Test { + protected: + void SetUp() override { fake_osi_ = std::make_unique<test::fake::FakeOsi>(); } + + void TearDown() override { fake_osi_.reset(); } + + std::unique_ptr<test::fake::FakeOsi> fake_osi_; +}; + +class BtifDmTest : public BtifDmWithMocksTest { protected: void SetUp() override { - fake_osi_ = std::make_unique<test::fake::FakeOsi>(); + BtifDmWithMocksTest::SetUp(); mock_core_interface_ = std::make_unique<MockCoreInterface>(); bluetooth::legacy::testing::set_interface_to_profiles( mock_core_interface_.get()); } - void TearDown() override {} + void TearDown() override { + bluetooth::legacy::testing::set_interface_to_profiles(nullptr); + mock_core_interface_.reset(); + BtifDmWithMocksTest::TearDown(); + } - std::unique_ptr<test::fake::FakeOsi> fake_osi_; std::unique_ptr<MockCoreInterface> mock_core_interface_; }; @@ -106,7 +118,7 @@ class BtifDmWithUidTest : public BtifDmTest { } void TearDown() override { - void btif_dm_cleanup(); + btif_dm_cleanup(); BtifDmTest::TearDown(); } }; @@ -178,7 +190,7 @@ TEST_F_WITH_FLAGS(BtifDmWithStackTest, bd_name_from_char_pointer(bd_name, kBdName); bluetooth::legacy::testing::btif_on_name_read(kRawAddress, HCI_SUCCESS, - bd_name); + bd_name, true); ASSERT_EQ(BT_STATUS_SUCCESS, invoke_remote_device_properties_cb.status); ASSERT_EQ(kRawAddress, invoke_remote_device_properties_cb.bd_addr); diff --git a/system/btif/test/btif_hh_test.cc b/system/btif/test/btif_hh_test.cc index 1319a27516..f22726f449 100644 --- a/system/btif/test/btif_hh_test.cc +++ b/system/btif/test/btif_hh_test.cc @@ -28,10 +28,8 @@ #include "btcore/include/module.h" #include "common/init_flags.h" #include "include/hardware/bt_hh.h" -#include "osi/include/allocator.h" #include "test/common/core_interface.h" #include "test/common/mock_functions.h" -#include "test/mock/mock_osi_allocator.h" using namespace std::chrono_literals; @@ -162,7 +160,7 @@ class BtifHhWithHalCallbacksTest : public BtifHhWithMockTest { ASSERT_EQ(std::future_status::ready, future.wait_for(2s)); ASSERT_EQ(ASSOCIATE_JVM, future.get()); - bt_callbacks.thread_evt_cb = [](bt_cb_thread_evt evt) {}; + bt_callbacks.thread_evt_cb = [](bt_cb_thread_evt /* evt */) {}; } void TearDown() override { @@ -175,7 +173,7 @@ class BtifHhWithHalCallbacksTest : public BtifHhWithMockTest { ASSERT_EQ(std::future_status::ready, future.wait_for(2s)); ASSERT_EQ(DISASSOCIATE_JVM, future.get()); - bt_callbacks.thread_evt_cb = [](bt_cb_thread_evt evt) {}; + bt_callbacks.thread_evt_cb = [](bt_cb_thread_evt /* evt */) {}; BtifHhWithMockTest::TearDown(); } }; @@ -213,6 +211,8 @@ class BtifHhWithDevice : public BtifHhAdapterReady { TEST_F(BtifHhAdapterReady, lifecycle) {} +static uint8_t report_data[sizeof(BT_HDR) + data32.size()]; + TEST_F(BtifHhWithDevice, BTA_HH_GET_RPT_EVT) { tBTA_HH data = { .hs_data = @@ -221,8 +221,7 @@ TEST_F(BtifHhWithDevice, BTA_HH_GET_RPT_EVT) { .handle = kHhHandle, .rsp_data = { - .p_rpt_data = static_cast<BT_HDR*>( - osi_calloc(data32.size() + sizeof(BT_HDR))), + .p_rpt_data = reinterpret_cast<BT_HDR*>(report_data), }, }, }; @@ -235,8 +234,8 @@ TEST_F(BtifHhWithDevice, BTA_HH_GET_RPT_EVT) { g_bthh_callbacks_get_report_promise = std::promise<get_report_cb_t>(); auto future = g_bthh_callbacks_get_report_promise.get_future(); bthh_callbacks.get_report_cb = [](RawAddress* bd_addr, - tBLE_ADDR_TYPE addr_type, - tBT_TRANSPORT transport, + tBLE_ADDR_TYPE /* addr_type */, + tBT_TRANSPORT /* transport */, bthh_status_t hh_status, uint8_t* rpt_data, int rpt_size) { get_report_cb_t report = { @@ -249,7 +248,6 @@ TEST_F(BtifHhWithDevice, BTA_HH_GET_RPT_EVT) { }; bluetooth::legacy::testing::bte_hh_evt(BTA_HH_GET_RPT_EVT, &data); - osi_free(data.hs_data.rsp_data.p_rpt_data); ASSERT_EQ(std::future_status::ready, future.wait_for(2s)); auto report = future.get(); @@ -269,8 +267,8 @@ class BtifHHVirtualUnplugTest : public BtifHhAdapterReady { void SetUp() override { BtifHhAdapterReady::SetUp(); bthh_callbacks.connection_state_cb = [](RawAddress* bd_addr, - tBLE_ADDR_TYPE addr_type, - tBT_TRANSPORT transport, + tBLE_ADDR_TYPE /* addr_type */, + tBT_TRANSPORT /* transport */, bthh_connection_state_t state) { connection_state_cb_t connection_state = { .raw_address = *bd_addr, @@ -282,8 +280,9 @@ class BtifHHVirtualUnplugTest : public BtifHhAdapterReady { void TearDown() override { bthh_callbacks.connection_state_cb = - [](RawAddress* bd_addr, tBLE_ADDR_TYPE addr_type, - tBT_TRANSPORT transport, bthh_connection_state_t state) {}; + [](RawAddress* /* bd_addr */, tBLE_ADDR_TYPE /* addr_type */, + tBT_TRANSPORT /* transport */, + bthh_connection_state_t /* state */) {}; BtifHhAdapterReady::TearDown(); } }; diff --git a/system/btif/test/btif_rc_test.cc b/system/btif/test/btif_rc_test.cc index 19c3a44ee4..9bd18300f6 100644 --- a/system/btif/test/btif_rc_test.cc +++ b/system/btif/test/btif_rc_test.cc @@ -78,6 +78,7 @@ void AvrcpService::RegisterVolChanged(const RawAddress& bdaddr) { namespace { const RawAddress kDeviceAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0x66}); +const uint8_t kRcHandle = 123; } // namespace void btif_av_clear_remote_suspend_flag(const A2dpType local_a2dp_type) {} @@ -451,8 +452,30 @@ class BtifTrackChangeCBTest : public BtifRcTest { }; TEST_F(BtifTrackChangeCBTest, handle_get_metadata_attr_response) { + // Setup an already connected device + btif_rc_cb.rc_multi_cb[0].rc_connected = true; + btif_rc_cb.rc_multi_cb[0].br_connected = false; + btif_rc_cb.rc_multi_cb[0].rc_handle = kRcHandle; + btif_rc_cb.rc_multi_cb[0].rc_features = {}; + btif_rc_cb.rc_multi_cb[0].rc_cover_art_psm = 0; + btif_rc_cb.rc_multi_cb[0].rc_state = BTRC_CONNECTION_STATE_CONNECTED; + btif_rc_cb.rc_multi_cb[0].rc_addr = kDeviceAddress; + btif_rc_cb.rc_multi_cb[0].rc_pending_play = 0; + btif_rc_cb.rc_multi_cb[0].rc_volume = 0; + btif_rc_cb.rc_multi_cb[0].rc_vol_label = 0; + btif_rc_cb.rc_multi_cb[0].rc_supported_event_list = nullptr; + btif_rc_cb.rc_multi_cb[0].rc_app_settings = {}; + btif_rc_cb.rc_multi_cb[0].rc_play_status_timer = nullptr; + btif_rc_cb.rc_multi_cb[0].rc_features_processed = false; + btif_rc_cb.rc_multi_cb[0].rc_playing_uid = 0; + btif_rc_cb.rc_multi_cb[0].rc_procedure_complete = false; + btif_rc_cb.rc_multi_cb[0].peer_ct_features = {}; + btif_rc_cb.rc_multi_cb[0].peer_tg_features = {}; + btif_rc_cb.rc_multi_cb[0].launch_cmd_pending = 0; + ASSERT_TRUE(btif_rc_get_device_by_handle(kRcHandle)); + tBTA_AV_META_MSG meta_msg = { - .rc_handle = 0, + .rc_handle = kRcHandle, .len = 0, .label = 0, .code{}, @@ -469,11 +492,6 @@ TEST_F(BtifTrackChangeCBTest, handle_get_metadata_attr_response) { .p_attrs = nullptr, }; - btif_rc_cb.rc_multi_cb[0].rc_handle = 0; - btif_rc_cb.rc_multi_cb[0].rc_addr = RawAddress::kEmpty; - btif_rc_cb.rc_multi_cb[0].rc_state = BTRC_CONNECTION_STATE_CONNECTED; - btif_rc_cb.rc_multi_cb[0].rc_connected = true; - handle_get_metadata_attr_response(&meta_msg, &rsp); ASSERT_EQ(1, get_func_call_count("osi_free_and_reset")); diff --git a/system/common/metrics.cc b/system/common/metrics.cc index f2016e2c2e..f2335e9f3e 100644 --- a/system/common/metrics.cc +++ b/system/common/metrics.cc @@ -611,11 +611,10 @@ void LogLinkLayerConnectionEvent(const RawAddress* address, hci_ble_event, cmd_status, reason_code, metric_id); if (ret < 0) { log::warn( - "failed to log status {}, reason {} from cmd {}, event {}, ble_event " - "{} for {}, handle {}, type {}, error {}", - loghex(cmd_status), loghex(reason_code), loghex(hci_cmd), - loghex(hci_event), loghex(hci_ble_event), *address, connection_handle, - loghex(link_type), ret); + "failed to log status 0x{:x}, reason 0x{:x} from cmd 0x{:x}, event " + "0x{:x}, ble_event 0x{:x} for {}, handle {}, type 0x{:x}, error {}", + cmd_status, reason_code, hci_cmd, hci_event, hci_ble_event, *address, + connection_handle, link_type, ret); } } @@ -623,7 +622,7 @@ void LogHciTimeoutEvent(uint32_t hci_cmd) { int ret = stats_write(BLUETOOTH_HCI_TIMEOUT_REPORTED, static_cast<int64_t>(hci_cmd)); if (ret < 0) { - log::warn("failed for opcode {}, error {}", loghex(hci_cmd), ret); + log::warn("failed for opcode 0x{:x}, error {}", hci_cmd, ret); } } @@ -633,10 +632,9 @@ void LogRemoteVersionInfo(uint16_t handle, uint8_t status, uint8_t version, version, manufacturer_name, subversion); if (ret < 0) { log::warn( - "failed for handle {}, status {}, version {}, manufacturer_name {}, " - "subversion {}, error {}", - handle, loghex(status), loghex(version), loghex(manufacturer_name), - loghex(subversion), ret); + "failed for handle {}, status 0x{:x}, version 0x{:x}, " + "manufacturer_name 0x{:x}, subversion 0x{:x}, error {}", + handle, status, version, manufacturer_name, subversion, ret); } } @@ -728,8 +726,8 @@ void LogReadRssiResult(const RawAddress& address, uint16_t handle, int ret = stats_write(BLUETOOTH_DEVICE_RSSI_REPORTED, bytes_field, handle, cmd_status, rssi, metric_id); if (ret < 0) { - log::warn("failed for {}, handle {}, status {}, rssi {} dBm, error {}", - address, handle, loghex(cmd_status), rssi, ret); + log::warn("failed for {}, handle {}, status 0x{:x}, rssi {} dBm, error {}", + address, handle, cmd_status, rssi, ret); } } @@ -750,9 +748,9 @@ void LogReadFailedContactCounterResult(const RawAddress& address, handle, cmd_status, failed_contact_counter, metric_id); if (ret < 0) { log::warn( - "failed for {}, handle {}, status {}, failed_contact_counter {} " + "failed for {}, handle {}, status 0x{:x}, failed_contact_counter {} " "packets, error {}", - address, handle, loghex(cmd_status), failed_contact_counter, ret); + address, handle, cmd_status, failed_contact_counter, ret); } } @@ -772,9 +770,9 @@ void LogReadTxPowerLevelResult(const RawAddress& address, uint16_t handle, handle, cmd_status, transmit_power_level, metric_id); if (ret < 0) { log::warn( - "failed for {}, handle {}, status {}, transmit_power_level {} packets, " - "error {}", - address, handle, loghex(cmd_status), transmit_power_level, ret); + "failed for {}, handle {}, status 0x{:x}, transmit_power_level {} " + "packets, error {}", + address, handle, cmd_status, transmit_power_level, ret); } } @@ -796,8 +794,9 @@ void LogSmpPairingEvent(const RawAddress& address, uint8_t smp_cmd, smp_cmd, direction, smp_fail_reason, metric_id); if (ret < 0) { log::warn( - "failed for {}, smp_cmd {}, direction {}, smp_fail_reason {}, error {}", - address, loghex(smp_cmd), direction, loghex(smp_fail_reason), ret); + "failed for {}, smp_cmd 0x{:x}, direction {}, smp_fail_reason 0x{:x}, " + "error {}", + address, smp_cmd, direction, smp_fail_reason, ret); } } @@ -818,10 +817,10 @@ void LogClassicPairingEvent(const RawAddress& address, uint16_t handle, uint32_t cmd_status, reason_code, event_value, metric_id); if (ret < 0) { log::warn( - "failed for {}, handle {}, hci_cmd {}, hci_event {}, cmd_status {}, " - "reason {}, event_value {}, error {}", - address, handle, loghex(hci_cmd), loghex(hci_event), loghex(cmd_status), - loghex(reason_code), event_value, ret); + "failed for {}, handle {}, hci_cmd 0x{:x}, hci_event 0x{:x}, " + "cmd_status 0x{:x}, reason 0x{:x}, event_value {}, error {}", + address, handle, hci_cmd, hci_event, cmd_status, reason_code, + event_value, ret); } } @@ -843,8 +842,9 @@ void LogSdpAttribute(const RawAddress& address, uint16_t protocol_uuid, stats_write(BLUETOOTH_SDP_ATTRIBUTE_REPORTED, obfuscated_id_field, protocol_uuid, attribute_id, attribute_field, metric_id); if (ret < 0) { - log::warn("failed for {}, protocol_uuid {}, attribute_id {}, error {}", - address, loghex(protocol_uuid), loghex(attribute_id), ret); + log::warn( + "failed for {}, protocol_uuid 0x{:x}, attribute_id 0x{:x}, error {}", + address, protocol_uuid, attribute_id, ret); } } @@ -923,8 +923,9 @@ void LogBluetoothHalCrashReason(const RawAddress& address, uint32_t error_code, int ret = stats_write(BLUETOOTH_HAL_CRASH_REASON_REPORTED, 0, obfuscated_id_field, error_code, vendor_error_code); if (ret < 0) { - log::warn("failed for {}, error_code {}, vendor_error_code {}, error {}", - address, loghex(error_code), loghex(vendor_error_code), ret); + log::warn( + "failed for {}, error_code 0x{:x}, vendor_error_code 0x{:x}, error {}", + address, error_code, vendor_error_code, ret); } } diff --git a/system/device/src/device_iot_config.cc b/system/device/src/device_iot_config.cc index a4123c6acf..2311281c37 100644 --- a/system/device/src/device_iot_config.cc +++ b/system/device/src/device_iot_config.cc @@ -22,7 +22,6 @@ #include <bluetooth/log.h> #include <ctype.h> -#include <stdio.h> #include <string.h> #include <time.h> #include <unistd.h> diff --git a/system/device/src/device_iot_config_int.cc b/system/device/src/device_iot_config_int.cc index bf038a74d9..f3d76acef2 100644 --- a/system/device/src/device_iot_config_int.cc +++ b/system/device/src/device_iot_config_int.cc @@ -21,7 +21,6 @@ #include "device_iot_config_int.h" #include <bluetooth/log.h> -#include <stdio.h> #include <string.h> #include <time.h> #include <unistd.h> @@ -37,7 +36,6 @@ #include "osi/include/alarm.h" #include "osi/include/config.h" #include "osi/include/future.h" -#include "osi/include/osi.h" #include "osi/include/properties.h" #include "types/raw_address.h" @@ -190,7 +188,7 @@ EXPORT_SYMBOL module_t device_iot_config_module = { .shut_down = device_iot_config_module_shut_down, .clean_up = device_iot_config_module_clean_up}; -void device_iot_config_write(uint16_t event, UNUSED_ATTR char* p_param) { +void device_iot_config_write(uint16_t event, char* /* p_param */) { if (!InitFlags::IsDeviceIotConfigLoggingEnabled()) return; log::assert_that(config != NULL, "assert failed: config != NULL"); @@ -295,7 +293,7 @@ bool device_iot_config_compare_key(const entry_t& first, } } -void device_iot_config_timer_save_cb(UNUSED_ATTR void* data) { +void device_iot_config_timer_save_cb(void* /* data */) { // Moving file I/O to btif context instead of timer callback because // it usually takes a lot of time to be completed, introducing // delays during A2DP playback causing blips or choppiness. diff --git a/system/device/src/device_iot_config_int.h b/system/device/src/device_iot_config_int.h index 0ae04af531..86e95df3cd 100644 --- a/system/device/src/device_iot_config_int.h +++ b/system/device/src/device_iot_config_int.h @@ -20,7 +20,6 @@ #pragma once #include "osi/include/config.h" -#include "osi/include/osi.h" #define PROPERTY_ENABLE_LOGGING \ "persist.bluetooth.device_iot_config.enablelogging" @@ -90,7 +89,7 @@ void device_iot_config_save_async(void); int device_iot_config_get_device_num(const config_t& config); void device_iot_config_restrict_device_num(config_t& config); bool device_iot_config_compare_key(const entry_t& first, const entry_t& second); -void device_iot_config_timer_save_cb(UNUSED_ATTR void* data); +void device_iot_config_timer_save_cb(void* /* data */); void device_iot_config_set_modified_time(); bool device_iot_config_is_factory_reset(void); void device_iot_config_delete_files(void); diff --git a/system/device/src/interop.cc b/system/device/src/interop.cc index 83ef4ad2b0..16f6428340 100644 --- a/system/device/src/interop.cc +++ b/system/device/src/interop.cc @@ -27,7 +27,6 @@ #include <fcntl.h> #include <hardware/bluetooth.h> #include <pthread.h> -#include <stdio.h> #include <string.h> // For memcmp #include <sys/stat.h> #include <unistd.h> diff --git a/system/embdrv/g722/g722_decode.cc b/system/embdrv/g722/g722_decode.cc index 4d812ac9a5..356e6db34b 100644 --- a/system/embdrv/g722/g722_decode.cc +++ b/system/embdrv/g722/g722_decode.cc @@ -23,7 +23,6 @@ /*! \file */ -#include <stdio.h> #include <string.h> #include <inttypes.h> #include <stdlib.h> diff --git a/system/embdrv/g722/g722_encode.cc b/system/embdrv/g722/g722_encode.cc index 817f5c00df..c68a4a19e3 100644 --- a/system/embdrv/g722/g722_encode.cc +++ b/system/embdrv/g722/g722_encode.cc @@ -25,7 +25,6 @@ /*! \file */ -#include <stdio.h> #include <string.h> #include <stdlib.h> diff --git a/system/embdrv/sbc/decoder/include/oi_codec_sbc_private.h b/system/embdrv/sbc/decoder/include/oi_codec_sbc_private.h index 7775670d11..7d4e5ec421 100644 --- a/system/embdrv/sbc/decoder/include/oi_codec_sbc_private.h +++ b/system/embdrv/sbc/decoder/include/oi_codec_sbc_private.h @@ -43,7 +43,6 @@ Function prototypes and macro definitions used internally by the codec. #endif #ifdef CODEC_DEBUG -#include <stdio.h> #define ERROR(x) \ do { \ printf x; \ diff --git a/system/embdrv/sbc/decoder/sbcdecoder_fuzzer.c b/system/embdrv/sbc/decoder/sbcdecoder_fuzzer.c index 9b23ccc475..e63d93ac35 100644 --- a/system/embdrv/sbc/decoder/sbcdecoder_fuzzer.c +++ b/system/embdrv/sbc/decoder/sbcdecoder_fuzzer.c @@ -1,5 +1,5 @@ #include <stddef.h> -#include <stdio.h> + #include "oi_codec_sbc.h" #define CODEC_DATA_WORDS(numChannels, numBuffers) \ diff --git a/system/embdrv/sbc/decoder/srce/decoder-private.c b/system/embdrv/sbc/decoder/srce/decoder-private.c index cba8e96dbc..47ddb72d0b 100644 --- a/system/embdrv/sbc/decoder/srce/decoder-private.c +++ b/system/embdrv/sbc/decoder/srce/decoder-private.c @@ -34,7 +34,6 @@ This file drives SBC decoding. @{ */ -#include <stdio.h> #include "oi_bitstream.h" #include "oi_codec_sbc_private.h" diff --git a/system/embdrv/sbc/decoder/srce/framing.c b/system/embdrv/sbc/decoder/srce/framing.c index 7c1c08775e..d581bdb6ef 100644 --- a/system/embdrv/sbc/decoder/srce/framing.c +++ b/system/embdrv/sbc/decoder/srce/framing.c @@ -98,7 +98,6 @@ const OI_BYTE crc8_narrow[256] = { #endif #if defined(OI_DEBUG) || defined(PRINT_SAMPLES) || defined(PRINT_SCALEFACTORS) -#include <stdio.h> #endif #ifdef USE_WIDE_CRC diff --git a/system/gd/Android.bp b/system/gd/Android.bp index 68e339cbd7..7fa3a5c1fe 100644 --- a/system/gd/Android.bp +++ b/system/gd/Android.bp @@ -473,6 +473,7 @@ cc_test { "BluetoothGeneratedDumpsysTestData_h", ], static_libs: [ + "libbase", "libbluetooth-protos", "libbluetooth-types", "libbluetooth_crypto_toolbox", @@ -496,7 +497,6 @@ cc_test { ], shared_libs: [ "libPlatformProperties", - "libbase", "libcrypto", "server_configurable_flags", ], diff --git a/system/gd/common/contextual_callback.h b/system/gd/common/contextual_callback.h index 12f9b47564..a5f565c395 100644 --- a/system/gd/common/contextual_callback.h +++ b/system/gd/common/contextual_callback.h @@ -48,14 +48,6 @@ class ContextualOnceCallback<R(Args...)> { return context_ && callback_; } - void Invoke(Args... args) { - context_->Post(common::BindOnce(std::move(callback_), std::forward<Args>(args)...)); - } - - bool IsEmpty() { - return context_ == nullptr; - } - private: common::OnceCallback<R(Args...)> callback_; IPostableContext* context_; @@ -83,21 +75,13 @@ class ContextualCallback<R(Args...)> { ContextualCallback& operator=(ContextualCallback&&) noexcept = default; void operator()(Args... args) { - context_->Post(common::BindOnce(std::move(callback_), std::forward<Args>(args)...)); + context_->Post(common::BindOnce(callback_, std::forward<Args>(args)...)); } operator bool() const { return context_ && callback_; } - void Invoke(Args... args) { - context_->Post(common::BindOnce(callback_, std::forward<Args>(args)...)); - } - - bool IsEmpty() { - return context_ == nullptr; - } - private: common::Callback<R(Args...)> callback_; IPostableContext* context_; diff --git a/system/gd/dumpsys/bundler/bundler.cc b/system/gd/dumpsys/bundler/bundler.cc index f2e6559a37..1f688bb93d 100644 --- a/system/gd/dumpsys/bundler/bundler.cc +++ b/system/gd/dumpsys/bundler/bundler.cc @@ -16,7 +16,6 @@ #include "bundler.h" #include <assert.h> -#include <stdio.h> #include <stdlib.h> #include <unistd.h> diff --git a/system/gd/dumpsys/filter.cc b/system/gd/dumpsys/filter.cc index 08e20f92be..8b51b5fda8 100644 --- a/system/gd/dumpsys/filter.cc +++ b/system/gd/dumpsys/filter.cc @@ -20,10 +20,6 @@ #include <memory> -#include "common/init_flags.h" -#include "dumpsys/internal/filter_internal.h" -#include "os/log.h" - using namespace bluetooth; using namespace dumpsys; @@ -35,8 +31,7 @@ class Filter { virtual void FilterInPlace(char* dumpsys_data) = 0; - static std::unique_ptr<Filter> Factory( - dumpsys::FilterType filter_type, const dumpsys::ReflectionSchema& reflection_schema); + static std::unique_ptr<Filter> Factory(const dumpsys::ReflectionSchema& reflection_schema); protected: /** @@ -88,124 +83,12 @@ class DeveloperPrivacyFilter : public Filter { } }; -class UserPrivacyFilter : public Filter { - public: - UserPrivacyFilter(const dumpsys::ReflectionSchema& reflection_schema) : Filter(reflection_schema) {} - void FilterInPlace(char* dumpsys_data) override; - - protected: - bool FilterField(const reflection::Field* field, flatbuffers::Table* table) override; - void FilterObject(const reflection::Object* object, flatbuffers::Table* table) override; - void FilterTable(const reflection::Schema* schema, flatbuffers::Table* table) override; -}; - -bool UserPrivacyFilter::FilterField(const reflection::Field* field, flatbuffers::Table* table) { - log::assert_that(field != nullptr, "assert failed: field != nullptr"); - log::assert_that(table != nullptr, "assert failed: table != nullptr"); - internal::PrivacyLevel privacy_level = internal::FindFieldPrivacyLevel(*field); - - const auto type = static_cast<flatbuffers::BaseType>(field->type()->base_type()); - switch (type) { - case flatbuffers::BASE_TYPE_INT: - return internal::FilterTypeInteger(*field, table, privacy_level); - break; - case flatbuffers::BASE_TYPE_FLOAT: - return internal::FilterTypeFloat(*field, table, privacy_level); - break; - case flatbuffers::BASE_TYPE_STRING: - return internal::FilterTypeString(*field, table, privacy_level); - break; - case flatbuffers::BASE_TYPE_STRUCT: - return internal::FilterTypeStruct(*field, table, privacy_level); - break; - case flatbuffers::BASE_TYPE_BOOL: - return internal::FilterTypeBool(*field, table, privacy_level); - break; - case flatbuffers::BASE_TYPE_LONG: - return internal::FilterTypeLong(*field, table, privacy_level); - break; - default: - log::warn("Unsupported base type:{}", internal::FlatbufferTypeText(type)); - break; - } - return false; -} - -void UserPrivacyFilter::FilterObject(const reflection::Object* object, flatbuffers::Table* table) { - log::assert_that(object != nullptr, "assert failed: object != nullptr"); - if (table == nullptr) { - return; // table data is not populated - } - for (auto it = object->fields()->cbegin(); it != object->fields()->cend(); ++it) { - if (!FilterField(*it, table)) { - log::error("Unable to filter field from an object when it's expected it will work"); - }; - } -} - -void UserPrivacyFilter::FilterTable(const reflection::Schema* schema, flatbuffers::Table* table) { - if (schema == nullptr) { - log::warn("schema is nullptr...probably ok"); - return; - } - - const reflection::Object* object = schema->root_table(); - if (object == nullptr) { - log::warn("reflection object is nullptr...is ok ?"); - return; - } - - if (table == nullptr) { - return; // table not populated - } - - for (auto it = object->fields()->cbegin(); it != object->fields()->cend(); ++it) { - if (FilterField(*it, table)) { - continue; // Field successfully filtered - } - // Get the index of this complex non-string object from the schema which is - // also the same index into the data table. - int32_t index = it->type()->index(); - log::assert_that(index != -1, "assert failed: index != -1"); - - flatbuffers::Table* sub_table = table->GetPointer<flatbuffers::Table*>(it->offset()); - const reflection::Schema* sub_schema = - reflection_schema_.FindInReflectionSchema(schema->objects()->Get(index)->name()->str()); - - if (sub_schema != nullptr) { - FilterTable(sub_schema, sub_table); // Top level schema - } else { - // Leaf node schema - const flatbuffers::String* name = schema->objects()->Get(index)->name(); - const reflection::Object* sub_object = internal::FindReflectionObject(schema->objects(), name); - if (sub_object != nullptr) { - FilterObject(sub_object, sub_table); - } else { - log::error("Unable to find reflection sub object:{}", name->c_str()); - } - } - } -} - -void UserPrivacyFilter::FilterInPlace(char* dumpsys_data) { - log::assert_that(dumpsys_data != nullptr, "assert failed: dumpsys_data != nullptr"); - const reflection::Schema* root_schema = reflection_schema_.FindInReflectionSchema(reflection_schema_.GetRootName()); - flatbuffers::Table* table = const_cast<flatbuffers::Table*>(flatbuffers::GetRoot<flatbuffers::Table>(dumpsys_data)); - FilterTable(root_schema, table); -} - -std::unique_ptr<Filter> Filter::Factory( - dumpsys::FilterType filter_type, const dumpsys::ReflectionSchema& reflection_schema) { - switch (filter_type) { - case dumpsys::FilterType::AS_DEVELOPER: - return std::make_unique<DeveloperPrivacyFilter>(reflection_schema); - default: - return std::make_unique<UserPrivacyFilter>(reflection_schema); - } +std::unique_ptr<Filter> Filter::Factory(const dumpsys::ReflectionSchema& reflection_schema) { + return std::make_unique<DeveloperPrivacyFilter>(reflection_schema); } -void bluetooth::dumpsys::FilterInPlace( - FilterType filter_type, const ReflectionSchema& reflection_schema, std::string* dumpsys_data) { - auto filter = Filter::Factory(filter_type, reflection_schema); +void bluetooth::dumpsys::FilterSchema( + const ReflectionSchema& reflection_schema, std::string* dumpsys_data) { + auto filter = Filter::Factory(reflection_schema); filter->FilterInPlace(dumpsys_data->data()); } diff --git a/system/gd/dumpsys/filter.h b/system/gd/dumpsys/filter.h index a572c403db..02c62e3d16 100644 --- a/system/gd/dumpsys/filter.h +++ b/system/gd/dumpsys/filter.h @@ -20,9 +20,7 @@ namespace bluetooth { namespace dumpsys { -enum FilterType { AS_USER = 0, AS_DEVELOPER }; - -void FilterInPlace(FilterType filter_type, const ReflectionSchema& reflection_schema, std::string* dumpsys_data); +void FilterSchema(const ReflectionSchema& reflection_schema, std::string* dumpsys_data); } // namespace dumpsys } // namespace bluetooth diff --git a/system/gd/dumpsys/filter_test.cc b/system/gd/dumpsys/filter_test.cc index 89a98f8747..5b555135cf 100644 --- a/system/gd/dumpsys/filter_test.cc +++ b/system/gd/dumpsys/filter_test.cc @@ -29,10 +29,10 @@ #include "test_data/qux.h" #include "test_data/root.h" -namespace testing { - using namespace bluetooth; +namespace testing { + class DumpsysFilterTest : public Test { protected: void SetUp() override { @@ -87,7 +87,7 @@ TEST_F(DumpsysFilterTest, filter_as_developer) { std::string dumpsys_data = PopulateTestSchema(); dumpsys::ReflectionSchema reflection_schema(testing::GetBundledSchemaData()); - dumpsys::FilterInPlace(dumpsys::FilterType::AS_DEVELOPER, reflection_schema, &dumpsys_data); + dumpsys::FilterSchema(reflection_schema, &dumpsys_data); const testing::DumpsysTestDataRoot* data_root = GetDumpsysTestDataRoot(dumpsys_data.data()); @@ -118,63 +118,4 @@ TEST_F(DumpsysFilterTest, filter_as_developer) { ASSERT_STREQ("123.456", foo->foo_float_string()->c_str()); } -TEST_F(DumpsysFilterTest, filter_as_user) { - std::string dumpsys_data = PopulateTestSchema(); - dumpsys::ReflectionSchema reflection_schema(testing::GetBundledSchemaData()); - - dumpsys::FilterInPlace(dumpsys::FilterType::AS_USER, reflection_schema, &dumpsys_data); - - [[maybe_unused]] const testing::DumpsysTestDataRoot* data_root = GetDumpsysTestDataRoot(dumpsys_data.data()); - - ASSERT_TRUE(data_root->string_private() == nullptr); - ASSERT_TRUE(data_root->string_opaque()->str() == "*************"); - ASSERT_TRUE(data_root->string_anonymized()->str() != "String anonymized"); - ASSERT_TRUE(data_root->string_any()->str() == "String any"); - - ASSERT_TRUE(data_root->int_private() == 0); - ASSERT_TRUE(data_root->int_opaque() == 0); - ASSERT_TRUE(data_root->int_anonymized() != 789); - ASSERT_TRUE(data_root->int_any() == 0xabc); - - // bar - ASSERT_EQ(nullptr, data_root->bar_module_data()); - - // baz - const testing::BazTestSchema* baz = data_root->baz_module_data(); - ASSERT_NE(nullptr, baz); - - const testing::BazSubTableAny* baz_any = baz->sub_table_any(); - ASSERT_NE(nullptr, baz_any); - ASSERT_EQ(nullptr, baz->sub_table_anonymized()); - ASSERT_EQ(nullptr, baz->sub_table_opaque()); - ASSERT_EQ(nullptr, baz->sub_table_private()); - - ASSERT_EQ(0, baz_any->subtable_int_private()); // 1 - ASSERT_EQ(0, baz_any->subtable_int_opaque()); // 2 - ASSERT_NE(3, baz_any->subtable_int_anonymized()); // 3 - ASSERT_EQ(4, baz_any->subtable_int_any()); // 4 - ASSERT_STREQ("Baz Subtable Any", baz_any->subtable_string_any()->c_str()); - - // foo - const testing::FooTestSchema* foo = data_root->foo_module_data(); - ASSERT_EQ(0, foo->foo_int_private()); - ASSERT_EQ(0, foo->foo_int_opaque()); - ASSERT_NE(123, foo->foo_int_anonymized()); - ASSERT_EQ(123, foo->foo_int_any()); - ASSERT_STREQ("123", foo->foo_int_string()->c_str()); - ASSERT_FLOAT_EQ(0.0, foo->foo_float_private()); - ASSERT_FLOAT_EQ(0.0, foo->foo_float_opaque()); - ASSERT_THAT(foo->foo_float_anonymized(), Not(FloatEq(123.456))); - ASSERT_FLOAT_EQ(123.456, foo->foo_float_any()); - ASSERT_STREQ("123.456", foo->foo_float_string()->c_str()); - - // qux - const testing::QuxTestSchema* qux = data_root->qux_module_data(); - ASSERT_EQ(0, qux->qux_int_private()); - ASSERT_EQ(0, qux->qux_int_opaque()); - ASSERT_NE(789, qux->qux_int_anonymized()); - ASSERT_EQ(0xabc, qux->qux_int_any()); - ASSERT_STREQ("Qux Module String", qux->qux_string_name()->c_str()); -} - } // namespace testing diff --git a/system/gd/fuzz/helpers.h b/system/gd/fuzz/helpers.h index 77e9a38b33..f4ca162730 100644 --- a/system/gd/fuzz/helpers.h +++ b/system/gd/fuzz/helpers.h @@ -43,8 +43,8 @@ void InvokeIfValid(common::ContextualOnceCallback<void(TView)> callback, std::ve if (!packet.IsValid()) { return; } - if (!callback.IsEmpty()) { - callback.Invoke(packet); + if (callback) { + callback(packet); } } @@ -54,8 +54,8 @@ void InvokeIfValid(common::ContextualCallback<void(TView)> callback, std::vector if (!packet.IsValid()) { return; } - if (!callback.IsEmpty()) { - callback.Invoke(packet); + if (callback) { + callback(packet); } } diff --git a/system/gd/hal/snoop_logger_socket.cc b/system/gd/hal/snoop_logger_socket.cc index c3a912ebaa..8b9db3dbc9 100644 --- a/system/gd/hal/snoop_logger_socket.cc +++ b/system/gd/hal/snoop_logger_socket.cc @@ -24,7 +24,6 @@ #include <netinet/in.h> #include <pthread.h> #include <stdbool.h> -#include <stdio.h> #include <string.h> #include <sys/prctl.h> #include <sys/socket.h> @@ -274,7 +273,7 @@ int SnoopLoggerSocket::NotifySocketListener() { } void SnoopLoggerSocket::SafeCloseSocket(int& fd) { - log::debug("{}", (fd)); + log::debug("{}", fd); if (fd != -1) { syscall_if_->Close(fd); syscall_if_->FDClr(fd, &save_sock_fds_); diff --git a/system/gd/hal/snoop_logger_socket_thread.cc b/system/gd/hal/snoop_logger_socket_thread.cc index 472397589e..3ea45bbaa3 100644 --- a/system/gd/hal/snoop_logger_socket_thread.cc +++ b/system/gd/hal/snoop_logger_socket_thread.cc @@ -24,7 +24,6 @@ #include <netinet/in.h> #include <pthread.h> #include <stdbool.h> -#include <stdio.h> #include <string.h> #include <sys/prctl.h> #include <sys/socket.h> diff --git a/system/gd/hci/acl_manager/acl_scheduler.cc b/system/gd/hci/acl_manager/acl_scheduler.cc index f1190b9571..4f7afec916 100644 --- a/system/gd/hci/acl_manager/acl_scheduler.cc +++ b/system/gd/hci/acl_manager/acl_scheduler.cc @@ -61,7 +61,7 @@ struct AclScheduler::impl { if (entry != nullptr && entry->address == address) { // If so, clear the current entry and advance the queue outgoing_entry_.reset(); - handle_outgoing_connection.Invoke(); + handle_outgoing_connection(); try_dequeue_next_operation(); return; } @@ -70,9 +70,9 @@ struct AclScheduler::impl { // Otherwise check if it's an incoming request and advance the queue if so if (incoming_connecting_address_set_.find(address) != incoming_connecting_address_set_.end()) { incoming_connecting_address_set_.erase(address); - handle_incoming_connection.Invoke(); + handle_incoming_connection(); } else { - handle_unknown_connection.Invoke(set_of_incoming_connecting_addresses()); + handle_unknown_connection(set_of_incoming_connecting_addresses()); } try_dequeue_next_operation(); } @@ -100,8 +100,8 @@ struct AclScheduler::impl { auto entry_ptr = std::get_if<AclCreateConnectionQueueEntry>(&entry); return entry_ptr != nullptr && entry_ptr->address == address; }, - [&]() { cancel_connection.Invoke(); }, - [&](auto /* entry */) { cancel_connection_completed.Invoke(); }); + [&]() { cancel_connection(); }, + [&](auto /* entry */) { cancel_connection_completed(); }); if (!ok) { log::error("Attempted to cancel connection to {} that does not exist", address); } @@ -147,8 +147,8 @@ struct AclScheduler::impl { auto entry_ptr = std::get_if<RemoteNameRequestQueueEntry>(&entry); return entry_ptr != nullptr && entry_ptr->address == address; }, - [&]() { cancel_request.Invoke(); }, - [](auto entry) { std::get<RemoteNameRequestQueueEntry>(entry).callback_when_cancelled.Invoke(); }); + [&]() { cancel_request(); }, + [](auto entry) { std::get<RemoteNameRequestQueueEntry>(entry).callback_when_cancelled(); }); if (!ok) { log::error("Attempted to cancel remote name request to {} that does not exist", address); } @@ -168,7 +168,7 @@ struct AclScheduler::impl { log::info("Pending connections is not empty; so sending next connection"); auto entry = std::move(pending_outgoing_operations_.front()); pending_outgoing_operations_.pop_front(); - std::visit([](auto&& variant) { variant.callback.Invoke(); }, entry); + std::visit([](auto&& variant) { variant.callback(); }, entry); outgoing_entry_ = std::move(entry); } } diff --git a/system/gd/hci/acl_manager/classic_impl_test.cc b/system/gd/hci/acl_manager/classic_impl_test.cc index 7dcef4be38..e59be364e0 100644 --- a/system/gd/hci/acl_manager/classic_impl_test.cc +++ b/system/gd/hci/acl_manager/classic_impl_test.cc @@ -129,14 +129,14 @@ class MockAclScheduler : public AclScheduler { common::ContextualOnceCallback<void()> handle_incoming_connection, common::ContextualOnceCallback<void(std::string)> handle_unknown_connection) override { if (handle_outgoing_connection_) { - handle_outgoing_connection.Invoke(); + handle_outgoing_connection(); return; } if (handle_incoming_connection_) { - handle_incoming_connection.Invoke(); + handle_incoming_connection(); } else { - handle_unknown_connection.Invoke("set_of_incoming_connecting_addresses()"); + handle_unknown_connection("set_of_incoming_connecting_addresses()"); } } }; diff --git a/system/gd/hci/acl_manager/le_acl_connection_test.cc b/system/gd/hci/acl_manager/le_acl_connection_test.cc index 2a128a535c..0a0a69990d 100644 --- a/system/gd/hci/acl_manager/le_acl_connection_test.cc +++ b/system/gd/hci/acl_manager/le_acl_connection_test.cc @@ -235,7 +235,7 @@ TEST_F(LeAclConnectionTest, LeSubrateRequest_success) { hci::EventView event = hci::EventView::Create(GetPacketView(std::move(status_builder))); hci::CommandStatusView command_status = hci::CommandStatusView::Create(event); auto on_status = le_acl_connection_interface_.DequeueStatusCallback(); - on_status.Invoke(command_status); + on_status(command_status); sync_handler(); } @@ -256,7 +256,7 @@ TEST_F(LeAclConnectionTest, LeSubrateRequest_error) { hci::EventView event = hci::EventView::Create(GetPacketView(std::move(status_builder))); hci::CommandStatusView command_status = hci::CommandStatusView::Create(event); auto on_status = le_acl_connection_interface_.DequeueStatusCallback(); - on_status.Invoke(std::move(command_status)); + on_status(std::move(command_status)); sync_handler(); } diff --git a/system/gd/hci/acl_manager/le_impl_test.cc b/system/gd/hci/acl_manager/le_impl_test.cc index fd79fbbf90..092db3e011 100644 --- a/system/gd/hci/acl_manager/le_impl_test.cc +++ b/system/gd/hci/acl_manager/le_impl_test.cc @@ -196,7 +196,7 @@ class TestController : public Controller { } void SendCompletedAclPacketsCallback(uint16_t handle, uint16_t credits) { - acl_credits_callback_.Invoke(handle, credits); + acl_credits_callback_(handle, credits); } void UnregisterCompletedAclPacketsCallback() { diff --git a/system/gd/hci/acl_manager/round_robin_scheduler_test.cc b/system/gd/hci/acl_manager/round_robin_scheduler_test.cc index 256e49180a..0683b46683 100644 --- a/system/gd/hci/acl_manager/round_robin_scheduler_test.cc +++ b/system/gd/hci/acl_manager/round_robin_scheduler_test.cc @@ -60,7 +60,7 @@ class TestController : public Controller { } void SendCompletedAclPacketsCallback(uint16_t handle, uint16_t credits) { - acl_credits_callback_.Invoke(handle, credits); + acl_credits_callback_(handle, credits); } void UnregisterCompletedAclPacketsCallback() { diff --git a/system/gd/hci/acl_manager_test.cc b/system/gd/hci/acl_manager_test.cc index 1f3e11b729..ac6ebc0a2c 100644 --- a/system/gd/hci/acl_manager_test.cc +++ b/system/gd/hci/acl_manager_test.cc @@ -95,7 +95,7 @@ class TestController : public testing::MockController { } void CompletePackets(uint16_t handle, uint16_t packets) { - acl_cb_.Invoke(handle, packets); + acl_cb_(handle, packets); } uint16_t acl_buffer_length_ = 1024; diff --git a/system/gd/hci/controller.cc b/system/gd/hci/controller.cc index 27e7f3e47c..b53b232119 100644 --- a/system/gd/hci/controller.cc +++ b/system/gd/hci/controller.cc @@ -229,7 +229,7 @@ struct Controller::impl { } void NumberOfCompletedPackets(EventView event) { - if (acl_credits_callback_.IsEmpty()) { + if (!acl_credits_callback_) { log::warn("Received event when AclManager is not listening"); return; } @@ -238,40 +238,40 @@ struct Controller::impl { for (auto completed_packets : complete_view.GetCompletedPackets()) { uint16_t handle = completed_packets.connection_handle_; uint16_t credits = completed_packets.host_num_of_completed_packets_; - acl_credits_callback_.Invoke(handle, credits); - if (!acl_monitor_credits_callback_.IsEmpty()) { - acl_monitor_credits_callback_.Invoke(handle, credits); + acl_credits_callback_(handle, credits); + if (acl_monitor_credits_callback_) { + acl_monitor_credits_callback_(handle, credits); } } } void register_completed_acl_packets_callback(CompletedAclPacketsCallback callback) { - ASSERT(acl_credits_callback_.IsEmpty()); + ASSERT(!acl_credits_callback_); acl_credits_callback_ = callback; } void unregister_completed_acl_packets_callback() { - ASSERT(!acl_credits_callback_.IsEmpty()); + ASSERT(acl_credits_callback_); acl_credits_callback_ = {}; } void register_completed_monitor_acl_packets_callback(CompletedAclPacketsCallback callback) { - ASSERT(acl_monitor_credits_callback_.IsEmpty()); + ASSERT(!acl_monitor_credits_callback_); acl_monitor_credits_callback_ = callback; } void unregister_completed_monitor_acl_packets_callback() { - ASSERT(!acl_monitor_credits_callback_.IsEmpty()); + ASSERT(acl_monitor_credits_callback_); acl_monitor_credits_callback_ = {}; } void register_monitor_completed_acl_packets_callback(CompletedAclPacketsCallback callback) { - ASSERT(acl_monitor_credits_callback_.IsEmpty()); + ASSERT(!acl_monitor_credits_callback_); acl_monitor_credits_callback_ = callback; } void unregister_monitor_completed_acl_packets_callback() { - ASSERT(!acl_monitor_credits_callback_.IsEmpty()); + ASSERT(acl_monitor_credits_callback_); acl_monitor_credits_callback_ = {}; } @@ -770,7 +770,7 @@ struct Controller::impl { auto status_view = LeRandCompleteView::Create(view); ASSERT(status_view.IsValid()); ASSERT(status_view.GetStatus() == ErrorCode::SUCCESS); - std::move(cb).Invoke(status_view.GetRandomNumber()); + std::move(cb)(status_view.GetRandomNumber()); } void set_event_filter(std::unique_ptr<SetEventFilterBuilder> packet) { diff --git a/system/gd/hci/controller_test.cc b/system/gd/hci/controller_test.cc index ca9cefa77c..e4a8075ff4 100644 --- a/system/gd/hci/controller_test.cc +++ b/system/gd/hci/controller_test.cc @@ -255,7 +255,7 @@ class HciLayerFakeForController : public HciLayerFake { ASSERT_TRUE(event.IsValid()); CommandCompleteView command_complete = CommandCompleteView::Create(event); ASSERT_TRUE(command_complete.IsValid()); - on_complete.Invoke(std::move(command_complete)); + on_complete(std::move(command_complete)); } void IncomingCredit() { diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index 7a7f0a0b7e..8f36f2c891 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -778,7 +778,7 @@ struct DistanceMeasurementManager::impl { uint16_t connection_handle = acl_manager_->HACK_GetLeHandle(address); log::debug( "address:{}, connection_handle 0x{:04x}, size:{}", - address.ToString().c_str(), + address.ToString(), connection_handle, raw_data.size()); @@ -832,7 +832,7 @@ struct DistanceMeasurementManager::impl { RangingHeader ranging_header, PacketViewForRecombination& segment_data, uint16_t connection_handle) { - log::debug("Data size {}, Ranging_header {}", segment_data.size(), ranging_header.ToString().c_str()); + log::debug("Data size {}, Ranging_header {}", segment_data.size(), ranging_header.ToString()); auto procedure_data = get_procedure_data_for_ras(connection_handle, ranging_header.ranging_counter_); if (procedure_data == nullptr) { @@ -886,9 +886,7 @@ struct DistanceMeasurementManager::impl { after = LeCsMode0InitatorData::Parse(&tone_data, parse_index); if (after == parse_index) { log::warn( - "Error invalid mode {} data, role:{}", - step_mode.mode_type_, - CsRoleText(role).c_str()); + "Error invalid mode {} data, role:{}", step_mode.mode_type_, CsRoleText(role)); return; } parse_index = after; @@ -897,9 +895,7 @@ struct DistanceMeasurementManager::impl { after = LeCsMode0ReflectorData::Parse(&tone_data, parse_index); if (after == parse_index) { log::warn( - "Error invalid mode {} data, role:{}", - step_mode.mode_type_, - CsRoleText(role).c_str()); + "Error invalid mode {} data, role:{}", step_mode.mode_type_, CsRoleText(role)); return; } } @@ -928,9 +924,7 @@ struct DistanceMeasurementManager::impl { after = LeCsMode2Data::Parse(&tone_data, packet_bytes_view.begin()); if (after == packet_bytes_view.begin()) { log::warn( - "Error invalid mode {} data, role:{}", - step_mode.mode_type_, - CsRoleText(role).c_str()); + "Error invalid mode {} data, role:{}", step_mode.mode_type_, CsRoleText(role)); return; } parse_index += data_len; diff --git a/system/gd/hci/fuzz/fuzz_hci_layer.cc b/system/gd/hci/fuzz/fuzz_hci_layer.cc index d2a3ddaacb..cb3862cc70 100644 --- a/system/gd/hci/fuzz/fuzz_hci_layer.cc +++ b/system/gd/hci/fuzz/fuzz_hci_layer.cc @@ -181,8 +181,8 @@ void FuzzHciLayer::injectAclEvent(std::vector<uint8_t> data) { } void FuzzHciLayer::injectAclDisconnect(FuzzedDataProvider& fdp) { - if (!acl_on_disconnect_.IsEmpty()) { - acl_on_disconnect_.Invoke( + if (acl_on_disconnect_) { + acl_on_disconnect_( fdp.ConsumeIntegral<uint16_t>(), static_cast<hci::ErrorCode>(fdp.ConsumeIntegral<uint8_t>())); } @@ -193,8 +193,8 @@ void FuzzHciLayer::injectLeAclEvent(std::vector<uint8_t> data) { } void FuzzHciLayer::injectLeAclDisconnect(FuzzedDataProvider& fdp) { - if (!le_acl_on_disconnect_.IsEmpty()) { - le_acl_on_disconnect_.Invoke( + if (le_acl_on_disconnect_) { + le_acl_on_disconnect_( fdp.ConsumeIntegral<uint16_t>(), static_cast<hci::ErrorCode>(fdp.ConsumeIntegral<uint8_t>())); } diff --git a/system/gd/hci/hci_layer.cc b/system/gd/hci/hci_layer.cc index d6f326cb2c..aa41eb0867 100644 --- a/system/gd/hci/hci_layer.cc +++ b/system/gd/hci/hci_layer.cc @@ -228,7 +228,7 @@ struct HciLayer::impl { CommandCompleteView::Create(EventView::Create(PacketView<kLittleEndian>(complete))); log::assert_that( command_complete_view.IsValid(), "assert failed: command_complete_view.IsValid()"); - command_queue_.front().GetCallback<CommandCompleteView>()->Invoke(command_complete_view); + (*command_queue_.front().GetCallback<CommandCompleteView>())(command_complete_view); } else { log::assert_that( command_queue_.front().waiting_for_status_ == is_status, @@ -236,7 +236,7 @@ struct HciLayer::impl { OpCodeText(op_code), logging_id); - command_queue_.front().GetCallback<TResponse>()->Invoke(std::move(response_view)); + (*command_queue_.front().GetCallback<TResponse>())(std::move(response_view)); } #ifdef TARGET_FLOSS @@ -329,7 +329,7 @@ struct HciLayer::impl { "Can not register handler for {}", EventCodeText(EventCode::LE_META_EVENT)); // Allow GD Cert tests to register for CONNECTION_REQUEST - if (event == EventCode::CONNECTION_REQUEST && module_.on_acl_connection_request_.IsEmpty()) { + if (event == EventCode::CONNECTION_REQUEST && !module_.on_acl_connection_request_) { log::info("Registering test for CONNECTION_REQUEST, since there's no ACL"); event_handlers_.erase(event); } @@ -444,7 +444,7 @@ struct HciLayer::impl { if (event_handlers_.find(event_code) == event_handlers_.end()) { log::warn("Unhandled event of type {}", EventCodeText(event_code)); } else { - event_handlers_[event_code].Invoke(event); + event_handlers_[event_code](event); } } } @@ -471,7 +471,7 @@ struct HciLayer::impl { log::warn("Unhandled le subevent of type {}", SubeventCodeText(subevent_code)); return; } - subevent_handlers_[subevent_code].Invoke(meta_event_view); + subevent_handlers_[subevent_code](meta_event_view); } hal::HciHal* hal_; @@ -605,18 +605,18 @@ void HciLayer::on_connection_request(EventView event_view) { ConnectionRequestLinkType link_type = view.GetLinkType(); switch (link_type) { case ConnectionRequestLinkType::ACL: - if (on_acl_connection_request_.IsEmpty()) { + if (!on_acl_connection_request_) { log::warn("No callback registered for ACL connection requests."); } else { - on_acl_connection_request_.Invoke(address, cod); + on_acl_connection_request_(address, cod); } break; case ConnectionRequestLinkType::SCO: case ConnectionRequestLinkType::ESCO: - if (on_sco_connection_request_.IsEmpty()) { + if (!on_sco_connection_request_) { log::warn("No callback registered for SCO connection requests."); } else { - on_sco_connection_request_.Invoke(address, cod, link_type); + on_sco_connection_request_(address, cod, link_type); } break; } @@ -625,7 +625,7 @@ void HciLayer::on_connection_request(EventView event_view) { void HciLayer::Disconnect(uint16_t handle, ErrorCode reason) { std::unique_lock<std::mutex> lock(callback_handlers_guard_); for (auto callback : disconnect_handlers_) { - callback.Invoke(handle, reason); + callback(handle, reason); } } @@ -649,7 +649,7 @@ void HciLayer::ReadRemoteVersion( hci::ErrorCode hci_status, uint16_t handle, uint8_t version, uint16_t manufacturer_name, uint16_t sub_version) { std::unique_lock<std::mutex> lock(callback_handlers_guard_); for (auto callback : read_remote_version_handlers_) { - callback.Invoke(hci_status, handle, version, manufacturer_name, sub_version); + callback(hci_status, handle, version, manufacturer_name, sub_version); } } diff --git a/system/gd/hci/hci_layer_fake.cc b/system/gd/hci/hci_layer_fake.cc index a47ee4d387..ba3946a755 100644 --- a/system/gd/hci/hci_layer_fake.cc +++ b/system/gd/hci/hci_layer_fake.cc @@ -148,7 +148,7 @@ void HciLayerFake::IncomingEvent(std::unique_ptr<EventBuilder> event_builder) { CommandStatusCallback(event); } else { ASSERT_NE(registered_events_.find(event_code), registered_events_.end()) << EventCodeText(event_code); - registered_events_[event_code].Invoke(event); + registered_events_[event_code](event); } } @@ -159,20 +159,20 @@ void HciLayerFake::IncomingLeMetaEvent(std::unique_ptr<LeMetaEventBuilder> event ASSERT_TRUE(meta_event_view.IsValid()); SubeventCode subevent_code = meta_event_view.GetSubeventCode(); ASSERT_TRUE(registered_le_events_.find(subevent_code) != registered_le_events_.end()); - registered_le_events_[subevent_code].Invoke(meta_event_view); + registered_le_events_[subevent_code](meta_event_view); } void HciLayerFake::CommandCompleteCallback(EventView event) { CommandCompleteView complete_view = CommandCompleteView::Create(event); ASSERT_TRUE(complete_view.IsValid()); - std::move(command_complete_callbacks.front()).Invoke(complete_view); + std::move(command_complete_callbacks.front())(complete_view); command_complete_callbacks.pop_front(); } void HciLayerFake::CommandStatusCallback(EventView event) { CommandStatusView status_view = CommandStatusView::Create(event); ASSERT_TRUE(status_view.IsValid()); - std::move(command_status_callbacks.front()).Invoke(status_view); + std::move(command_status_callbacks.front())(status_view); command_status_callbacks.pop_front(); } diff --git a/system/gd/hci/hci_layer_unittest.cc b/system/gd/hci/hci_layer_unittest.cc index 9e7100444e..8b2c15ba46 100644 --- a/system/gd/hci/hci_layer_unittest.cc +++ b/system/gd/hci/hci_layer_unittest.cc @@ -99,7 +99,7 @@ class HciLayerTest : public ::testing::Test { } void FailIfResetNotSent() { - hci_handler_->BindOnceOn(this, &HciLayerTest::fail_if_reset_not_sent).Invoke(); + (hci_handler_->BindOnceOn(this, &HciLayerTest::fail_if_reset_not_sent))(); sync_handler(); } diff --git a/system/gd/hci/le_address_manager.cc b/system/gd/hci/le_address_manager.cc index ed9141a94d..f06568f05e 100644 --- a/system/gd/hci/le_address_manager.cc +++ b/system/gd/hci/le_address_manager.cc @@ -116,7 +116,7 @@ void LeAddressManager::SetPrivacyPolicyForInitiatorAddress( switch (address_policy_) { case AddressPolicy::USE_PUBLIC_ADDRESS: le_address_ = AddressWithType(public_address_, AddressType::PUBLIC_DEVICE_ADDRESS); - handler_->BindOnceOn(this, &LeAddressManager::resume_registered_clients).Invoke(); + handler_->BindOnceOn(this, &LeAddressManager::resume_registered_clients)(); break; case AddressPolicy::USE_STATIC_ADDRESS: { auto addr = fixed_address.GetAddress(); @@ -208,7 +208,7 @@ bool LeAddressManager::RotatingAddress() { address_policy_ == AddressPolicy::USE_NON_RESOLVABLE_ADDRESS; } LeAddressManager::AddressPolicy LeAddressManager::Register(LeAddressManagerCallback* callback) { - handler_->BindOnceOn(this, &LeAddressManager::register_client, callback).Invoke(); + handler_->BindOnceOn(this, &LeAddressManager::register_client, callback)(); return address_policy_; } @@ -230,7 +230,7 @@ void LeAddressManager::register_client(LeAddressManagerCallback* callback) { } void LeAddressManager::Unregister(LeAddressManagerCallback* callback) { - handler_->BindOnceOn(this, &LeAddressManager::unregister_client, callback).Invoke(); + handler_->BindOnceOn(this, &LeAddressManager::unregister_client, callback)(); } void LeAddressManager::unregister_client(LeAddressManagerCallback* callback) { @@ -250,7 +250,7 @@ void LeAddressManager::unregister_client(LeAddressManagerCallback* callback) { } bool LeAddressManager::UnregisterSync(LeAddressManagerCallback* callback, std::chrono::milliseconds timeout) { - handler_->BindOnceOn(this, &LeAddressManager::unregister_client, callback).Invoke(); + handler_->BindOnceOn(this, &LeAddressManager::unregister_client, callback)(); std::promise<void> promise; auto future = promise.get_future(); handler_->Post(common::BindOnce(&std::promise<void>::set_value, common::Unretained(&promise))); @@ -258,11 +258,11 @@ bool LeAddressManager::UnregisterSync(LeAddressManagerCallback* callback, std::c } void LeAddressManager::AckPause(LeAddressManagerCallback* callback) { - handler_->BindOnceOn(this, &LeAddressManager::ack_pause, callback).Invoke(); + handler_->BindOnceOn(this, &LeAddressManager::ack_pause, callback)(); } void LeAddressManager::AckResume(LeAddressManagerCallback* callback) { - handler_->BindOnceOn(this, &LeAddressManager::ack_resume, callback).Invoke(); + handler_->BindOnceOn(this, &LeAddressManager::ack_resume, callback)(); } AddressWithType LeAddressManager::GetInitiatorAddress() { @@ -528,7 +528,7 @@ void LeAddressManager::AddDeviceToFilterAcceptList( FilterAcceptListAddressType accept_list_address_type, bluetooth::hci::Address address) { auto packet_builder = hci::LeAddDeviceToFilterAcceptListBuilder::Create(accept_list_address_type, address); Command command = {CommandType::ADD_DEVICE_TO_ACCEPT_LIST, HCICommand{std::move(packet_builder)}}; - handler_->BindOnceOn(this, &LeAddressManager::push_command, std::move(command)).Invoke(); + handler_->BindOnceOn(this, &LeAddressManager::push_command, std::move(command))(); } void LeAddressManager::AddDeviceToResolvingList( @@ -563,9 +563,9 @@ void LeAddressManager::AddDeviceToResolvingList( cached_commands_.push(std::move(enable)); if (registered_clients_.empty()) { - handler_->BindOnceOn(this, &LeAddressManager::handle_next_command).Invoke(); + handler_->BindOnceOn(this, &LeAddressManager::handle_next_command)(); } else { - handler_->BindOnceOn(this, &LeAddressManager::pause_registered_clients).Invoke(); + handler_->BindOnceOn(this, &LeAddressManager::pause_registered_clients)(); } } @@ -573,7 +573,7 @@ void LeAddressManager::RemoveDeviceFromFilterAcceptList( FilterAcceptListAddressType accept_list_address_type, bluetooth::hci::Address address) { auto packet_builder = hci::LeRemoveDeviceFromFilterAcceptListBuilder::Create(accept_list_address_type, address); Command command = {CommandType::REMOVE_DEVICE_FROM_ACCEPT_LIST, HCICommand{std::move(packet_builder)}}; - handler_->BindOnceOn(this, &LeAddressManager::push_command, std::move(command)).Invoke(); + handler_->BindOnceOn(this, &LeAddressManager::push_command, std::move(command))(); } void LeAddressManager::RemoveDeviceFromResolvingList( @@ -598,16 +598,16 @@ void LeAddressManager::RemoveDeviceFromResolvingList( cached_commands_.push(std::move(enable)); if (registered_clients_.empty()) { - handler_->BindOnceOn(this, &LeAddressManager::handle_next_command).Invoke(); + handler_->BindOnceOn(this, &LeAddressManager::handle_next_command)(); } else { - handler_->BindOnceOn(this, &LeAddressManager::pause_registered_clients).Invoke(); + handler_->BindOnceOn(this, &LeAddressManager::pause_registered_clients)(); } } void LeAddressManager::ClearFilterAcceptList() { auto packet_builder = hci::LeClearFilterAcceptListBuilder::Create(); Command command = {CommandType::CLEAR_ACCEPT_LIST, HCICommand{std::move(packet_builder)}}; - handler_->BindOnceOn(this, &LeAddressManager::push_command, std::move(command)).Invoke(); + handler_->BindOnceOn(this, &LeAddressManager::push_command, std::move(command))(); } void LeAddressManager::ClearResolvingList() { @@ -629,7 +629,7 @@ void LeAddressManager::ClearResolvingList() { Command enable = {CommandType::SET_ADDRESS_RESOLUTION_ENABLE, HCICommand{std::move(enable_builder)}}; cached_commands_.push(std::move(enable)); - handler_->BindOnceOn(this, &LeAddressManager::pause_registered_clients).Invoke(); + handler_->BindOnceOn(this, &LeAddressManager::pause_registered_clients)(); } template <class View> @@ -720,7 +720,7 @@ void LeAddressManager::OnCommandComplete(bluetooth::hci::CommandCompleteView vie break; } - handler_->BindOnceOn(this, &LeAddressManager::check_cached_commands).Invoke(); + handler_->BindOnceOn(this, &LeAddressManager::check_cached_commands)(); } void LeAddressManager::check_cached_commands() { diff --git a/system/gd/hci/le_advertising_manager.cc b/system/gd/hci/le_advertising_manager.cc index a054b7f778..8d6e70deca 100644 --- a/system/gd/hci/le_advertising_manager.cc +++ b/system/gd/hci/le_advertising_manager.cc @@ -776,9 +776,9 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb common::ContextualOnceCallback<void(uint8_t /* inst_id */, uint8_t /* status */)> callback) { AdvertiserId id = allocate_advertiser(); if (id == kInvalidId) { - callback.Invoke(kInvalidId, AdvertisingCallback::AdvertisingStatus::TOO_MANY_ADVERTISERS); + callback(kInvalidId, AdvertisingCallback::AdvertisingStatus::TOO_MANY_ADVERTISERS); } else { - callback.Invoke(id, AdvertisingCallback::AdvertisingStatus::SUCCESS); + callback(id, AdvertisingCallback::AdvertisingStatus::SUCCESS); } } diff --git a/system/gd/hci/le_periodic_sync_manager_test.cc b/system/gd/hci/le_periodic_sync_manager_test.cc index 1d1fdce8c4..ecf3248bc1 100644 --- a/system/gd/hci/le_periodic_sync_manager_test.cc +++ b/system/gd/hci/le_periodic_sync_manager_test.cc @@ -113,7 +113,7 @@ class TestLeScanningInterface : public LeScanningInterface { CommandCompleteView complete_view = CommandCompleteView::Create(event); ASSERT_TRUE(complete_view.IsValid()); ASSERT_NE((uint16_t)command_complete_callbacks.size(), 0); - std::move(command_complete_callbacks.front()).Invoke(complete_view); + std::move(command_complete_callbacks.front())(complete_view); command_complete_callbacks.pop_front(); } @@ -122,7 +122,7 @@ class TestLeScanningInterface : public LeScanningInterface { CommandStatusView status_view = CommandStatusView::Create(event); ASSERT_TRUE(status_view.IsValid()); ASSERT_NE((uint16_t)command_status_callbacks.size(), 0); - std::move(command_status_callbacks.front()).Invoke(status_view); + std::move(command_status_callbacks.front())(status_view); command_status_callbacks.pop_front(); } diff --git a/system/gd/hci/le_scanning_reassembler.cc b/system/gd/hci/le_scanning_reassembler.cc index e7ef3ffc5f..27b50bde15 100644 --- a/system/gd/hci/le_scanning_reassembler.cc +++ b/system/gd/hci/le_scanning_reassembler.cc @@ -64,7 +64,7 @@ LeScanningReassembler::ProcessAdvertisingReport( // the previous data as safety measure if the report is not a scan // response. if (is_legacy && !is_scan_response) { - log::debug("Dropping repeated legacy advertising data"); + log::verbose("Dropping repeated legacy advertising data"); RemoveFragment(key); } diff --git a/system/gd/hci/remote_name_request.cc b/system/gd/hci/remote_name_request.cc index fb32ace6d8..5f8fd685c9 100644 --- a/system/gd/hci/remote_name_request.cc +++ b/system/gd/hci/remote_name_request.cc @@ -80,7 +80,7 @@ struct RemoteNameRequestModule::impl { log::info( "Dequeued remote name request to {} since it was cancelled", address.ToRedactedStringForLogging()); - on_remote_name_complete_ptr->Invoke(ErrorCode::PAGE_TIMEOUT, {}); + (*on_remote_name_complete_ptr)(ErrorCode::PAGE_TIMEOUT, {}); }, address, on_remote_name_complete_ptr)); @@ -99,7 +99,7 @@ struct RemoteNameRequestModule::impl { "Received CONNECTION_COMPLETE (corresponding INCORRECTLY to an RNR cancellation) from {}", address.ToRedactedStringForLogging()); pending_ = false; - on_remote_name_complete_.Invoke(ErrorCode::UNKNOWN_CONNECTION, {}); + on_remote_name_complete_(ErrorCode::UNKNOWN_CONNECTION, {}); acl_scheduler_->ReportRemoteNameRequestCompletion(address); } else { log::error( @@ -146,7 +146,7 @@ struct RemoteNameRequestModule::impl { "Started remote name request peer:{} status:{}", address.ToRedactedStringForLogging(), ErrorCodeText(status.GetStatus())); - on_completion.Invoke(status.GetStatus()); + on_completion(status.GetStatus()); if (status.GetStatus() != ErrorCode::SUCCESS /* pending */) { pending_ = false; acl_scheduler_->ReportRemoteNameRequestCompletion(address); @@ -177,11 +177,11 @@ struct RemoteNameRequestModule::impl { void on_remote_host_supported_features_notification(EventView view) { auto packet = RemoteHostSupportedFeaturesNotificationView::Create(view); log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()"); - if (pending_ && !on_remote_host_supported_features_notification_.IsEmpty()) { + if (pending_ && on_remote_host_supported_features_notification_) { log::info( "Received REMOTE_HOST_SUPPORTED_FEATURES_NOTIFICATION from {}", packet.GetBdAddr().ToRedactedStringForLogging()); - on_remote_host_supported_features_notification_.Invoke(packet.GetHostSupportedFeatures()); + on_remote_host_supported_features_notification_(packet.GetHostSupportedFeatures()); // Remove the callback so that we won't call it again. on_remote_host_supported_features_notification_ = RemoteHostSupportedFeaturesCallback(); } else if (!pending_) { @@ -202,7 +202,7 @@ struct RemoteNameRequestModule::impl { address.ToRedactedStringForLogging(), ErrorCodeText(status)); pending_ = false; - on_remote_name_complete_.Invoke(status, name); + on_remote_name_complete_(status, name); acl_scheduler_->ReportRemoteNameRequestCompletion(address); } else { log::error( diff --git a/system/gd/hci/vendor_specific_event_manager.cc b/system/gd/hci/vendor_specific_event_manager.cc index 7baea6034b..b7810d9f75 100644 --- a/system/gd/hci/vendor_specific_event_manager.cc +++ b/system/gd/hci/vendor_specific_event_manager.cc @@ -89,7 +89,7 @@ struct VendorSpecificEventManager::impl { log::warn("Unhandled vendor specific event of type 0x{:02x}", vse_subevent_code); return; } - subevent_handlers_[vse_subevent_code].Invoke(vendor_specific_event_view); + subevent_handlers_[vse_subevent_code](vendor_specific_event_view); } Module* module_; diff --git a/system/gd/l2cap/classic/internal/dynamic_channel_service_impl.h b/system/gd/l2cap/classic/internal/dynamic_channel_service_impl.h index b444c7b15b..15aaff0583 100644 --- a/system/gd/l2cap/classic/internal/dynamic_channel_service_impl.h +++ b/system/gd/l2cap/classic/internal/dynamic_channel_service_impl.h @@ -16,8 +16,6 @@ #pragma once -#include "common/bind.h" - #include "l2cap/classic/dynamic_channel.h" #include "l2cap/classic/dynamic_channel_configuration_option.h" #include "l2cap/classic/dynamic_channel_manager.h" @@ -41,7 +39,7 @@ class DynamicChannelServiceImpl { }; virtual void NotifyChannelCreation(std::unique_ptr<DynamicChannel> channel) { - on_connection_open_callback_.Invoke(std::move(channel)); + on_connection_open_callback_(std::move(channel)); } virtual DynamicChannelConfigurationOption GetConfigOption() const { diff --git a/system/gd/l2cap/classic/internal/dynamic_channel_service_manager_impl.cc b/system/gd/l2cap/classic/internal/dynamic_channel_service_manager_impl.cc index 2197d349d2..3dfb0e185f 100644 --- a/system/gd/l2cap/classic/internal/dynamic_channel_service_manager_impl.cc +++ b/system/gd/l2cap/classic/internal/dynamic_channel_service_manager_impl.cc @@ -18,7 +18,6 @@ #include <bluetooth/log.h> -#include "common/bind.h" #include "l2cap/classic/internal/dynamic_channel_service_impl.h" #include "l2cap/psm.h" #include "os/log.h" @@ -32,12 +31,14 @@ void DynamicChannelServiceManagerImpl::Register(Psm psm, DynamicChannelServiceImpl::PendingRegistration pending_registration) { if (!IsPsmValid(psm)) { std::unique_ptr<DynamicChannelService> invalid_service(new DynamicChannelService()); - pending_registration.on_registration_complete_callback_.Invoke( - DynamicChannelManager::RegistrationResult::FAIL_INVALID_SERVICE, std::move(invalid_service)); + pending_registration.on_registration_complete_callback_( + DynamicChannelManager::RegistrationResult::FAIL_INVALID_SERVICE, + std::move(invalid_service)); } else if (IsServiceRegistered(psm)) { std::unique_ptr<DynamicChannelService> invalid_service(new DynamicChannelService()); - pending_registration.on_registration_complete_callback_.Invoke( - DynamicChannelManager::RegistrationResult::FAIL_DUPLICATE_SERVICE, std::move(invalid_service)); + pending_registration.on_registration_complete_callback_( + DynamicChannelManager::RegistrationResult::FAIL_DUPLICATE_SERVICE, + std::move(invalid_service)); } else { service_map_.try_emplace( psm, @@ -46,7 +47,7 @@ void DynamicChannelServiceManagerImpl::Register(Psm psm, std::move(pending_registration.on_connection_open_callback_), pending_registration.configuration_)); std::unique_ptr<DynamicChannelService> user_service(new DynamicChannelService(psm, this, l2cap_layer_handler_)); - pending_registration.on_registration_complete_callback_.Invoke( + pending_registration.on_registration_complete_callback_( DynamicChannelManager::RegistrationResult::SUCCESS, std::move(user_service)); } } @@ -54,7 +55,7 @@ void DynamicChannelServiceManagerImpl::Register(Psm psm, void DynamicChannelServiceManagerImpl::Unregister(Psm psm, DynamicChannelService::OnUnregisteredCallback callback) { if (IsServiceRegistered(psm)) { service_map_.erase(psm); - callback.Invoke(); + callback(); } else { log::error("service not registered psm:{}", psm); } diff --git a/system/gd/l2cap/classic/internal/link.cc b/system/gd/l2cap/classic/internal/link.cc index cb79d077a5..0e0d48ab94 100644 --- a/system/gd/l2cap/classic/internal/link.cc +++ b/system/gd/l2cap/classic/internal/link.cc @@ -164,7 +164,7 @@ void Link::SendConnectionRequest(Psm psm, Cid local_cid, ConnectionResult result{ .connection_result_code = ConnectionResultCode::FAIL_REMOTE_NOT_SUPPORT, }; - pending_dynamic_channel_connection.on_fail_callback_.Invoke(result); + pending_dynamic_channel_connection.on_fail_callback_(result); dynamic_channel_allocator_.FreeChannel(local_cid); return; } else { @@ -286,7 +286,7 @@ void Link::NotifyChannelCreation(Cid cid, std::unique_ptr<DynamicChannel> user_c "assert failed: local_cid_to_pending_dynamic_channel_connection_map_.find(cid) != " "local_cid_to_pending_dynamic_channel_connection_map_.end()"); auto& pending_dynamic_channel_connection = local_cid_to_pending_dynamic_channel_connection_map_[cid]; - pending_dynamic_channel_connection.on_open_callback_.Invoke(std::move(user_channel)); + pending_dynamic_channel_connection.on_open_callback_(std::move(user_channel)); local_cid_to_pending_dynamic_channel_connection_map_.erase(cid); } @@ -297,7 +297,7 @@ void Link::NotifyChannelFail(Cid cid, ConnectionResult result) { "assert failed: local_cid_to_pending_dynamic_channel_connection_map_.find(cid) != " "local_cid_to_pending_dynamic_channel_connection_map_.end()"); auto& pending_dynamic_channel_connection = local_cid_to_pending_dynamic_channel_connection_map_[cid]; - pending_dynamic_channel_connection.on_fail_callback_.Invoke(result); + pending_dynamic_channel_connection.on_fail_callback_(result); local_cid_to_pending_dynamic_channel_connection_map_.erase(cid); } diff --git a/system/gd/l2cap/classic/internal/link_manager.cc b/system/gd/l2cap/classic/internal/link_manager.cc index 50c170fa3d..6ce3188a71 100644 --- a/system/gd/l2cap/classic/internal/link_manager.cc +++ b/system/gd/l2cap/classic/internal/link_manager.cc @@ -303,7 +303,7 @@ void LinkManager::OnConnectFail(hci::Address device, hci::ErrorCode reason, bool hci::ErrorCodeText(reason)); if (pending_dynamic_channels_callbacks_.find(device) != pending_dynamic_channels_callbacks_.end()) { for (Link::PendingDynamicChannelConnection& callbacks : pending_dynamic_channels_callbacks_[device]) { - callbacks.on_fail_callback_.Invoke(DynamicChannelManager::ConnectionResult{ + callbacks.on_fail_callback_(DynamicChannelManager::ConnectionResult{ .hci_error = hci::ErrorCode::CONNECTION_TIMEOUT, }); } diff --git a/system/gd/l2cap/classic/security_enforcement_interface.h b/system/gd/l2cap/classic/security_enforcement_interface.h index 5ea9df83ff..f951760b52 100644 --- a/system/gd/l2cap/classic/security_enforcement_interface.h +++ b/system/gd/l2cap/classic/security_enforcement_interface.h @@ -51,9 +51,9 @@ class SecurityEnforcementRejectAllImpl : public SecurityEnforcementInterface { SecurityPolicy policy, ResultCallback result_callback) override { if (policy == SecurityPolicy::_SDP_ONLY_NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK) { - result_callback.Invoke(true); + result_callback(true); } else { - result_callback.Invoke(false); + result_callback(false); } } }; diff --git a/system/gd/l2cap/fuzz/fuzz_dynamic_channel_manager_impl.h b/system/gd/l2cap/fuzz/fuzz_dynamic_channel_manager_impl.h index d8a8b3f35d..bf8adb7f02 100644 --- a/system/gd/l2cap/fuzz/fuzz_dynamic_channel_manager_impl.h +++ b/system/gd/l2cap/fuzz/fuzz_dynamic_channel_manager_impl.h @@ -79,12 +79,12 @@ class FuzzDynamicChannelManagerImpl { } void SetConnectionOnFail(l2cap::classic::DynamicChannelManager::ConnectionResult result, std::promise<void> promise) { - std::move(on_fail_callback_).Invoke(result); + std::move(on_fail_callback_)(result); promise.set_value(); } void SetConnectionOnOpen(std::unique_ptr<l2cap::DynamicChannel> channel, std::promise<void> promise) { - std::move(on_open_callback_).Invoke(std::move(channel)); + std::move(on_open_callback_)(std::move(channel)); promise.set_value(); } diff --git a/system/gd/l2cap/internal/dynamic_channel_impl.cc b/system/gd/l2cap/internal/dynamic_channel_impl.cc index 0f1b235b35..dfd2bc335e 100644 --- a/system/gd/l2cap/internal/dynamic_channel_impl.cc +++ b/system/gd/l2cap/internal/dynamic_channel_impl.cc @@ -47,10 +47,10 @@ hci::AddressWithType DynamicChannelImpl::GetDevice() const { } void DynamicChannelImpl::RegisterOnCloseCallback(DynamicChannel::OnCloseCallback on_close_callback) { - log::assert_that(on_close_callback_.IsEmpty(), "OnCloseCallback can only be registered once"); + log::assert_that(!on_close_callback_, "OnCloseCallback can only be registered once"); // If channel is already closed, call the callback immediately without saving it if (closed_) { - on_close_callback.Invoke(close_reason_); + on_close_callback(close_reason_); return; } on_close_callback_ = std::move(on_close_callback); @@ -76,7 +76,7 @@ void DynamicChannelImpl::OnClosed(hci::ErrorCode status) { close_reason_ = status; link_ = nullptr; l2cap_handler_ = nullptr; - on_close_callback_.Invoke(close_reason_); + on_close_callback_(close_reason_); on_close_callback_ = {}; } diff --git a/system/gd/l2cap/le/l2cap_le_module.cc b/system/gd/l2cap/le/l2cap_le_module.cc index 182468d33e..f4f1daee56 100644 --- a/system/gd/l2cap/le/l2cap_le_module.cc +++ b/system/gd/l2cap/le/l2cap_le_module.cc @@ -44,9 +44,9 @@ class SecurityEnforcementRejectAllImpl : public SecurityEnforcementInterface { SecurityPolicy policy, ResultCallback result_callback) override { if (policy == SecurityPolicy::NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK) { - result_callback.Invoke(true); + result_callback(true); } else { - result_callback.Invoke(false); + result_callback(false); } } }; diff --git a/system/gd/metrics/counter_metrics.cc b/system/gd/metrics/counter_metrics.cc index 75c41f54a5..5b82b099b5 100644 --- a/system/gd/metrics/counter_metrics.cc +++ b/system/gd/metrics/counter_metrics.cc @@ -56,7 +56,7 @@ bool CounterMetrics::CacheCount(int32_t key, int64_t count) { return false; } if (count <= 0) { - log::warn("count is not larger than 0. count: {}, key: {}", std::to_string(count), key); + log::warn("count is not larger than 0. count: {}, key: {}", count, key); return false; } int64_t total = 0; @@ -65,11 +65,7 @@ bool CounterMetrics::CacheCount(int32_t key, int64_t count) { total = counters_[key]; } if (LLONG_MAX - total < count) { - log::warn( - "Counter metric overflows. count {} current total: {} key: {}", - std::to_string(count), - std::to_string(total), - key); + log::warn("Counter metric overflows. count {} current total: {} key: {}", count, total, key); counters_[key] = LLONG_MAX; return false; } @@ -83,7 +79,7 @@ bool CounterMetrics::Count(int32_t key, int64_t count) { return false; } if (count <= 0) { - log::warn("count is not larger than 0. count: {}, key: {}", std::to_string(count), key); + log::warn("count is not larger than 0. count: {}, key: {}", count, key); return false; } os::LogMetricBluetoothCodePathCounterMetrics(key, count); diff --git a/system/gd/os/android/metrics.cc b/system/gd/os/android/metrics.cc index 5ad9a3bc80..45b7d9ac5b 100644 --- a/system/gd/os/android/metrics.cc +++ b/system/gd/os/android/metrics.cc @@ -139,7 +139,7 @@ void LogMetricA2dpAudioUnderrunEvent( log::warn( "Failed for {}, encoding_interval_nanos {}, num_missing_pcm_bytes {}, error {}", address, - std::to_string(encoding_interval_nanos), + encoding_interval_nanos, num_missing_pcm_bytes, ret); } @@ -170,7 +170,7 @@ void LogMetricA2dpAudioOverrunEvent( "Failed to log for {}, encoding_interval_nanos {}, num_dropped_buffers {}, " "num_dropped_encoded_frames {}, num_dropped_encoded_bytes {}, error {}", address, - std::to_string(encoding_interval_nanos), + encoding_interval_nanos, num_dropped_buffers, num_dropped_encoded_frames, num_dropped_encoded_bytes, @@ -332,7 +332,7 @@ void LogMetricClassicPairingEvent( common::ToHexString(hci_event), common::ToHexString(cmd_status), common::ToHexString(reason_code), - std::to_string(event_value), + event_value, ret); } @@ -398,8 +398,8 @@ void LogMetricSocketConnectionState( port, type, connection_state, - std::to_string(tx_bytes), - std::to_string(rx_bytes), + tx_bytes, + rx_bytes, uid, server_port, socket_role, @@ -477,7 +477,7 @@ void LogMetricBluetoothLocalSupportedFeatures(uint32_t page_num, uint64_t featur log::warn( "Failed for LogMetricBluetoothLocalSupportedFeatures, page_num {}, features {}, error {}", page_num, - std::to_string(features), + features, ret); } } @@ -544,7 +544,7 @@ void LogMetricBluetoothRemoteSupportedFeatures( "connection_handle {}, error {}", metric_id, page, - std::to_string(features), + features, connection_handle, ret); } @@ -553,7 +553,7 @@ void LogMetricBluetoothRemoteSupportedFeatures( void LogMetricBluetoothCodePathCounterMetrics(int32_t key, int64_t count) { int ret = stats_write(BLUETOOTH_CODE_PATH_COUNTER, key, count); if (ret < 0) { - log::warn("Failed counter metrics for {}, count {}, error {}", key, std::to_string(count), ret); + log::warn("Failed counter metrics for {}, count {}, error {}", key, count, ret); } } diff --git a/system/gd/os/linux_generic/alarm_timerfd_unittest.cc b/system/gd/os/linux_generic/alarm_timerfd_unittest.cc index 03335f40eb..c2e3952b29 100644 --- a/system/gd/os/linux_generic/alarm_timerfd_unittest.cc +++ b/system/gd/os/linux_generic/alarm_timerfd_unittest.cc @@ -95,12 +95,19 @@ TEST_F(AlarmOnTimerFdTest, cancel_alarm) { } TEST_F(AlarmOnTimerFdTest, cancel_alarm_from_callback) { - auto promise = std::make_unique<std::promise<void>>(); - auto future = promise->get_future(); - alarm_->Schedule(BindOnce(&Alarm::Cancel, alarm_), kShortWait); - // Could wait for kForever, but no need. Just let others run twice for a short time. - ASSERT_NE(std::future_status::ready, future.wait_for(kShortWait)); - ASSERT_NE(std::future_status::ready, future.wait_for(kShortWait)); + auto promise = std::promise<void>(); + auto future = promise.get_future(); + alarm_->Schedule( + BindOnce( + [](std::shared_ptr<Alarm> alarm, std::promise<void> promise) { + alarm->Cancel(); + alarm.reset(); // Allow alarm to be freed by Teardown + promise.set_value(); + }, + alarm_, + std::move(promise)), + kShortWait); + ASSERT_EQ(std::future_status::ready, future.wait_for(kForever)); } TEST_F(AlarmOnTimerFdTest, schedule_while_alarm_armed) { diff --git a/system/gd/os/linux_generic/alarm_unittest.cc b/system/gd/os/linux_generic/alarm_unittest.cc index 81d16d5c62..d3b07beb89 100644 --- a/system/gd/os/linux_generic/alarm_unittest.cc +++ b/system/gd/os/linux_generic/alarm_unittest.cc @@ -16,7 +16,6 @@ #include "os/alarm.h" -#include <cstddef> #include <future> #include <memory> @@ -85,8 +84,21 @@ TEST_F(AlarmTest, cancel_alarm) { } TEST_F(AlarmTest, cancel_alarm_from_callback) { - alarm_->Schedule(BindOnce(&Alarm::Cancel, alarm_), std::chrono::milliseconds(1)); - std::this_thread::sleep_for(std::chrono::milliseconds(5)); + std::promise<void> promise; + auto future = promise.get_future(); + alarm_->Schedule( + BindOnce( + [](std::shared_ptr<Alarm> alarm, std::promise<void> promise) { + alarm->Cancel(); + alarm.reset(); // Allow alarm to be freed by Teardown + promise.set_value(); + }, + alarm_, + std::move(promise)), + std::chrono::milliseconds(1)); + fake_timer_advance(10); + ASSERT_EQ(std::future_status::ready, future.wait_for(std::chrono::seconds(1))); + ASSERT_EQ(alarm_.use_count(), 1); } TEST_F(AlarmTest, schedule_while_alarm_armed) { diff --git a/system/gd/os/linux_generic/repeating_alarm_unittest.cc b/system/gd/os/linux_generic/repeating_alarm_unittest.cc index 2e2bcdf4ed..a1329845f5 100644 --- a/system/gd/os/linux_generic/repeating_alarm_unittest.cc +++ b/system/gd/os/linux_generic/repeating_alarm_unittest.cc @@ -26,6 +26,7 @@ namespace bluetooth { namespace os { namespace { +using common::BindOnce; using fake_timer::fake_timerfd_advance; using fake_timer::fake_timerfd_reset; @@ -85,7 +86,7 @@ class RepeatingAlarmTest : public ::testing::Test { RepeatingAlarm* alarm_; - common::Closure should_not_happen_ = common::Bind([] { ASSERT_TRUE(false); }); + common::Closure should_not_happen_ = common::Bind([]() { FAIL(); }); private: Thread* thread_; @@ -111,13 +112,23 @@ TEST_F(RepeatingAlarmTest, schedule) { TEST_F(RepeatingAlarmTest, cancel_alarm) { alarm_->Schedule(should_not_happen_, std::chrono::milliseconds(10)); alarm_->Cancel(); - std::this_thread::sleep_for(std::chrono::milliseconds(50)); + fake_timer_advance(10); } TEST_F(RepeatingAlarmTest, cancel_alarm_from_callback) { + std::promise<void> promise; + auto future = promise.get_future(); alarm_->Schedule( - common::Bind(&RepeatingAlarm::Cancel, common::Unretained(this->alarm_)), std::chrono::milliseconds(1)); - std::this_thread::sleep_for(std::chrono::milliseconds(5)); + common::Bind( + [](RepeatingAlarm* alarm, std::promise<void>* promise) { + alarm->Cancel(); + promise->set_value(); + }, + common::Unretained(this->alarm_), + common::Unretained(&promise)), + std::chrono::milliseconds(1)); + fake_timer_advance(1); + ASSERT_EQ(std::future_status::ready, future.wait_for(std::chrono::seconds(1))); } TEST_F(RepeatingAlarmTest, schedule_while_alarm_armed) { @@ -127,7 +138,7 @@ TEST_F(RepeatingAlarmTest, schedule_while_alarm_armed) { alarm_->Schedule( common::Bind(&std::promise<void>::set_value, common::Unretained(&promise)), std::chrono::milliseconds(10)); fake_timer_advance(10); - future.get(); + ASSERT_EQ(std::future_status::ready, future.wait_for(std::chrono::seconds(1))); alarm_->Cancel(); } @@ -135,7 +146,7 @@ TEST_F(RepeatingAlarmTest, delete_while_alarm_armed) { alarm_->Schedule(should_not_happen_, std::chrono::milliseconds(1)); delete alarm_; alarm_ = nullptr; - std::this_thread::sleep_for(std::chrono::milliseconds(1)); + fake_timer_advance(10); } TEST_F(RepeatingAlarmTest, verify_small) { diff --git a/system/gd/packet/parser/test/generated_packet_test.cc b/system/gd/packet/parser/test/generated_packet_test.cc index 1ce4feebce..a3ce2542cf 100644 --- a/system/gd/packet/parser/test/generated_packet_test.cc +++ b/system/gd/packet/parser/test/generated_packet_test.cc @@ -2004,6 +2004,38 @@ TEST(GeneratedPacketTest, testStructWithShadowedNames) { ASSERT_EQ(ebs.struct_type_, struct_type); } +TEST(GeneratedPacketTest, testArrays) { + std::vector<uint8_t> bytes({1, 2, 3}); + std::vector<uint16_t> sixteens({0x0111, 0x0212, 0x0313}); + std::vector<uint32_t> thirtytwos({0x01112131, 0x02122232, 0x03132333}); + auto packet = ArraysBuilder::Create(bytes, sixteens, thirtytwos); + + std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>(); + BitInserter it(*packet_bytes); + packet->Serialize(it); + + PacketView<kLittleEndian> packet_bytes_view(packet_bytes); + auto view = ArraysView::Create(packet_bytes_view); + ASSERT_TRUE(view.IsValid()); + + auto bytes_from_packet = view.GetBytes(); + ASSERT_EQ(bytes.size(), bytes_from_packet.size()); + for (size_t i = 0; i < bytes.size(); i++) { + ASSERT_EQ(bytes[i], bytes_from_packet[i]); + } + + auto sixteens_from_packet = view.GetSixteens(); + ASSERT_EQ(sixteens.size(), sixteens_from_packet.size()); + for (size_t i = 0; i < sixteens.size(); i++) { + ASSERT_EQ(sixteens[i], sixteens_from_packet[i]); + } + + auto thirtytwos_from_packet = view.GetThirtytwos(); + ASSERT_EQ(thirtytwos.size(), thirtytwos_from_packet.size()); + for (size_t i = 0; i < thirtytwos.size(); i++) { + ASSERT_EQ(thirtytwos[i], thirtytwos_from_packet[i]); + } +} } // namespace parser } // namespace packet } // namespace bluetooth diff --git a/system/gd/packet/parser/test/variable.cc b/system/gd/packet/parser/test/variable.cc index 23443bf22b..aba8aae74c 100644 --- a/system/gd/packet/parser/test/variable.cc +++ b/system/gd/packet/parser/test/variable.cc @@ -18,7 +18,6 @@ #include "variable.h" -#include <stdio.h> #include <sstream> namespace bluetooth { diff --git a/system/gd/rust/common/src/init_flags.rs b/system/gd/rust/common/src/init_flags.rs index b81eb1c74f..c9bf40c7e3 100644 --- a/system/gd/rust/common/src/init_flags.rs +++ b/system/gd/rust/common/src/init_flags.rs @@ -89,15 +89,13 @@ trait FlagHolder: Default { fn get_defaults_for_test() -> Self; fn parse(flags: Vec<String>) -> Self; fn dump(&self) -> BTreeMap<&'static str, String>; - fn reconcile(self) -> Self; } macro_rules! init_flags_struct { ( name: $name:ident flags: { $($flag:ident $(: $type:ty)? $(= $default:tt)?,)* } - extra_parsed_flags: { $($extra_flag:tt => $extra_flag_fn:ident(_, _ $(,$extra_args:tt)*),)*} - dependencies: { $($parent:ident => $child:ident),* }) => { + extra_parsed_flags: { $($extra_flag:tt => $extra_flag_fn:ident(_, _ $(,$extra_args:tt)*),)*}) => { struct $name { $($flag : type_expand!($($type)?),)* @@ -144,20 +142,7 @@ macro_rules! init_flags_struct { } } - init_flags.reconcile() - } - - #[allow(unused_mut)] - fn reconcile(mut self) -> Self { - loop { - // dependencies can be specified in any order - $(if self.$parent && !self.$child { - self.$child = true; - continue; - })* - break; - } - self + init_flags } } @@ -175,8 +160,7 @@ macro_rules! init_flags_struct { macro_rules! init_flags_getters { ( flags: { $($flag:ident $(: $type:ty)? $(= $default:tt)?,)* } - extra_parsed_flags: { $($extra_flag:tt => $extra_flag_fn:ident(_, _ $(,$extra_args:tt)*),)*} - dependencies: { $($parent:ident => $child:ident),* }) => { + extra_parsed_flags: { $($extra_flag:tt => $extra_flag_fn:ident(_, _ $(,$extra_args:tt)*),)*}) => { $(create_getter_fn!($flag $($type)?);)* @@ -232,16 +216,13 @@ init_flags!( classic_discovery_only, device_iot_config_logging, dynamic_avrcp_version_enhancement = true, - gatt_robust_caching_client = true, gatt_robust_caching_server, hci_adapter: i32, hfp_dynamic_version = true, irk_rotation, leaudio_targeted_announcement_reconnection_mode = true, pbap_pse_dynamic_version_upgrade = false, - private_gatt = true, redact_log = true, - rust_event_loop = true, sco_codec_select_lc3 = true, sco_codec_timeout_clear, sdp_serialization = true, @@ -258,10 +239,6 @@ init_flags!( extra_parsed_flags: { "--hci" => parse_hci_adapter(_, _), } - dependencies: { - always_use_private_gatt_for_debugging => private_gatt, - private_gatt => rust_event_loop - } ); lazy_static! { @@ -304,11 +281,7 @@ mod tests { #[test] fn simple_flag() { let _guard = ASYNC_LOCK.lock().unwrap(); - test_load(vec![ - "INIT_private_gatt=false", //override a default flag - "INIT_gatt_robust_caching_server=true", - ]); - assert!(!private_gatt_is_enabled()); + test_load(vec!["INIT_gatt_robust_caching_server=true"]); assert!(gatt_robust_caching_server_is_enabled()); } #[test] @@ -317,10 +290,8 @@ mod tests { test_load(vec![ "foo=bar=?", // vec length "foo=bar", // flag not save - "INIT_private_gatt=not_false", // parse error but has default value "INIT_gatt_robust_caching_server=not_true", // parse error ]); - assert!(private_gatt_is_enabled()); assert!(!gatt_robust_caching_server_is_enabled()); } #[test] @@ -347,7 +318,6 @@ mod tests { cat, } extra_parsed_flags: {} - dependencies: {} ); #[test] diff --git a/system/gd/rust/linux/client/src/command_handler.rs b/system/gd/rust/linux/client/src/command_handler.rs index cad6c1073f..d200555a39 100644 --- a/system/gd/rust/linux/client/src/command_handler.rs +++ b/system/gd/rust/linux/client/src/command_handler.rs @@ -783,14 +783,14 @@ impl CommandHandler { .into()); } - let success = self + let status = self .lock_context() .adapter_dbus .as_mut() .unwrap() .create_bond(device.clone(), BtTransport::Auto); - if success { + if status == BtStatus::Success { self.lock_context().bonding_attempt = Some(device); } } @@ -832,14 +832,14 @@ impl CommandHandler { name: String::from("Classic Device"), }; - let success = self + let status = self .lock_context() .adapter_dbus .as_mut() .unwrap() .connect_all_enabled_profiles(device.clone()); - if success { + if status == BtStatus::Success { println!("Connecting to {}", &device.address); } else { println!("Can't connect to {}", &device.address); diff --git a/system/gd/rust/linux/client/src/dbus_iface.rs b/system/gd/rust/linux/client/src/dbus_iface.rs index fb392a3795..2283fabae1 100644 --- a/system/gd/rust/linux/client/src/dbus_iface.rs +++ b/system/gd/rust/linux/client/src/dbus_iface.rs @@ -846,7 +846,7 @@ impl IBluetooth for BluetoothDBus { } #[dbus_method("CreateBond")] - fn create_bond(&mut self, device: BluetoothDevice, transport: BtTransport) -> bool { + fn create_bond(&mut self, device: BluetoothDevice, transport: BtTransport) -> BtStatus { dbus_generated!() } @@ -981,7 +981,7 @@ impl IBluetooth for BluetoothDBus { } #[dbus_method("ConnectAllEnabledProfiles")] - fn connect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> bool { + fn connect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> BtStatus { dbus_generated!() } diff --git a/system/gd/rust/linux/mgmt/Cargo.toml b/system/gd/rust/linux/mgmt/Cargo.toml index 092235c2e0..7306393ae2 100644 --- a/system/gd/rust/linux/mgmt/Cargo.toml +++ b/system/gd/rust/linux/mgmt/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "manager_service" -version = "0.3.0" +version = "0.4.0" edition = "2018" build = "build.rs" diff --git a/system/gd/rust/linux/service/src/iface_bluetooth.rs b/system/gd/rust/linux/service/src/iface_bluetooth.rs index d1783e38cd..d84f5e20a0 100644 --- a/system/gd/rust/linux/service/src/iface_bluetooth.rs +++ b/system/gd/rust/linux/service/src/iface_bluetooth.rs @@ -557,7 +557,7 @@ impl IBluetooth for IBluetoothDBus { } #[dbus_method("CreateBond")] - fn create_bond(&mut self, device: BluetoothDevice, transport: BtTransport) -> bool { + fn create_bond(&mut self, device: BluetoothDevice, transport: BtTransport) -> BtStatus { dbus_generated!() } @@ -692,7 +692,7 @@ impl IBluetooth for IBluetoothDBus { } #[dbus_method("ConnectAllEnabledProfiles")] - fn connect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> bool { + fn connect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> BtStatus { dbus_generated!() } diff --git a/system/gd/rust/linux/stack/src/bluetooth.rs b/system/gd/rust/linux/stack/src/bluetooth.rs index 5d34bba8b7..a44b2552f8 100644 --- a/system/gd/rust/linux/stack/src/bluetooth.rs +++ b/system/gd/rust/linux/stack/src/bluetooth.rs @@ -156,7 +156,7 @@ pub trait IBluetooth { fn get_discovery_end_millis(&self) -> u64; /// Initiates pairing to a remote device. Triggers connection if not already started. - fn create_bond(&mut self, device: BluetoothDevice, transport: BtTransport) -> bool; + fn create_bond(&mut self, device: BluetoothDevice, transport: BtTransport) -> BtStatus; /// Cancels any pending bond attempt on given device. fn cancel_bond_process(&mut self, device: BluetoothDevice) -> bool; @@ -237,7 +237,7 @@ pub trait IBluetooth { fn remove_sdp_record(&self, handle: i32) -> bool; /// Connect all profiles supported by device and enabled on adapter. - fn connect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> bool; + fn connect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> BtStatus; /// Disconnect all profiles supported by device and enabled on adapter. /// Note that it includes all custom profiles enabled by the users e.g. through SocketManager or @@ -1246,8 +1246,6 @@ pub(crate) trait BtifBluetoothCallbacks { fn ssp_request( &mut self, remote_addr: RawAddress, - remote_name: String, - cod: u32, variant: BtSspVariant, passkey: u32, ) { @@ -1614,8 +1612,6 @@ impl BtifBluetoothCallbacks for Bluetooth { fn ssp_request( &mut self, remote_addr: RawAddress, - remote_name: String, - cod: u32, variant: BtSspVariant, passkey: u32, ) { @@ -1623,7 +1619,7 @@ impl BtifBluetoothCallbacks for Bluetooth { if variant == BtSspVariant::Consent { let initiated_by_us = Some(remote_addr.clone()) == self.active_pairing_address; self.set_pairing_confirmation( - BluetoothDevice::new(remote_addr.to_string(), remote_name.clone()), + BluetoothDevice::new(remote_addr.to_string(), "".to_string()), initiated_by_us, ); return; @@ -1632,9 +1628,13 @@ impl BtifBluetoothCallbacks for Bluetooth { // Currently this supports many agent because we accept many callbacks. // TODO(b/274706838): We need a way to select the default agent. self.callbacks.for_all_callbacks(|callback| { + // TODO(b/336960912): libbluetooth changed their API so that we no longer + // get the Device name and CoD, which were included in our DBus API. + // Now we simply put random values since we aren't ready to change our DBus API + // and it works because our Clients are not using these anyway. callback.on_ssp_request( - BluetoothDevice::new(remote_addr.to_string(), remote_name.clone()), - cod, + BluetoothDevice::new(remote_addr.to_string(), "".to_string()), + 0, variant.clone(), passkey, ); @@ -2279,7 +2279,7 @@ impl IBluetooth for Bluetooth { } } - fn create_bond(&mut self, device: BluetoothDevice, transport: BtTransport) -> bool { + fn create_bond(&mut self, device: BluetoothDevice, transport: BtTransport) -> BtStatus { let addr = RawAddress::from_string(device.address.clone()); if addr.is_none() { @@ -2292,7 +2292,7 @@ impl IBluetooth for Bluetooth { 0, ); warn!("Can't create bond. Address {} is not valid", device.address); - return false; + return BtStatus::InvalidParam; } let address = addr.unwrap(); @@ -2308,7 +2308,7 @@ impl IBluetooth for Bluetooth { DisplayAddress(&address), DisplayAddress(&active_address) ); - return false; + return BtStatus::Busy; } // There could be a race between bond complete and bond cancel, which makes @@ -2335,7 +2335,7 @@ impl IBluetooth for Bluetooth { BtBondState::NotBonded, 0, ); - return false; + return BtStatus::from(status as u32); } // Creating bond automatically create ACL connection as well, therefore also log metrics @@ -2347,7 +2347,7 @@ impl IBluetooth for Bluetooth { metrics::acl_connect_attempt(address, BtAclState::Connected); } - return true; + return BtStatus::Success; } fn cancel_bond_process(&mut self, device: BluetoothDevice) -> bool { @@ -2691,17 +2691,17 @@ impl IBluetooth for Bluetooth { self.sdp.as_ref().unwrap().remove_sdp_record(handle) == BtStatus::Success } - fn connect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> bool { + fn connect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> BtStatus { // Profile init must be complete before this api is callable if !self.profiles_ready { - return false; + return BtStatus::NotReady; } let mut addr = match RawAddress::from_string(device.address.clone()) { Some(v) => v, None => { warn!("Can't connect profiles on invalid address [{}]", &device.address); - return false; + return BtStatus::InvalidParam; } }; @@ -2773,7 +2773,7 @@ impl IBluetooth for Bluetooth { let transport = match self.get_remote_device_if_found(&device.address) { Some(context) => context.acl_reported_transport, - None => return false, + None => return BtStatus::RemoteDeviceDown, }; let device_to_send = device.clone(); let transport = match self.get_remote_type(device.clone()) { @@ -2821,7 +2821,7 @@ impl IBluetooth for Bluetooth { self.resume_discovery(); } - return true; + return BtStatus::Success; } fn disconnect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> bool { diff --git a/system/gd/rust/linux/stack/src/bluetooth_media.rs b/system/gd/rust/linux/stack/src/bluetooth_media.rs index 631ede6e84..8ddee66f77 100644 --- a/system/gd/rust/linux/stack/src/bluetooth_media.rs +++ b/system/gd/rust/linux/stack/src/bluetooth_media.rs @@ -530,6 +530,7 @@ impl BluetoothMedia { } } A2dpCallbacks::AudioState(addr, state) => { + info!("[{}]: a2dp audio state: {:?}", DisplayAddress(&addr), state); self.a2dp_audio_state.insert(addr, state); } A2dpCallbacks::AudioConfig(addr, _config, _local_caps, a2dp_caps) => { diff --git a/system/gd/rust/shim/src/init_flags.rs b/system/gd/rust/shim/src/init_flags.rs index acf6495732..3e960e2ac0 100644 --- a/system/gd/rust/shim/src/init_flags.rs +++ b/system/gd/rust/shim/src/init_flags.rs @@ -19,7 +19,6 @@ mod ffi { fn classic_discovery_only_is_enabled() -> bool; fn device_iot_config_logging_is_enabled() -> bool; fn dynamic_avrcp_version_enhancement_is_enabled() -> bool; - fn gatt_robust_caching_client_is_enabled() -> bool; fn gatt_robust_caching_server_is_enabled() -> bool; fn get_hci_adapter() -> i32; fn get_asha_packet_drop_frequency_threshold() -> i32; @@ -28,9 +27,7 @@ mod ffi { fn irk_rotation_is_enabled() -> bool; fn leaudio_targeted_announcement_reconnection_mode_is_enabled() -> bool; fn pbap_pse_dynamic_version_upgrade_is_enabled() -> bool; - fn private_gatt_is_enabled() -> bool; fn redact_log_is_enabled() -> bool; - fn rust_event_loop_is_enabled() -> bool; fn sco_codec_select_lc3_is_enabled() -> bool; fn sco_codec_timeout_clear_is_enabled() -> bool; fn sdp_serialization_is_enabled() -> bool; diff --git a/system/gd/rust/topshim/facade/src/adapter_service.rs b/system/gd/rust/topshim/facade/src/adapter_service.rs index d9aed8dcda..06c7e18ef6 100644 --- a/system/gd/rust/topshim/facade/src/adapter_service.rs +++ b/system/gd/rust/topshim/facade/src/adapter_service.rs @@ -34,7 +34,7 @@ fn get_bt_dispatcher( BaseCallbacks::AdapterState(state) => { println!("State changed to {:?}", state); } - BaseCallbacks::SspRequest(addr, _, _, variant, passkey) => { + BaseCallbacks::SspRequest(addr, variant, passkey) => { println!( "SSP Request made for address {:?} with variant {:?} and passkey {:?}", addr.to_string(), @@ -125,7 +125,7 @@ impl AdapterService for AdapterServiceImpl { ); sink.send((rsp, WriteFlags::default())).await.unwrap(); } - BaseCallbacks::SspRequest(_, _, _, _, _) => {} + BaseCallbacks::SspRequest(_, _, _) => {} BaseCallbacks::LeRandCallback(random) => { let mut rsp = FetchEventsResponse::new(); rsp.event_type = EventType::LE_RAND.into(); diff --git a/system/gd/rust/topshim/src/btif.rs b/system/gd/rust/topshim/src/btif.rs index a4b6647e48..b161e1f01f 100644 --- a/system/gd/rust/topshim/src/btif.rs +++ b/system/gd/rust/topshim/src/btif.rs @@ -958,7 +958,7 @@ pub enum BaseCallbacks { DeviceFound(i32, Vec<BluetoothProperty>), DiscoveryState(BtDiscoveryState), PinRequest(RawAddress, String, u32, bool), - SspRequest(RawAddress, String, u32, BtSspVariant, u32), + SspRequest(RawAddress, BtSspVariant, u32), BondState(BtStatus, RawAddress, BtBondState, i32), AddressConsolidate(RawAddress, RawAddress), LeAddressAssociate(RawAddress, RawAddress), @@ -1012,9 +1012,8 @@ cb_variant!(BaseCb, pin_request_cb -> BaseCallbacks::PinRequest, let _1 = String::from(unsafe{*_1}); }); cb_variant!(BaseCb, ssp_request_cb -> BaseCallbacks::SspRequest, -*mut RawAddress, *mut bindings::bt_bdname_t, u32, bindings::bt_ssp_variant_t -> BtSspVariant, u32, { +*mut RawAddress, bindings::bt_ssp_variant_t -> BtSspVariant, u32, { let _0 = unsafe { *(_0 as *const RawAddress) }; - let _1 = String::from(unsafe{*_1}); }); cb_variant!(BaseCb, bond_state_cb -> BaseCallbacks::BondState, u32 -> BtStatus, *mut RawAddress, bindings::bt_bond_state_t -> BtBondState, i32, { diff --git a/system/gd/security/ecc/p_256_ecc_pp.cc b/system/gd/security/ecc/p_256_ecc_pp.cc index ecb805c534..9a97551da2 100644 --- a/system/gd/security/ecc/p_256_ecc_pp.cc +++ b/system/gd/security/ecc/p_256_ecc_pp.cc @@ -23,9 +23,10 @@ * ******************************************************************************/ #include "security/ecc/p_256_ecc_pp.h" -#include <stdio.h> + #include <stdlib.h> #include <string.h> + #include "security/ecc/multprecision.h" namespace bluetooth { @@ -261,4 +262,4 @@ bool ECC_ValidatePoint(const Point& pt) { } // namespace ecc } // namespace security -} // namespace bluetooth
\ No newline at end of file +} // namespace bluetooth diff --git a/system/gd/security/internal/security_manager_impl.cc b/system/gd/security/internal/security_manager_impl.cc index 453a152b1b..1f5a8a0483 100644 --- a/system/gd/security/internal/security_manager_impl.cc +++ b/system/gd/security/internal/security_manager_impl.cc @@ -815,7 +815,7 @@ void SecurityManagerImpl::InternalEnforceSecurityPolicy( l2cap::classic::SecurityEnforcementInterface::ResultCallback result_callback) { if (IsSecurityRequirementSatisfied(remote, policy)) { // Notify client immediately if already satisfied - std::move(result_callback).Invoke(true); + std::move(result_callback)(true); return; } @@ -855,7 +855,7 @@ void SecurityManagerImpl::UpdateLinkSecurityCondition(hci::AddressWithType remot log::error("No L2CAP security policy callback pending for {}", remote); return; } - std::move(entry->second.callback_).Invoke(IsSecurityRequirementSatisfied(remote, entry->second.policy_)); + std::move(entry->second.callback_)(IsSecurityRequirementSatisfied(remote, entry->second.policy_)); enforce_security_policy_callback_map_.erase(entry); } @@ -905,7 +905,7 @@ void SecurityManagerImpl::EnforceLeSecurityPolicy( case l2cap::le::SecurityPolicy::_NOT_FOR_YOU__AUTHORIZATION: break; } - result_callback.Invoke(result); + result_callback(result); } } // namespace internal } // namespace security diff --git a/system/gd/security/pairing_handler_le_legacy.cc b/system/gd/security/pairing_handler_le_legacy.cc index affc5f9121..9e28ce6a11 100644 --- a/system/gd/security/pairing_handler_le_legacy.cc +++ b/system/gd/security/pairing_handler_le_legacy.cc @@ -135,10 +135,10 @@ StkOrFailure PairingHandlerLe::DoLegacyStage2(const InitialInformations& i, cons if (IAmCentral(i)) { mrand = GenerateRandom<16>(); - // log::info("{} tk = {}", (IAmCentral(i)), base::HexEncode(tk.data(), tk.size())); - // log::info("{} mrand = {}", (IAmCentral(i)), base::HexEncode(mrand.data(), mrand.size())); - // log::info("{} pres = {}", (IAmCentral(i)), base::HexEncode(pres.data(), pres.size())); - // log::info("{} preq = {}", (IAmCentral(i)), base::HexEncode(preq.data(), preq.size())); + // log::info("{} tk = {}", IAmCentral(i), base::HexEncode(tk.data(), tk.size())); + // log::info("{} mrand = {}", IAmCentral(i), base::HexEncode(mrand.data(), mrand.size())); + // log::info("{} pres = {}", IAmCentral(i), base::HexEncode(pres.data(), pres.size())); + // log::info("{} preq = {}", IAmCentral(i), base::HexEncode(preq.data(), preq.size())); Octet16 mconfirm = crypto_toolbox::c1( tk, @@ -150,7 +150,7 @@ StkOrFailure PairingHandlerLe::DoLegacyStage2(const InitialInformations& i, cons (uint8_t)i.remote_connection_address.GetAddressType(), i.remote_connection_address.GetAddress().data()); - // log::info("{} mconfirm = {}", (IAmCentral(i)), base::HexEncode(mconfirm.data(), + // log::info("{} mconfirm = {}", IAmCentral(i), base::HexEncode(mconfirm.data(), // mconfirm.size())); log::info("Central sends Mconfirm"); @@ -173,7 +173,7 @@ StkOrFailure PairingHandlerLe::DoLegacyStage2(const InitialInformations& i, cons } srand = std::get<PairingRandomView>(random_pkt).GetRandomValue(); - // log::info("{} srand = {}", (IAmCentral(i)), base::HexEncode(srand.data(), srand.size())); + // log::info("{} srand = {}", IAmCentral(i), base::HexEncode(srand.data(), srand.size())); Octet16 sconfirm_generated = crypto_toolbox::c1( tk, diff --git a/system/gd/security/pairing_handler_le_secure_connections.cc b/system/gd/security/pairing_handler_le_secure_connections.cc index 45455f5a45..c3d1ef2ef5 100644 --- a/system/gd/security/pairing_handler_le_secure_connections.cc +++ b/system/gd/security/pairing_handler_le_secure_connections.cc @@ -171,16 +171,16 @@ Stage2ResultOrFailure PairingHandlerLe::DoSecureConnectionsStage2( std::array<uint8_t, 3> iocapB{static_cast<uint8_t>(pairing_response.GetIoCapability()), static_cast<uint8_t>(pairing_response.GetOobDataFlag()), pairing_response.GetAuthReq()}; - // log::info("{} LTK = {}", (IAmCentral(i)), base::HexEncode(ltk.data(), ltk.size())); - // log::info("{} MAC_KEY = {}", (IAmCentral(i)), base::HexEncode(mac_key.data(), mac_key.size())); - // log::info("{} Na = {}", (IAmCentral(i)), base::HexEncode(Na.data(), Na.size())); - // log::info("{} Nb = {}", (IAmCentral(i)), base::HexEncode(Nb.data(), Nb.size())); - // log::info("{} ra = {}", (IAmCentral(i)), base::HexEncode(ra.data(), ra.size())); - // log::info("{} rb = {}", (IAmCentral(i)), base::HexEncode(rb.data(), rb.size())); - // log::info("{} iocapA = {}", (IAmCentral(i)), base::HexEncode(iocapA.data(), iocapA.size())); - // log::info("{} iocapB = {}", (IAmCentral(i)), base::HexEncode(iocapB.data(), iocapB.size())); - // log::info("{} a = {}", (IAmCentral(i)), base::HexEncode(a, 7)); - // log::info("{} b = {}", (IAmCentral(i)), base::HexEncode(b, 7)); + // log::info("{} LTK = {}", IAmCentral(i), base::HexEncode(ltk.data(), ltk.size())); + // log::info("{} MAC_KEY = {}", IAmCentral(i), base::HexEncode(mac_key.data(), mac_key.size())); + // log::info("{} Na = {}", IAmCentral(i), base::HexEncode(Na.data(), Na.size())); + // log::info("{} Nb = {}", IAmCentral(i), base::HexEncode(Nb.data(), Nb.size())); + // log::info("{} ra = {}", IAmCentral(i), base::HexEncode(ra.data(), ra.size())); + // log::info("{} rb = {}", IAmCentral(i), base::HexEncode(rb.data(), rb.size())); + // log::info("{} iocapA = {}", IAmCentral(i), base::HexEncode(iocapA.data(), iocapA.size())); + // log::info("{} iocapB = {}", IAmCentral(i), base::HexEncode(iocapB.data(), iocapB.size())); + // log::info("{} a = {}", IAmCentral(i), base::HexEncode(a, 7)); + // log::info("{} b = {}", IAmCentral(i), base::HexEncode(b, 7)); Octet16 Ea = crypto_toolbox::f6(mac_key, Na, Nb, rb, iocapA.data(), a, b); diff --git a/system/gd/shim/dumpsys.cc b/system/gd/shim/dumpsys.cc index f12c0bbd5b..3baf4f4c5c 100644 --- a/system/gd/shim/dumpsys.cc +++ b/system/gd/shim/dumpsys.cc @@ -54,8 +54,7 @@ struct Dumpsys::impl { ~impl() = default; protected: - void FilterAsUser(std::string* dumpsys_data) const; - void FilterAsDeveloper(std::string* dumpsys_data) const; + void FilterSchema(std::string* dumpsys_data) const; std::string PrintAsJson(std::string* dumpsys_data) const; bool IsDebuggable() const; @@ -81,14 +80,9 @@ bool Dumpsys::impl::IsDebuggable() const { return (os::GetSystemProperty(kReadOnlyDebuggableProperty) == "1"); } -void Dumpsys::impl::FilterAsDeveloper(std::string* dumpsys_data) const { +void Dumpsys::impl::FilterSchema(std::string* dumpsys_data) const { log::assert_that(dumpsys_data != nullptr, "assert failed: dumpsys_data != nullptr"); - dumpsys::FilterInPlace(dumpsys::FilterType::AS_DEVELOPER, reflection_schema_, dumpsys_data); -} - -void Dumpsys::impl::FilterAsUser(std::string* dumpsys_data) const { - log::assert_that(dumpsys_data != nullptr, "assert failed: dumpsys_data != nullptr"); - dumpsys::FilterInPlace(dumpsys::FilterType::AS_USER, reflection_schema_, dumpsys_data); + dumpsys::FilterSchema(reflection_schema_, dumpsys_data); } std::string Dumpsys::impl::PrintAsJson(std::string* dumpsys_data) const { @@ -151,7 +145,7 @@ void Dumpsys::impl::DumpWithArgsAsync(int fd, const char** args) const { dumper.DumpState(&dumpsys_data, oss); dprintf(fd, " ----- Filtering as Developer -----\n"); - FilterAsDeveloper(&dumpsys_data); + FilterSchema(&dumpsys_data); dprintf(fd, "%s", PrintAsJson(&dumpsys_data).c_str()); } diff --git a/system/gd/stack_manager.cc b/system/gd/stack_manager.cc index 5d82a63ceb..764d07b843 100644 --- a/system/gd/stack_manager.cc +++ b/system/gd/stack_manager.cc @@ -17,7 +17,6 @@ #include "stack_manager.h" #include <bluetooth/log.h> -#include <stdio.h> #include <chrono> #include <future> diff --git a/system/include/hardware/bluetooth.h b/system/include/hardware/bluetooth.h index 683fb5525d..5a2fcf3c68 100644 --- a/system/include/hardware/bluetooth.h +++ b/system/include/hardware/bluetooth.h @@ -518,7 +518,6 @@ typedef void (*pin_request_callback)(RawAddress* remote_bd_addr, /* TODO: Passkey request callback shall not be needed for devices with display * capability. We still need support this in the stack for completeness */ typedef void (*ssp_request_callback)(RawAddress* remote_bd_addr, - bt_bdname_t* bd_name, uint32_t cod, bt_ssp_variant_t pairing_variant, uint32_t pass_key); diff --git a/system/log/src/vlog_syslog.cc b/system/log/src/vlog_syslog.cc index 904e956347..9696aee4ff 100644 --- a/system/log/src/vlog_syslog.cc +++ b/system/log/src/vlog_syslog.cc @@ -90,6 +90,12 @@ void vlog(Level level, char const* tag, source_location location, // Print to vsyslog. syslog(LOG_USER | severity, "%s", buffer.c_str()); + + // abort if the message was fatal. + // syslog does not independently abort on CRIT logs. + if (level == Level::kFatal) { + std::abort(); + } } } // namespace bluetooth::log_internal diff --git a/system/main/bte_conf.cc b/system/main/bte_conf.cc index 5b3f3766b0..d0b2b696c8 100644 --- a/system/main/bte_conf.cc +++ b/system/main/bte_conf.cc @@ -85,7 +85,7 @@ void bte_load_did_conf(const char* p_path) { } log::info("Device ID record {} : {}", i, - (record.primary_record ? "primary" : "not primary")); + record.primary_record ? "primary" : "not primary"); log::info("vendorId = {:04x}", record.vendor); log::info("vendorIdSource = {:04x}", record.vendor_id_source); log::info("product = {:04x}", record.product); diff --git a/system/main/shim/le_scanning_manager.cc b/system/main/shim/le_scanning_manager.cc index c023c6f625..50d3007088 100644 --- a/system/main/shim/le_scanning_manager.cc +++ b/system/main/shim/le_scanning_manager.cc @@ -22,7 +22,6 @@ #include <base/threading/thread.h> #include <bluetooth/log.h> #include <hardware/bluetooth.h> -#include <stdio.h> #include "btif/include/btif_common.h" #include "hci/address.h" @@ -177,7 +176,7 @@ void BleScannerInterfaceImpl::Unregister(int scanner_id) { /** Start or stop LE device scanning */ void BleScannerInterfaceImpl::Scan(bool start) { - log::info("in shim layer {}", ((start) ? "started" : "stopped")); + log::info("in shim layer {}", (start) ? "started" : "stopped"); bluetooth::shim::GetScanning()->Scan(start); if (start && !btm_cb.ble_ctr_cb.is_ble_observe_active()) { btm_cb.neighbor.le_scan = { diff --git a/system/main/shim/stack.cc b/system/main/shim/stack.cc index 008bf8bedc..69210377d7 100644 --- a/system/main/shim/stack.cc +++ b/system/main/shim/stack.cc @@ -20,7 +20,6 @@ #include <bluetooth/log.h> #include <fcntl.h> -#include <stdio.h> #include <unistd.h> #include <string> diff --git a/system/osi/src/alarm.cc b/system/osi/src/alarm.cc index 917ee1b7bb..b0206d326a 100644 --- a/system/osi/src/alarm.cc +++ b/system/osi/src/alarm.cc @@ -36,7 +36,6 @@ #include "osi/include/allocator.h" #include "osi/include/fixed_queue.h" #include "osi/include/list.h" -#include "osi/include/osi.h" #include "osi/include/thread.h" #include "osi/include/wakelock.h" #include "osi/semaphore.h" @@ -593,7 +592,7 @@ static void alarm_ready_mloop(alarm_t* alarm) { alarm_ready_generic(alarm, lock); } -static void alarm_queue_ready(fixed_queue_t* queue, UNUSED_ATTR void* context) { +static void alarm_queue_ready(fixed_queue_t* queue, void* /* context */) { log::assert_that(queue != NULL, "assert failed: queue != NULL"); std::unique_lock<std::mutex> lock(alarms_mutex); @@ -602,15 +601,13 @@ static void alarm_queue_ready(fixed_queue_t* queue, UNUSED_ATTR void* context) { } // Callback function for wake alarms and our posix timer -static void timer_callback(UNUSED_ATTR void* ptr) { - semaphore_post(alarm_expired); -} +static void timer_callback(void* /* ptr */) { semaphore_post(alarm_expired); } // Function running on |dispatcher_thread| that performs the following: // (1) Receives a signal using |alarm_exired| that the alarm has expired // (2) Dispatches the alarm callback for processing by the corresponding // thread for that alarm. -static void callback_dispatch(UNUSED_ATTR void* context) { +static void callback_dispatch(void* /* context */) { while (true) { semaphore_wait(alarm_expired); if (!dispatcher_thread_active) break; diff --git a/system/osi/src/config.cc b/system/osi/src/config.cc index 5cdc4bcde7..71b2b22bfa 100644 --- a/system/osi/src/config.cc +++ b/system/osi/src/config.cc @@ -23,7 +23,6 @@ #include <ctype.h> #include <fcntl.h> #include <libgen.h> -#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> diff --git a/system/osi/src/list.cc b/system/osi/src/list.cc index b6d3678317..00c4d59744 100644 --- a/system/osi/src/list.cc +++ b/system/osi/src/list.cc @@ -3,7 +3,6 @@ #include <bluetooth/log.h> #include "osi/include/allocator.h" -#include "osi/include/osi.h" using namespace bluetooth; @@ -189,7 +188,7 @@ list_node_t* list_begin(const list_t* list) { return list->head; } -list_node_t* list_end(UNUSED_ATTR const list_t* list) { +list_node_t* list_end(const list_t* list) { log::assert_that(list != NULL, "assert failed: list != NULL"); return NULL; } diff --git a/system/osi/src/osi.cc b/system/osi/src/osi.cc index 0fd3b0c0b7..be921a35f7 100644 --- a/system/osi/src/osi.cc +++ b/system/osi/src/osi.cc @@ -22,7 +22,6 @@ #include <bluetooth/log.h> #include <fcntl.h> -#include <stdio.h> #include <string.h> #include <sys/stat.h> #include <sys/types.h> diff --git a/system/osi/src/socket_utils/socket_local_client.cc b/system/osi/src/socket_utils/socket_local_client.cc index 7a0764d541..2c0d9c3929 100644 --- a/system/osi/src/socket_utils/socket_local_client.cc +++ b/system/osi/src/socket_utils/socket_local_client.cc @@ -109,7 +109,7 @@ error: * Used by AndroidSocketImpl */ int osi_socket_local_client_connect(int fd, const char* name, int namespaceId, - int type UNUSED_ATTR) { + int /* type */) { struct sockaddr_un addr; socklen_t alen; int err; diff --git a/system/osi/test/alarm_test.cc b/system/osi/test/alarm_test.cc index f6ec145472..b3325984da 100644 --- a/system/osi/test/alarm_test.cc +++ b/system/osi/test/alarm_test.cc @@ -81,7 +81,7 @@ class AlarmTest : public ::testing::Test { } }; -static void cb(UNUSED_ATTR void* data) { +static void cb(void* /* data */) { ++cb_counter; semaphore_post(semaphore); } diff --git a/system/osi/test/fixed_queue_test.cc b/system/osi/test/fixed_queue_test.cc index c34b5409e5..88370cb24b 100644 --- a/system/osi/test/fixed_queue_test.cc +++ b/system/osi/test/fixed_queue_test.cc @@ -6,7 +6,6 @@ #include "osi/include/allocator.h" #include "osi/include/future.h" -#include "osi/include/osi.h" #include "osi/include/thread.h" static const size_t TEST_QUEUE_SIZE = 10; @@ -36,7 +35,7 @@ static bool is_fd_readable(int fd) { } // Function for performing dequeue operations from the queue when is ready -static void fixed_queue_ready(fixed_queue_t* queue, UNUSED_ATTR void* context) { +static void fixed_queue_ready(fixed_queue_t* queue, void* /* context */) { void* msg = fixed_queue_try_dequeue(queue); EXPECT_TRUE(msg != NULL); future_ready(received_message_future, msg); diff --git a/system/profile/avrcp/Android.bp b/system/profile/avrcp/Android.bp index fa7012701e..4cb4a82b32 100644 --- a/system/profile/avrcp/Android.bp +++ b/system/profile/avrcp/Android.bp @@ -64,6 +64,9 @@ cc_test { "tests/avrcp_connection_handler_test.cc", "tests/avrcp_device_test.cc", ], + shared_libs: [ + "server_configurable_flags", + ], static_libs: [ "avrcp-target-service", "lib-bt-packets", diff --git a/system/profile/avrcp/avrcp_internal.h b/system/profile/avrcp/avrcp_internal.h index 74620dc84e..d29d785867 100644 --- a/system/profile/avrcp/avrcp_internal.h +++ b/system/profile/avrcp/avrcp_internal.h @@ -17,6 +17,7 @@ #pragma once #include "avrcp_config.h" +#include "stack/include/a2dp_api.h" #include "stack/include/avrc_api.h" #include "stack/include/bt_hdr.h" #include "stack/include/sdp_api.h" @@ -95,6 +96,9 @@ class A2dpInterface { public: virtual RawAddress active_peer() = 0; virtual bool is_peer_in_silence_mode(const RawAddress& peer_address) = 0; - + virtual void connect_audio_sink_delayed(uint8_t handle, + const RawAddress& peer_address) = 0; + virtual uint16_t find_audio_sink_service(const RawAddress& peer_address, + tA2DP_FIND_CBACK p_cback) = 0; virtual ~A2dpInterface() = default; }; diff --git a/system/profile/avrcp/connection_handler.cc b/system/profile/avrcp/connection_handler.cc index a30c6a8a6a..ca490fbfa8 100644 --- a/system/profile/avrcp/connection_handler.cc +++ b/system/profile/avrcp/connection_handler.cc @@ -18,6 +18,7 @@ #include "connection_handler.h" +#include <android_bluetooth_flags.h> #include <base/functional/bind.h> #include <bluetooth/log.h> @@ -137,11 +138,12 @@ bool ConnectionHandler::ConnectDevice(const RawAddress& bdaddr) { auto connection_lambda = [](ConnectionHandler* instance_, const RawAddress& bdaddr, uint16_t status, uint16_t version, uint16_t features) { - log::info("SDP Completed features={}", loghex(features)); + log::info("SDP Completed features=0x{:x}", features); if (status != AVRC_SUCCESS || !(features & BTA_AV_FEAT_RCCT)) { log::error( - "Failed to do SDP: status={} features={} supports controller: {}", - loghex(status), loghex(features), (features & BTA_AV_FEAT_RCCT)); + "Failed to do SDP: status=0x{:x} features=0x{:x} supports " + "controller: {}", + status, features, features & BTA_AV_FEAT_RCCT); instance_->connection_cb_.Run(std::shared_ptr<Device>()); } @@ -232,7 +234,7 @@ bool ConnectionHandler::AvrcpConnect(bool initiator, const RawAddress& bdaddr) { uint8_t handle = 0; uint16_t status = avrc_->Open(&handle, &open_cb, bdaddr); - log::info("handle={} status= {}", loghex(handle), loghex(status)); + log::info("handle=0x{:x} status= 0x{:x}", handle, status); return status == AVRC_SUCCESS; } @@ -241,8 +243,8 @@ void ConnectionHandler::InitiatorControlCb(uint8_t handle, uint8_t event, const RawAddress* peer_addr) { DCHECK(!connection_cb_.is_null()); - log::info("handle={} result={} addr={}", loghex(handle), loghex(result), - (peer_addr ? ADDRESS_TO_LOGGABLE_STR(*peer_addr) : "none")); + log::info("handle=0x{:x} result=0x{:x} addr={}", handle, result, + peer_addr ? ADDRESS_TO_LOGGABLE_STR(*peer_addr) : "none"); switch (event) { case AVRC_OPEN_IND_EVT: { @@ -333,8 +335,8 @@ void ConnectionHandler::AcceptorControlCb(uint8_t handle, uint8_t event, const RawAddress* peer_addr) { DCHECK(!connection_cb_.is_null()); - log::info("handle={} result={} addr={}", loghex(handle), loghex(result), - (peer_addr ? ADDRESS_TO_LOGGABLE_STR(*peer_addr) : "none")); + log::info("handle=0x{:x} result=0x{:x} addr={}", handle, result, + peer_addr ? ADDRESS_TO_LOGGABLE_STR(*peer_addr) : "none"); switch (event) { case AVRC_OPEN_IND_EVT: { @@ -372,7 +374,7 @@ void ConnectionHandler::AcceptorControlCb(uint8_t handle, uint8_t event, uint16_t features) { if (instance_->device_map_.find(handle) == instance_->device_map_.end()) { - log::warn("No device found for handle: {}", loghex(handle)); + log::warn("No device found for handle: 0x{:x}", handle); return; } @@ -398,13 +400,18 @@ void ConnectionHandler::AcceptorControlCb(uint8_t handle, uint8_t event, // SDP search failed, this could be due to a collision between outgoing // and incoming connection. In any case, we need to reject the current // connection. - log::error("SDP search failed for handle: {}, closing connection", - loghex(handle)); + log::error("SDP search failed for handle: 0x{:x}, closing connection", + handle); DisconnectDevice(*peer_addr); } // Open for the next incoming connection. The handle will not be the same // as this one which will be closed when the device is disconnected. AvrcpConnect(false, RawAddress::kAny); + + if (IS_FLAG_ENABLED(avrcp_connect_a2dp_delayed)) { + // Check peer audio role: src or sink and connect A2DP after 3 seconds + SdpLookupAudioRole(handle); + } } break; case AVRC_CLOSE_IND_EVT: { @@ -449,8 +456,8 @@ void ConnectionHandler::AcceptorControlCb(uint8_t handle, uint8_t event, void ConnectionHandler::MessageCb(uint8_t handle, uint8_t label, uint8_t opcode, tAVRC_MSG* p_msg) { if (device_map_.find(handle) == device_map_.end()) { - log::error("Message received for unconnected device: handle={}", - loghex(handle)); + log::error("Message received for unconnected device: handle=0x{:x}", + handle); return; } @@ -505,8 +512,8 @@ void ConnectionHandler::SdpCb(RawAddress bdaddr, SdpCallback cb, /* get profile version (if failure, version parameter is not updated) */ sdp_->FindProfileVersionInRec( sdp_record, UUID_SERVCLASS_AV_REMOTE_CONTROL, &peer_avrcp_version); - log::verbose("Device {} peer avrcp version={}", bdaddr, - loghex(peer_avrcp_version)); + log::verbose("Device {} peer avrcp version=0x{:x}", bdaddr, + peer_avrcp_version); if (peer_avrcp_version >= AVRC_REV_1_3) { // These are the standard features, another way to check this is to @@ -551,8 +558,8 @@ void ConnectionHandler::SdpCb(RawAddress bdaddr, SdpCallback cb, uint16_t peer_avrcp_target_version = 0; sdp_->FindProfileVersionInRec(sdp_record, UUID_SERVCLASS_AV_REMOTE_CONTROL, &peer_avrcp_target_version); - log::verbose("Device {} peer avrcp target version={}", bdaddr, - loghex(peer_avrcp_target_version)); + log::verbose("Device {} peer avrcp target version=0x{:x}", bdaddr, + peer_avrcp_target_version); if ((sdp_->FindAttributeInRec(sdp_record, ATTR_ID_BT_PROFILE_DESC_LIST)) != NULL) { @@ -594,7 +601,7 @@ void ConnectionHandler::SendMessage( (uint8_t)(::bluetooth::Packet::Specialize<Packet>(packet)->GetCType()); } - log::info("SendMessage to handle={}", loghex(handle)); + log::info("SendMessage to handle=0x{:x}", handle); BT_HDR* pkt = (BT_HDR*)osi_malloc(BT_DEFAULT_BUFFER_SIZE); @@ -642,5 +649,40 @@ void ConnectionHandler::RegisterVolChanged(const RawAddress& bdaddr) { } } +bool ConnectionHandler::SdpLookupAudioRole(uint16_t handle) { + if (device_map_.find(handle) == device_map_.end()) { + log::warn("No device found for handle: {}", loghex(handle)); + return false; + } + auto device = device_map_[handle]; + + log::info( + "Performing SDP for AUDIO_SINK on connected device: address={}, " + "handle={}", + ADDRESS_TO_LOGGABLE_STR(device->GetAddress()), handle); + + return device->find_sink_service( + base::Bind(&ConnectionHandler::SdpLookupAudioRoleCb, + weak_ptr_factory_.GetWeakPtr(), handle)); +} + +void ConnectionHandler::SdpLookupAudioRoleCb(uint16_t handle, bool found, + tA2DP_Service* p_service, + const RawAddress& peer_address) { + if (device_map_.find(handle) == device_map_.end()) { + log::warn("No device found for handle: {}", loghex(handle)); + return; + } + auto device = device_map_[handle]; + + log::debug("SDP callback for address={}, handle={}, AUDIO_SINK {}", + ADDRESS_TO_LOGGABLE_STR(device->GetAddress()), handle, + found ? "found" : "not found"); + + if (found) { + device->connect_a2dp_sink_delayed(handle); + } +} + } // namespace avrcp } // namespace bluetooth diff --git a/system/profile/avrcp/connection_handler.h b/system/profile/avrcp/connection_handler.h index 897541d31d..46346aee92 100644 --- a/system/profile/avrcp/connection_handler.h +++ b/system/profile/avrcp/connection_handler.h @@ -172,6 +172,13 @@ class ConnectionHandler { void SendMessage(uint8_t handle, uint8_t label, bool browse, std::unique_ptr<::bluetooth::PacketBuilder> message); + // Check peer role: audio src or sink. If any role supported send + // delayed a2dp connect request + bool SdpLookupAudioRole(uint16_t handle); + void SdpLookupAudioRoleCb(uint16_t handle, bool found, + tA2DP_Service* p_service, + const RawAddress& peer_address); + base::WeakPtrFactory<ConnectionHandler> weak_ptr_factory_; }; diff --git a/system/profile/avrcp/device.cc b/system/profile/avrcp/device.cc index 89de0ad464..cdd350b9bc 100644 --- a/system/profile/avrcp/device.cc +++ b/system/profile/avrcp/device.cc @@ -1018,7 +1018,7 @@ void Device::ListPlayerApplicationSettingValuesResponse( log::verbose("value={}", static_cast<PlayerShuffleValue>(value)); } } else { - log::verbose("value={}", loghex(values.at(0))); + log::verbose("value=0x{:x}", values.at(0)); } } @@ -1038,7 +1038,7 @@ void Device::GetPlayerApplicationSettingValueResponse( } else if (attributes[i] == PlayerAttribute::SHUFFLE) { log::verbose("value={}", static_cast<PlayerShuffleValue>(values[i])); } else { - log::verbose("value={}", loghex(values.at(0))); + log::verbose("value=0x{:x}", values.at(0)); } } @@ -1216,8 +1216,7 @@ void Device::HandleChangePath(uint8_t label, return; } - log::verbose("direction={} uid={}", pkt->GetDirection(), - loghex(pkt->GetUid())); + log::verbose("direction={} uid=0x{:x}", pkt->GetDirection(), pkt->GetUid()); if (pkt->GetDirection() == Direction::DOWN && vfs_ids_.get_media_id(pkt->GetUid()) == "") { @@ -1272,8 +1271,8 @@ void Device::HandleGetItemAttributes( return; } - log::verbose("scope={} uid={} uid counter={}", pkt->GetScope(), - loghex(pkt->GetUid()), loghex(pkt->GetUidCounter())); + log::verbose("scope={} uid=0x{:x} uid counter=0x{:x}", pkt->GetScope(), + pkt->GetUid(), pkt->GetUidCounter()); if (pkt->GetUidCounter() != 0x0000) { // For database unaware player, use 0 log::warn("{}: UidCounter is invalid", address_); auto builder = GetItemAttributesResponseBuilder::MakeBuilder( @@ -1307,7 +1306,7 @@ void Device::HandleGetItemAttributes( void Device::GetItemAttributesNowPlayingResponse( uint8_t label, std::shared_ptr<GetItemAttributesRequest> pkt, std::string curr_media_id, std::vector<SongInfo> song_list) { - log::verbose("uid={}", loghex(pkt->GetUid())); + log::verbose("uid=0x{:x}", pkt->GetUid()); auto builder = GetItemAttributesResponseBuilder::MakeBuilder(Status::NO_ERROR, browse_mtu_); @@ -1356,7 +1355,7 @@ void Device::GetItemAttributesNowPlayingResponse( void Device::GetItemAttributesVFSResponse( uint8_t label, std::shared_ptr<GetItemAttributesRequest> pkt, std::vector<ListItem> item_list) { - log::verbose("uid={}", loghex(pkt->GetUid())); + log::verbose("uid=0x{:x}", pkt->GetUid()); auto media_id = vfs_ids_.get_media_id(pkt->GetUid()); if (media_id == "") { diff --git a/system/profile/avrcp/device.h b/system/profile/avrcp/device.h index 1b4288941b..2d1ff3dfa7 100644 --- a/system/profile/avrcp/device.h +++ b/system/profile/avrcp/device.h @@ -327,6 +327,17 @@ class Device { active_labels_.erase(label); send_message_cb_.Run(label, browse, std::move(message)); } + + // A2DP interface implementation + void connect_a2dp_sink_delayed(uint8_t handle) const { + a2dp_interface_->connect_audio_sink_delayed(handle, address_); + } + + bool find_sink_service(tA2DP_FIND_CBACK p_cback) const { + return a2dp_interface_->find_audio_sink_service(address_, p_cback) == + A2DP_SUCCESS; + } + base::WeakPtrFactory<Device> weak_ptr_factory_; // TODO (apanicke): Initialize all the variables in the constructor. diff --git a/system/profile/avrcp/tests/avrcp_device_fuzz/avrcp_device_fuzz.cc b/system/profile/avrcp/tests/avrcp_device_fuzz/avrcp_device_fuzz.cc index df91e77b39..cf30d98cd9 100644 --- a/system/profile/avrcp/tests/avrcp_device_fuzz/avrcp_device_fuzz.cc +++ b/system/profile/avrcp/tests/avrcp_device_fuzz/avrcp_device_fuzz.cc @@ -5,6 +5,7 @@ #include "device.h" #include "internal_include/stack_config.h" #include "packet_test_helper.h" +#include "stack/include/a2dp_api.h" #include "types/raw_address.h" bool btif_av_src_sink_coexist_enabled(void) { return true; } @@ -65,6 +66,14 @@ class FakeA2dpInterface : public A2dpInterface { virtual bool is_peer_in_silence_mode(const RawAddress& peer_address) { return false; } + virtual void connect_audio_sink_delayed(uint8_t handle, + const RawAddress& peer_address) { + return; + } + virtual uint16_t find_audio_sink_service(const RawAddress& peer_address, + tA2DP_FIND_CBACK p_cback) override { + return 0; + } }; bool get_pts_avrcp_test(void) { return false; } diff --git a/system/profile/avrcp/tests/avrcp_test_helper.h b/system/profile/avrcp/tests/avrcp_test_helper.h index 5cf75b9dd4..2a3064d5d2 100644 --- a/system/profile/avrcp/tests/avrcp_test_helper.h +++ b/system/profile/avrcp/tests/avrcp_test_helper.h @@ -23,6 +23,7 @@ #include "avrcp.h" #include "avrcp_internal.h" #include "avrcp_packet.h" +#include "stack/include/a2dp_api.h" #include "stack/include/bt_hdr.h" #include "tests/packet_test_helper.h" #include "types/bluetooth/uuid.h" @@ -97,6 +98,9 @@ class MockA2dpInterface : public A2dpInterface { MOCK_METHOD1(event_close, void(const RawAddress&)); MOCK_METHOD0(active_peer, RawAddress()); MOCK_METHOD1(is_peer_in_silence_mode, bool(const RawAddress&)); + MOCK_METHOD2(connect_audio_sink_delayed, void(uint8_t, const RawAddress&)); + MOCK_METHOD2(find_audio_sink_service, + uint16_t(const RawAddress&, tA2DP_FIND_CBACK)); }; class MockSdpInterface : public SdpInterface { diff --git a/system/rust/src/core/mod.rs b/system/rust/src/core/mod.rs index 51e24535be..2f48f19619 100644 --- a/system/rust/src/core/mod.rs +++ b/system/rust/src/core/mod.rs @@ -8,7 +8,6 @@ pub mod uuid; use std::{pin::Pin, rc::Rc, thread}; -use bt_common::init_flags::rust_event_loop_is_enabled; use cxx::UniquePtr; use crate::{ @@ -24,18 +23,16 @@ fn start( le_acl_manager: UniquePtr<LeAclManagerShim>, on_started: Pin<&'static mut Future>, ) { - if rust_event_loop_is_enabled() { - thread::spawn(move || { - GlobalModuleRegistry::start( - Rc::new(GattCallbacksImpl(gatt_server_callbacks)), - Rc::new(AttTransportImpl()), - LeAclManagerImpl(le_acl_manager), - || { - future_ready(on_started); - }, - ); - }); - } + thread::spawn(move || { + GlobalModuleRegistry::start( + Rc::new(GattCallbacksImpl(gatt_server_callbacks)), + Rc::new(AttTransportImpl()), + LeAclManagerImpl(le_acl_manager), + || { + future_ready(on_started); + }, + ); + }); } fn stop() { diff --git a/system/rust/src/gatt/ffi.rs b/system/rust/src/gatt/ffi.rs index 5a0f3b548e..d21c23dd1c 100644 --- a/system/rust/src/gatt/ffi.rs +++ b/system/rust/src/gatt/ffi.rs @@ -4,9 +4,7 @@ use std::iter::Peekable; use anyhow::{bail, Result}; -use bt_common::init_flags::{ - always_use_private_gatt_for_debugging_is_enabled, rust_event_loop_is_enabled, -}; +use bt_common::init_flags::always_use_private_gatt_for_debugging_is_enabled; use cxx::UniquePtr; pub use inner::*; use log::{error, info, trace, warn}; @@ -283,10 +281,6 @@ impl AttTransport for AttTransportImpl { } fn open_server(server_id: u8) { - if !rust_event_loop_is_enabled() { - return; - } - let server_id = ServerId(server_id); do_in_rust_thread(move |modules| { @@ -303,10 +297,6 @@ fn open_server(server_id: u8) { } fn close_server(server_id: u8) { - if !rust_event_loop_is_enabled() { - return; - } - let server_id = ServerId(server_id); do_in_rust_thread(move |modules| { @@ -368,17 +358,15 @@ fn records_to_service(service_records: &[GattRecord]) -> Result<GattServiceWithH } let Some((handle, uuid)) = service_handle_uuid else { - bail!("got service registration but with no primary service! {characteristics:?}".to_string()) + bail!( + "got service registration but with no primary service! {characteristics:?}".to_string() + ) }; Ok(GattServiceWithHandle { handle: AttHandle(handle), type_: uuid, characteristics }) } fn add_service(server_id: u8, service_records: Vec<GattRecord>) { - if !rust_event_loop_is_enabled() { - return; - } - // marshal into the form expected by GattModule let server_id = ServerId(server_id); @@ -408,10 +396,6 @@ fn add_service(server_id: u8, service_records: Vec<GattRecord>) { } fn remove_service(server_id: u8, service_handle: u16) { - if !rust_event_loop_is_enabled() { - return; - } - let server_id = ServerId(server_id); let service_handle = AttHandle(service_handle); do_in_rust_thread(move |modules| { @@ -428,18 +412,10 @@ fn remove_service(server_id: u8, service_handle: u16) { } fn is_connection_isolated(conn_id: u16) -> bool { - if !rust_event_loop_is_enabled() { - return false; - } - with_arbiter(|arbiter| arbiter.is_connection_isolated(ConnectionId(conn_id).get_tcb_idx())) } fn send_response(_server_id: u8, conn_id: u16, trans_id: u32, status: u8, value: &[u8]) { - if !rust_event_loop_is_enabled() { - return; - } - // TODO(aryarahul): fixup error codes to allow app-specific values (i.e. don't // make it an enum in PDL) let value = if status == 0 { @@ -463,10 +439,6 @@ fn send_response(_server_id: u8, conn_id: u16, trans_id: u32, status: u8, value: } fn send_indication(_server_id: u8, handle: u16, conn_id: u16, value: &[u8]) { - if !rust_event_loop_is_enabled() { - return; - } - let handle = AttHandle(handle); let conn_id = ConnectionId(conn_id); let value = AttAttributeDataChild::RawData(value.into()); @@ -488,10 +460,6 @@ fn send_indication(_server_id: u8, handle: u16, conn_id: u16, value: &[u8]) { } fn associate_server_with_advertiser(server_id: u8, advertiser_id: u8) { - if !rust_event_loop_is_enabled() { - return; - } - let server_id = ServerId(server_id); let advertiser_id = AdvertiserId(advertiser_id); do_in_rust_thread(move |modules| { @@ -503,10 +471,6 @@ fn associate_server_with_advertiser(server_id: u8, advertiser_id: u8) { } fn clear_advertiser(advertiser_id: u8) { - if !rust_event_loop_is_enabled() { - return; - } - let advertiser_id = AdvertiserId(advertiser_id); do_in_rust_thread(move |modules| { diff --git a/system/rust/src/lib.rs b/system/rust/src/lib.rs index 4693320516..b3361bad1e 100644 --- a/system/rust/src/lib.rs +++ b/system/rust/src/lib.rs @@ -15,7 +15,6 @@ //! The core event loop for Rust modules. Here Rust modules are started in //! dependency order. -use bt_common::init_flags::rust_event_loop_is_enabled; use connection::le_manager::InactiveLeAclManager; use gatt::{channel::AttTransport, GattCallbacks}; use log::{info, warn}; @@ -160,10 +159,6 @@ pub fn do_in_rust_thread<F>(f: F) where F: for<'a> FnOnce(&'a mut ModuleViews) + Send + 'static, { - if !rust_event_loop_is_enabled() { - warn!("ignoring do_in_rust_thread() invocation since Rust loop is inactive"); - return; - } let ret = MAIN_THREAD_TX.with(|tx| tx.send(MainThreadTxMessage::Callback(Box::new(f)))); if ret.is_err() { panic!("Rust call failed"); diff --git a/system/stack/a2dp/a2dp_aac_encoder.cc b/system/stack/a2dp/a2dp_aac_encoder.cc index 6cfdd9ecc9..d8e8d5b843 100644 --- a/system/stack/a2dp/a2dp_aac_encoder.cc +++ b/system/stack/a2dp/a2dp_aac_encoder.cc @@ -21,7 +21,6 @@ #include <aacenc_lib.h> #include <bluetooth/log.h> #include <inttypes.h> -#include <stdio.h> #include <string.h> #include "a2dp_aac.h" diff --git a/system/stack/a2dp/a2dp_aac_encoder_linux.cc b/system/stack/a2dp/a2dp_aac_encoder_linux.cc index 6c23efa51d..223b99a55f 100644 --- a/system/stack/a2dp/a2dp_aac_encoder_linux.cc +++ b/system/stack/a2dp/a2dp_aac_encoder_linux.cc @@ -18,7 +18,6 @@ #include <bluetooth/log.h> #include <inttypes.h> -#include <stdio.h> #include <string.h> #include <string> diff --git a/system/stack/a2dp/a2dp_sbc_encoder.cc b/system/stack/a2dp/a2dp_sbc_encoder.cc index 61cd6e4ffa..731389efbe 100644 --- a/system/stack/a2dp/a2dp_sbc_encoder.cc +++ b/system/stack/a2dp/a2dp_sbc_encoder.cc @@ -23,7 +23,6 @@ #include <bluetooth/log.h> #include <limits.h> -#include <stdio.h> #include <string.h> #include "a2dp_sbc.h" diff --git a/system/stack/a2dp/a2dp_vendor_aptx_encoder.cc b/system/stack/a2dp/a2dp_vendor_aptx_encoder.cc index 6a7e0aed7b..2787170e4b 100644 --- a/system/stack/a2dp/a2dp_vendor_aptx_encoder.cc +++ b/system/stack/a2dp/a2dp_vendor_aptx_encoder.cc @@ -21,7 +21,6 @@ #include <bluetooth/log.h> #include <dlfcn.h> #include <inttypes.h> -#include <stdio.h> #include <string.h> #include "a2dp_vendor.h" diff --git a/system/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc b/system/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc index 0ebeca3cd1..9f09ce04af 100644 --- a/system/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc +++ b/system/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc @@ -21,7 +21,6 @@ #include <bluetooth/log.h> #include <dlfcn.h> #include <inttypes.h> -#include <stdio.h> #include <string.h> #include "a2dp_vendor.h" diff --git a/system/stack/a2dp/a2dp_vendor_ldac_decoder.cc b/system/stack/a2dp/a2dp_vendor_ldac_decoder.cc index 45e0b18c23..ab72832583 100644 --- a/system/stack/a2dp/a2dp_vendor_ldac_decoder.cc +++ b/system/stack/a2dp/a2dp_vendor_ldac_decoder.cc @@ -23,7 +23,6 @@ #include <ldacBT.h> #include <ldacBT_bco_for_fluoride.h> #include <pthread.h> -#include <stdio.h> #include <string.h> #include "a2dp_vendor_ldac.h" diff --git a/system/stack/a2dp/a2dp_vendor_ldac_encoder.cc b/system/stack/a2dp/a2dp_vendor_ldac_encoder.cc index 7faee577d8..9bc6bda3e9 100644 --- a/system/stack/a2dp/a2dp_vendor_ldac_encoder.cc +++ b/system/stack/a2dp/a2dp_vendor_ldac_encoder.cc @@ -26,7 +26,6 @@ #include <dlfcn.h> #include <inttypes.h> #include <ldacBT_abr.h> -#include <stdio.h> #include <string.h> #include "a2dp_vendor_ldac.h" diff --git a/system/stack/a2dp/a2dp_vendor_opus.cc b/system/stack/a2dp/a2dp_vendor_opus.cc index 4937547e67..5441ef9d96 100644 --- a/system/stack/a2dp/a2dp_vendor_opus.cc +++ b/system/stack/a2dp/a2dp_vendor_opus.cc @@ -149,19 +149,19 @@ static tA2DP_STATUS A2DP_BuildInfoOpus(uint8_t media_type, *p_result = 0; *p_result |= (uint8_t)(p_ie->channelMode) & A2DP_OPUS_CHANNEL_MODE_MASK; if ((*p_result & A2DP_OPUS_CHANNEL_MODE_MASK) == 0) { - log::error("channelmode 0x{:X} setting failed", (p_ie->channelMode)); + log::error("channelmode 0x{:X} setting failed", p_ie->channelMode); return A2DP_INVALID_PARAMS; } *p_result |= ((uint8_t)(p_ie->future1) & A2DP_OPUS_FRAMESIZE_MASK); if ((*p_result & A2DP_OPUS_FRAMESIZE_MASK) == 0) { - log::error("frameSize 0x{:X} setting failed", (p_ie->future1)); + log::error("frameSize 0x{:X} setting failed", p_ie->future1); return A2DP_INVALID_PARAMS; } *p_result |= ((uint8_t)(p_ie->sampleRate) & A2DP_OPUS_SAMPLING_FREQ_MASK); if ((*p_result & A2DP_OPUS_SAMPLING_FREQ_MASK) == 0) { - log::error("samplerate 0x{:X} setting failed", (p_ie->sampleRate)); + log::error("samplerate 0x{:X} setting failed", p_ie->sampleRate); return A2DP_INVALID_PARAMS; } diff --git a/system/stack/a2dp/a2dp_vendor_opus_encoder.cc b/system/stack/a2dp/a2dp_vendor_opus_encoder.cc index 92d449ffa5..5356b22c85 100644 --- a/system/stack/a2dp/a2dp_vendor_opus_encoder.cc +++ b/system/stack/a2dp/a2dp_vendor_opus_encoder.cc @@ -21,7 +21,6 @@ #include <bluetooth/log.h> #include <dlfcn.h> #include <opus.h> -#include <stdio.h> #include <string.h> #include "a2dp_vendor.h" diff --git a/system/stack/acl/btm_acl.cc b/system/stack/acl/btm_acl.cc index bc6743610c..227fca65c3 100644 --- a/system/stack/acl/btm_acl.cc +++ b/system/stack/acl/btm_acl.cc @@ -649,9 +649,9 @@ void btm_acl_encrypt_change(uint16_t handle, uint8_t /* status */, if (bluetooth::os::ParameterProvider::IsCommonCriteriaMode()) { if (p->is_encrypted && !encr_enable) { log::error( - "attempting to decrypt encrypted connection, disconnecting. " - "handle: {}", - loghex(handle)); + "attempting to decrypt encrypted connection, disconnecting. handle: " + "0x{:x}", + handle); acl_disconnect_from_handle(handle, HCI_ERR_HOST_REJECT_SECURITY, "stack::btu::btu_hcif::read_drop_encryption " diff --git a/system/stack/arbiter/acl_arbiter.cc b/system/stack/arbiter/acl_arbiter.cc index c80f98a74a..a67a7e2f58 100644 --- a/system/stack/arbiter/acl_arbiter.cc +++ b/system/stack/arbiter/acl_arbiter.cc @@ -30,39 +30,6 @@ namespace bluetooth { namespace shim { namespace arbiter { -class PassthroughAclArbiter : public AclArbiter { - public: - virtual void OnLeConnect(uint8_t tcb_idx, uint16_t advertiser_id) override { - // no-op - } - - virtual void OnLeDisconnect(uint8_t tcb_idx) override { - // no-op - } - - virtual InterceptAction InterceptAttPacket(uint8_t tcb_idx, - const BT_HDR* packet) override { - return InterceptAction::FORWARD; - } - - virtual void OnOutgoingMtuReq(uint8_t tcb_idx) override { - // no-op - } - - virtual void OnIncomingMtuResp(uint8_t tcb_idx, size_t mtu) { - // no-op - } - - virtual void OnIncomingMtuReq(uint8_t tcb_idx, size_t mtu) { - // no-op - } - - static PassthroughAclArbiter& Get() { - static auto singleton = PassthroughAclArbiter(); - return singleton; - } -}; - namespace { struct RustArbiterCallbacks { ::rust::Fn<void(uint8_t tcb_idx, uint8_t advertiser)> on_le_connect; @@ -77,68 +44,61 @@ struct RustArbiterCallbacks { RustArbiterCallbacks callbacks_{}; } // namespace -class RustGattAclArbiter : public AclArbiter { - public: - virtual void OnLeConnect(uint8_t tcb_idx, uint16_t advertiser_id) override { - log::info("Notifying Rust of LE connection"); - callbacks_.on_le_connect(tcb_idx, advertiser_id); - } +void AclArbiter::OnLeConnect(uint8_t tcb_idx, uint16_t advertiser_id) { + log::info("Notifying Rust of LE connection"); + callbacks_.on_le_connect(tcb_idx, advertiser_id); +} - virtual void OnLeDisconnect(uint8_t tcb_idx) override { - log::info("Notifying Rust of LE disconnection"); - callbacks_.on_le_disconnect(tcb_idx); - } +void AclArbiter::OnLeDisconnect(uint8_t tcb_idx) { + log::info("Notifying Rust of LE disconnection"); + callbacks_.on_le_disconnect(tcb_idx); +} - virtual InterceptAction InterceptAttPacket(uint8_t tcb_idx, - const BT_HDR* packet) override { - log::debug("Intercepting ATT packet and forwarding to Rust"); +InterceptAction AclArbiter::InterceptAttPacket(uint8_t tcb_idx, + const BT_HDR* packet) { + log::debug("Intercepting ATT packet and forwarding to Rust"); - uint8_t* packet_start = (uint8_t*)(packet + 1) + packet->offset; - uint8_t* packet_end = packet_start + packet->len; + uint8_t* packet_start = (uint8_t*)(packet + 1) + packet->offset; + uint8_t* packet_end = packet_start + packet->len; - auto vec = ::rust::Vec<uint8_t>(); - std::copy(packet_start, packet_end, std::back_inserter(vec)); - return callbacks_.intercept_packet(tcb_idx, std::move(vec)); - } + auto vec = ::rust::Vec<uint8_t>(); + std::copy(packet_start, packet_end, std::back_inserter(vec)); + return callbacks_.intercept_packet(tcb_idx, std::move(vec)); +} - virtual void OnOutgoingMtuReq(uint8_t tcb_idx) override { - log::debug("Notifying Rust of outgoing MTU request"); - callbacks_.on_outgoing_mtu_req(tcb_idx); - } +void AclArbiter::OnOutgoingMtuReq(uint8_t tcb_idx) { + log::debug("Notifying Rust of outgoing MTU request"); + callbacks_.on_outgoing_mtu_req(tcb_idx); +} - virtual void OnIncomingMtuResp(uint8_t tcb_idx, size_t mtu) { - log::debug("Notifying Rust of incoming MTU response {}", mtu); - callbacks_.on_incoming_mtu_resp(tcb_idx, mtu); - } +void AclArbiter::OnIncomingMtuResp(uint8_t tcb_idx, size_t mtu) { + log::debug("Notifying Rust of incoming MTU response {}", mtu); + callbacks_.on_incoming_mtu_resp(tcb_idx, mtu); +} - virtual void OnIncomingMtuReq(uint8_t tcb_idx, size_t mtu) { - log::debug("Notifying Rust of incoming MTU request {}", mtu); - callbacks_.on_incoming_mtu_req(tcb_idx, mtu); - } +void AclArbiter::OnIncomingMtuReq(uint8_t tcb_idx, size_t mtu) { + log::debug("Notifying Rust of incoming MTU request {}", mtu); + callbacks_.on_incoming_mtu_req(tcb_idx, mtu); +} - void SendPacketToPeer(uint8_t tcb_idx, ::rust::Vec<uint8_t> buffer) { - tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx); - if (p_tcb != nullptr) { - BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR) + buffer.size() + - L2CAP_MIN_OFFSET); - if (p_buf == nullptr) { - log::fatal("OOM when sending packet"); - } - auto p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET; - std::copy(buffer.begin(), buffer.end(), p); - p_buf->offset = L2CAP_MIN_OFFSET; - p_buf->len = buffer.size(); - L2CA_SendFixedChnlData(L2CAP_ATT_CID, p_tcb->peer_bda, p_buf); - } else { - log::error("Dropping packet since connection no longer exists"); +void AclArbiter::SendPacketToPeer(uint8_t tcb_idx, + ::rust::Vec<uint8_t> buffer) { + tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx); + if (p_tcb != nullptr) { + BT_HDR* p_buf = + (BT_HDR*)osi_malloc(sizeof(BT_HDR) + buffer.size() + L2CAP_MIN_OFFSET); + if (p_buf == nullptr) { + log::fatal("OOM when sending packet"); } + auto p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET; + std::copy(buffer.begin(), buffer.end(), p); + p_buf->offset = L2CAP_MIN_OFFSET; + p_buf->len = buffer.size(); + L2CA_SendFixedChnlData(L2CAP_ATT_CID, p_tcb->peer_bda, p_buf); + } else { + log::error("Dropping packet since connection no longer exists"); } - - static RustGattAclArbiter& Get() { - static auto singleton = RustGattAclArbiter(); - return singleton; - } -}; +} void StoreCallbacksFromRust( ::rust::Fn<void(uint8_t tcb_idx, uint8_t advertiser)> on_le_connect, @@ -154,16 +114,14 @@ void StoreCallbacksFromRust( } void SendPacketToPeer(uint8_t tcb_idx, ::rust::Vec<uint8_t> buffer) { - do_in_main_thread(FROM_HERE, - base::BindOnce(&RustGattAclArbiter::SendPacketToPeer, - base::Unretained(&RustGattAclArbiter::Get()), - tcb_idx, std::move(buffer))); + do_in_main_thread(FROM_HERE, base::BindOnce(&AclArbiter::SendPacketToPeer, + base::Unretained(&GetArbiter()), + tcb_idx, std::move(buffer))); } AclArbiter& GetArbiter() { - return common::init_flags::private_gatt_is_enabled() - ? static_cast<AclArbiter&>(RustGattAclArbiter::Get()) - : static_cast<AclArbiter&>(PassthroughAclArbiter::Get()); + static auto singleton = AclArbiter(); + return singleton; } } // namespace arbiter diff --git a/system/stack/arbiter/acl_arbiter.h b/system/stack/arbiter/acl_arbiter.h index 485adb6b80..65c6df796c 100644 --- a/system/stack/arbiter/acl_arbiter.h +++ b/system/stack/arbiter/acl_arbiter.h @@ -39,19 +39,20 @@ enum class InterceptAction { class AclArbiter { public: - virtual void OnLeConnect(uint8_t tcb_idx, uint16_t advertiser_id) = 0; - virtual void OnLeDisconnect(uint8_t tcb_idx) = 0; - virtual InterceptAction InterceptAttPacket(uint8_t tcb_idx, - const BT_HDR* packet) = 0; + void OnLeConnect(uint8_t tcb_idx, uint16_t advertiser_id); + void OnLeDisconnect(uint8_t tcb_idx); + InterceptAction InterceptAttPacket(uint8_t tcb_idx, const BT_HDR* packet); - virtual void OnOutgoingMtuReq(uint8_t tcb_idx) = 0; - virtual void OnIncomingMtuResp(uint8_t tcb_idx, size_t mtu) = 0; - virtual void OnIncomingMtuReq(uint8_t tcb_idx, size_t mtu) = 0; + void OnOutgoingMtuReq(uint8_t tcb_idx); + void OnIncomingMtuResp(uint8_t tcb_idx, size_t mtu); + void OnIncomingMtuReq(uint8_t tcb_idx, size_t mtu); + + void SendPacketToPeer(uint8_t tcb_idx, ::rust::Vec<uint8_t> buffer); AclArbiter() = default; AclArbiter(AclArbiter&& other) = default; AclArbiter& operator=(AclArbiter&& other) = default; - virtual ~AclArbiter() = default; + ~AclArbiter() = default; }; void StoreCallbacksFromRust( diff --git a/system/stack/avdt/avdt_ad.cc b/system/stack/avdt/avdt_ad.cc index 6bc4f1482b..ceba0d6d89 100644 --- a/system/stack/avdt/avdt_ad.cc +++ b/system/stack/avdt/avdt_ad.cc @@ -547,7 +547,7 @@ void avdt_ad_open_req(uint8_t type, AvdtpCcb* p_ccb, AvdtpScb* p_scb, if (lcid != 0) { /* if connect req ok, store tcid in lcid table */ avdtp_cb.ad.lcid_tbl[lcid] = avdt_ad_tc_tbl_to_idx(p_tbl); - log::verbose("avdtp_cb.ad.lcid_tbl[{}] = {}", (lcid), + log::verbose("avdtp_cb.ad.lcid_tbl[{}] = {}", lcid, avdt_ad_tc_tbl_to_idx(p_tbl)); avdtp_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = lcid; diff --git a/system/stack/avdt/avdt_api.cc b/system/stack/avdt/avdt_api.cc index 58be182e09..a1a64aa039 100644 --- a/system/stack/avdt/avdt_api.cc +++ b/system/stack/avdt/avdt_api.cc @@ -588,7 +588,7 @@ uint16_t AVDT_StartReq(uint8_t* p_handles, uint8_t num_handles) { log::error("result={} num_handles={} invalid", result, num_handles); } else { log::error("result={} avdt_handle={}", result, - (i < num_handles ? p_handles[i] : p_handles[num_handles - 1])); + i < num_handles ? p_handles[i] : p_handles[num_handles - 1]); } } return result; @@ -646,7 +646,7 @@ uint16_t AVDT_SuspendReq(uint8_t* p_handles, uint8_t num_handles) { log::error("result={} num_handles={} invalid", result, num_handles); } else { log::error("result={} avdt_handle={}", result, - (i < num_handles ? p_handles[i] : p_handles[num_handles - 1])); + i < num_handles ? p_handles[i] : p_handles[num_handles - 1]); } } return result; diff --git a/system/stack/bnep/bnep_utils.cc b/system/stack/bnep/bnep_utils.cc index edf1592827..f85bf57627 100644 --- a/system/stack/bnep/bnep_utils.cc +++ b/system/stack/bnep/bnep_utils.cc @@ -23,7 +23,6 @@ ******************************************************************************/ #include <bluetooth/log.h> -#include <stdio.h> #include <string.h> #include "bnep_int.h" diff --git a/system/stack/btm/btm_ble_gap.cc b/system/stack/btm/btm_ble_gap.cc index 137232ea69..ab09ac7387 100644 --- a/system/stack/btm/btm_ble_gap.cc +++ b/system/stack/btm/btm_ble_gap.cc @@ -662,7 +662,7 @@ static void btm_get_dynamic_audio_buffer_vsc_cmpl_cback( // Audio_Codec_Buffer_Time | 192 octet| Default/Max/Min buffer time STREAM_TO_UINT8(status, p_event_param_buf); if (status != HCI_SUCCESS) { - log::error("Fail to configure DFTB. status: {}", loghex(status)); + log::error("Fail to configure DFTB. status: 0x{:x}", status); return; } @@ -673,11 +673,11 @@ static void btm_get_dynamic_audio_buffer_vsc_cmpl_cback( } STREAM_TO_UINT8(opcode, p_event_param_buf); - log::info("opcode = {}", loghex(opcode)); + log::info("opcode = 0x{:x}", opcode); if (opcode == 0x01) { STREAM_TO_UINT32(codec_mask, p_event_param_buf); - log::info("codec_mask = {}", loghex(codec_mask)); + log::info("codec_mask = 0x{:x}", codec_mask); for (int i = 0; i < BTM_CODEC_TYPE_MAX_RECORDS; i++) { STREAM_TO_UINT16(btm_cb.dynamic_audio_buffer_cb[i].default_buffer_time, diff --git a/system/stack/btm/btm_devctl.cc b/system/stack/btm/btm_devctl.cc index 59e7de8c1d..a3becc321b 100644 --- a/system/stack/btm/btm_devctl.cc +++ b/system/stack/btm/btm_devctl.cc @@ -670,7 +670,7 @@ tBTM_STATUS BTM_DeleteStoredLinkKey(const RawAddress* bd_addr, bool delete_all_flag = !bd_addr; log::verbose("BTM: BTM_DeleteStoredLinkKey: delete_all_flag: {}", - delete_all_flag ? "true" : "false"); + delete_all_flag); btm_sec_cb.devcb.p_stored_link_key_cmpl_cb = p_cb; if (!bd_addr) { diff --git a/system/stack/btm/btm_inq.cc b/system/stack/btm/btm_inq.cc index 0681153911..1ec035f64c 100644 --- a/system/stack/btm/btm_inq.cc +++ b/system/stack/btm/btm_inq.cc @@ -28,7 +28,6 @@ #include <android_bluetooth_flags.h> #include <bluetooth/log.h> #include <stddef.h> -#include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/system/stack/btm/btm_iso_impl.h b/system/stack/btm/btm_iso_impl.h index e4f43ad384..54448ead52 100644 --- a/system/stack/btm/btm_iso_impl.h +++ b/system/stack/btm/btm_iso_impl.h @@ -473,7 +473,7 @@ struct iso_impl { STREAM_TO_UINT8(status, stream); if (status != HCI_SUCCESS) { - log::error("Failed to Read ISO Link Quality, status: {}", loghex(status)); + log::error("Failed to Read ISO Link Quality, status: 0x{:x}", status); return; } @@ -505,7 +505,7 @@ struct iso_impl { void read_iso_link_quality(uint16_t iso_handle) { iso_base* iso = GetIsoIfKnown(iso_handle); if (iso == nullptr) { - log::error("No such iso connection: {}", loghex(iso_handle)); + log::error("No such iso connection: 0x{:x}", iso_handle); return; } @@ -545,7 +545,7 @@ struct iso_impl { if (!(iso->state_flags & kStateFlagIsBroadcast)) { if (!(iso->state_flags & kStateFlagIsConnected)) { - log::warn("Cis handle: {} not established", loghex(iso_handle)); + log::warn("Cis handle: 0x{:x} not established", iso_handle); return; } } @@ -568,9 +568,9 @@ struct iso_impl { bluetooth::common::time_get_os_boottime_us(); log::warn( - ", dropping ISO packet, len: {}, iso credits: {}, iso handle: {}", + ", dropping ISO packet, len: {}, iso credits: {}, iso handle: 0x{:x}", static_cast<int>(data_len), static_cast<int>(iso_credits_), - loghex(iso_handle)); + iso_handle); return; } diff --git a/system/stack/btm/btm_sec.cc b/system/stack/btm/btm_sec.cc index 95e65c6eaf..96f2d443e3 100644 --- a/system/stack/btm/btm_sec.cc +++ b/system/stack/btm/btm_sec.cc @@ -1586,8 +1586,8 @@ tBTM_STATUS btm_sec_l2cap_access_req_by_requirement( log::verbose( "(SM4 to SM4) btm_sec_l2cap_access_req rspd. authenticated: x{:x}, " "enc: x{:x}", - (p_dev_rec->sec_rec.sec_flags & BTM_SEC_AUTHENTICATED), - (p_dev_rec->sec_rec.sec_flags & BTM_SEC_ENCRYPTED)); + p_dev_rec->sec_rec.sec_flags & BTM_SEC_AUTHENTICATED, + p_dev_rec->sec_rec.sec_flags & BTM_SEC_ENCRYPTED); /* SM4, but we do not know for sure which level of security we need. * as long as we have a link key, it's OK */ if ((0 == (p_dev_rec->sec_rec.sec_flags & BTM_SEC_AUTHENTICATED)) || diff --git a/system/stack/btu/btu_hcif.cc b/system/stack/btu/btu_hcif.cc index 15d033e7dc..9e82a1ce81 100644 --- a/system/stack/btu/btu_hcif.cc +++ b/system/stack/btu/btu_hcif.cc @@ -856,13 +856,12 @@ static void btu_hcif_esco_connection_comp_evt(const uint8_t* p) { STREAM_SKIP_UINT8(p); // air_mode handle = HCID_GET_HANDLE(handle); - log::assert_that(handle <= HCI_HANDLE_MAX, - "Received eSCO connection complete event with invalid " - "handle: 0x{:X} that should be <= 0x{:X}", - handle, HCI_HANDLE_MAX); - data.bd_addr = bda; if (status == HCI_SUCCESS) { + log::assert_that(handle <= HCI_HANDLE_MAX, + "Received eSCO connection complete event with invalid " + "handle: 0x{:X} that should be <= 0x{:X}", + handle, HCI_HANDLE_MAX); btm_sco_connected(bda, handle, &data); } else { btm_sco_connection_failed(static_cast<tHCI_STATUS>(status), bda, handle, diff --git a/system/stack/eatt/eatt_impl.h b/system/stack/eatt/eatt_impl.h index 2dcf242b22..13ce3c4366 100644 --- a/system/stack/eatt/eatt_impl.h +++ b/system/stack/eatt/eatt_impl.h @@ -180,7 +180,7 @@ struct eatt_impl { chan->EattChannelSetState(EattChannelState::EATT_CHANNEL_OPENED); eatt_dev->eatt_tcb_->eatt++; - log::info("Channel connected CID {}", loghex(cid)); + log::info("Channel connected CID 0x{:x}", cid); } return true; @@ -387,12 +387,12 @@ struct eatt_impl { EattChannel* channel = this->find_channel_by_cid(bda, lcid); if (!channel) { - log::error("unknown cid: {}", loghex(lcid)); + log::error("unknown cid: 0x{:x}", lcid); return; } if (result != L2CAP_CONN_OK) { - log::error("Could not connect CoC result: {}", loghex(result)); + log::error("Could not connect CoC result: 0x{:x}", result); remove_channel_by_cid(eatt_dev, lcid); /* If there is no channels connected, check if there was collision */ @@ -421,7 +421,7 @@ struct eatt_impl { void eatt_l2cap_reconfig_completed(const RawAddress& bda, uint16_t lcid, bool is_local_cfg, tL2CAP_LE_CFG_INFO* p_cfg) { - log::info("lcid: {} local cfg?: {}", loghex(lcid), is_local_cfg); + log::info("lcid: 0x{:x} local cfg?: {}", lcid, is_local_cfg); EattChannel* channel = find_channel_by_cid(bda, lcid); if (!channel) return; @@ -430,8 +430,8 @@ struct eatt_impl { channel->EattChannelSetState(EattChannelState::EATT_CHANNEL_OPENED); if (p_cfg->result != L2CAP_CFG_OK) { - log::info("reconfig failed lcid: {} result: {}", loghex(lcid), - loghex(p_cfg->result)); + log::info("reconfig failed lcid: 0x{:x} result: 0x{:x}", lcid, + p_cfg->result); return; } @@ -466,26 +466,26 @@ struct eatt_impl { void eatt_l2cap_error_cb(uint16_t lcid, uint16_t reason) { EattChannel* channel = find_channel_by_cid(lcid); if (!channel) { - log::error("Unknown cid: {}, reason: {}", loghex(lcid), loghex(reason)); + log::error("Unknown cid: 0x{:x}, reason: 0x{:x}", lcid, reason); return; } eatt_device* eatt_dev = find_device_by_address(channel->bda_); switch (channel->state_) { case EattChannelState::EATT_CHANNEL_PENDING: - log::warn("Channel for cid: {} is not extablished, reason: {}", - loghex(lcid), loghex(reason)); + log::warn("Channel for cid: 0x{:x} is not extablished, reason: 0x{:x}", + lcid, reason); remove_channel_by_cid(eatt_dev, lcid); break; case EattChannelState::EATT_CHANNEL_RECONFIGURING: /* Just go back to open state */ - log::error("Reconfig failed fo cid: {}, reason: {}", loghex(lcid), - loghex(reason)); + log::error("Reconfig failed fo cid: 0x{:x}, reason: 0x{:x}", lcid, + reason); channel->EattChannelSetState(EattChannelState::EATT_CHANNEL_OPENED); break; default: - log::error("cid: {}, reason: {}, invalid state: {}", loghex(lcid), - loghex(reason), static_cast<uint8_t>(channel->state_)); + log::error("cid: 0x{:x}, reason: 0x{:x}, invalid state: {}", lcid, + reason, static_cast<uint8_t>(channel->state_)); break; } @@ -495,10 +495,10 @@ struct eatt_impl { } void eatt_l2cap_disconnect_ind(uint16_t lcid, bool please_confirm) { - log::info("cid: {}", loghex(lcid)); + log::info("cid: 0x{:x}", lcid); eatt_device* eatt_dev = find_device_by_cid(lcid); if (!eatt_dev) { - log::error("unknown cid: {}", loghex(lcid)); + log::error("unknown cid: 0x{:x}", lcid); return; } @@ -507,16 +507,16 @@ struct eatt_impl { } void eatt_l2cap_data_ind(uint16_t lcid, BT_HDR* data_p) { - log::info("cid: {}", loghex(lcid)); + log::info("cid: 0x{:x}", lcid); eatt_device* eatt_dev = find_device_by_cid(lcid); if (!eatt_dev) { - log::error("unknown cid: {}", loghex(lcid)); + log::error("unknown cid: 0x{:x}", lcid); return; } EattChannel* channel = find_channel_by_cid(eatt_dev->bda_, lcid); if (!channel) { - log::error("Received data on closed channel {}", loghex(lcid)); + log::error("Received data on closed channel 0x{:x}", lcid); return; } @@ -586,7 +586,7 @@ struct eatt_impl { connecting_cids.size()); for (uint16_t cid : connecting_cids) { - log::info("\t cid: {}", loghex(cid)); + log::info("\t cid: 0x{:x}", cid); auto chan = std::make_shared<EattChannel>(eatt_dev->bda_, cid, 0, eatt_dev->rx_mtu_); @@ -741,7 +741,7 @@ struct eatt_impl { void start_indication_confirm_timer(const RawAddress& bd_addr, uint16_t cid) { EattChannel* channel = find_eatt_channel_by_cid(bd_addr, cid); if (!channel) { - log::error("Unknown cid: {} or device {}", loghex(cid), bd_addr); + log::error("Unknown cid: 0x{:x} or device {}", cid, bd_addr); return; } @@ -753,7 +753,7 @@ struct eatt_impl { void stop_indication_confirm_timer(const RawAddress& bd_addr, uint16_t cid) { EattChannel* channel = find_eatt_channel_by_cid(bd_addr, cid); if (!channel) { - log::error("Unknown cid: {} or device {}", loghex(cid), bd_addr); + log::error("Unknown cid: 0x{:x} or device {}", cid, bd_addr); return; } @@ -763,7 +763,7 @@ struct eatt_impl { void start_app_indication_timer(const RawAddress& bd_addr, uint16_t cid) { EattChannel* channel = find_eatt_channel_by_cid(bd_addr, cid); if (!channel) { - log::error("Unknown cid: {} or device {}", loghex(cid), bd_addr); + log::error("Unknown cid: 0x{:x} or device {}", cid, bd_addr); return; } @@ -774,7 +774,7 @@ struct eatt_impl { void stop_app_indication_timer(const RawAddress& bd_addr, uint16_t cid) { EattChannel* channel = find_eatt_channel_by_cid(bd_addr, cid); if (!channel) { - log::error("Unknown cid: {} or device {}", loghex(cid), bd_addr); + log::error("Unknown cid: 0x{:x} or device {}", cid, bd_addr); return; } @@ -790,12 +790,12 @@ struct eatt_impl { EattChannel* channel = find_eatt_channel_by_cid(bd_addr, cid); if (!channel) { - log::error("Unknown cid: {} or device {}", loghex(cid), bd_addr); + log::error("Unknown cid: 0x{:x} or device {}", cid, bd_addr); return; } if (new_mtu <= channel->rx_mtu_) { - log::error("Invalid mtu: {}", loghex(new_mtu)); + log::error("Invalid mtu: 0x{:x}", new_mtu); return; } @@ -804,7 +804,7 @@ struct eatt_impl { tL2CAP_LE_CFG_INFO cfg = {.mtu = new_mtu, .mps = eatt_dev->rx_mps_}; if (!L2CA_ReconfigCreditBasedConnsReq(eatt_dev->bda_, cids, &cfg)) { - log::error("Could not start reconfig cid: {} or device {}", loghex(cid), + log::error("Could not start reconfig cid: 0x{:x} or device {}", cid, bd_addr); return; } @@ -836,7 +836,7 @@ struct eatt_impl { } if (new_mtu <= EATT_MIN_MTU_MPS) { - log::error("Invalid mtu: {}", loghex(new_mtu)); + log::error("Invalid mtu: 0x{:x}", new_mtu); return; } @@ -973,7 +973,7 @@ struct eatt_impl { } log::info("Device {}, role {}", bd_addr, - (role == HCI_ROLE_CENTRAL ? "central" : "peripheral")); + role == HCI_ROLE_CENTRAL ? "central" : "peripheral"); if (eatt_dev) { /* We are reconnecting device we know that support EATT. diff --git a/system/stack/gatt/connection_manager.cc b/system/stack/gatt/connection_manager.cc index 31c726fa8c..0d99ede488 100644 --- a/system/stack/gatt/connection_manager.cc +++ b/system/stack/gatt/connection_manager.cc @@ -463,8 +463,8 @@ bool direct_connect_add(uint8_t app_id, const RawAddress& address) { if (it != bgconn_dev.end()) { // app already trying to connect to this particular device if (it->second.doing_direct_conn.count(app_id)) { - log::info("direct connect attempt from app_id={} already in progress", - loghex(app_id)); + log::info("direct connect attempt from app_id=0x{:x} already in progress", + app_id); return false; } diff --git a/system/stack/gatt/gatt_api.cc b/system/stack/gatt/gatt_api.cc index 12f6cdd34e..d25e19e388 100644 --- a/system/stack/gatt/gatt_api.cc +++ b/system/stack/gatt/gatt_api.cc @@ -226,10 +226,10 @@ tGATT_STATUS GATTS_AddService(tGATT_IF gatt_if, btgatt_db_element_t* service, gatts_init_service_db(list.svc_db, svc_uuid, is_pri, s_hdl, num_handles); - log::verbose("handles needed={}, s_hdl={}, e_hdl={}, uuid={}, is_primary={}", - num_handles, loghex(list.asgn_range.s_handle), - loghex(list.asgn_range.e_handle), list.asgn_range.svc_uuid, - list.asgn_range.is_primary); + log::verbose( + "handles needed={}, s_hdl=0x{:x}, e_hdl=0x{:x}, uuid={}, is_primary={}", + num_handles, list.asgn_range.s_handle, list.asgn_range.e_handle, + list.asgn_range.svc_uuid, list.asgn_range.is_primary); service->attribute_handle = s_hdl; @@ -243,8 +243,8 @@ tGATT_STATUS GATTS_AddService(tGATT_IF gatt_if, btgatt_db_element_t* service, !(el->permissions & GATT_WRITE_SIGNED_PERM)) || ((el->permissions & GATT_WRITE_SIGNED_PERM) && !(el->properties & GATT_CHAR_PROP_BIT_AUTH))) { - log::verbose("Invalid configuration property={}, perm={}", - loghex(el->properties), loghex(el->permissions)); + log::verbose("Invalid configuration property=0x{:x}, perm=0x{:x}", + el->properties, el->permissions); return GATT_INTERNAL_ERROR; } @@ -326,9 +326,9 @@ tGATT_STATUS GATTS_AddService(tGATT_IF gatt_if, btgatt_db_element_t* service, gatt_update_last_srv_info(); - log::verbose("allocated el s_hdl={}, e_hdl={}, type={}, sdp_hdl={}", - loghex(elem.s_hdl), loghex(elem.e_hdl), loghex(elem.type), - loghex(elem.sdp_handle)); + log::verbose( + "allocated el s_hdl=0x{:x}, e_hdl=0x{:x}, type=0x{:x}, sdp_hdl=0x{:x}", + elem.s_hdl, elem.e_hdl, elem.type, elem.sdp_handle); gatt_update_for_database_change(); gatt_proc_srv_chg(); @@ -388,9 +388,8 @@ bool GATTS_DeleteService(tGATT_IF gatt_if, Uuid* p_svc_uuid, gatt_update_for_database_change(); gatt_proc_srv_chg(); - log::verbose("released handles s_hdl={}, e_hdl={}", - loghex(it->asgn_range.s_handle), - loghex(it->asgn_range.e_handle)); + log::verbose("released handles s_hdl=0x{:x}, e_hdl=0x{:x}", + it->asgn_range.s_handle, it->asgn_range.e_handle); if ((it->asgn_range.s_handle >= gatt_cb.hdl_cfg.app_start_hdl) && gatt_cb.cb_info.p_nv_save_callback) @@ -412,11 +411,11 @@ bool GATTS_DeleteService(tGATT_IF gatt_if, Uuid* p_svc_uuid, * ******************************************************************************/ void GATTS_StopService(uint16_t service_handle) { - log::info("service = {}", loghex(service_handle)); + log::info("service = 0x{:x}", service_handle); auto it = gatt_sr_find_i_rcb_by_handle(service_handle); if (it == gatt_cb.srv_list_info->end()) { - log::error("service_handle={} is not in use", loghex(service_handle)); + log::error("service_handle=0x{:x} is not in use", service_handle); return; } @@ -452,7 +451,7 @@ tGATT_STATUS GATTS_HandleValueIndication(uint16_t conn_id, uint16_t attr_handle, log::verbose(""); if ((p_reg == NULL) || (p_tcb == NULL)) { - log::error("Unknown conn_id={}", loghex(conn_id)); + log::error("Unknown conn_id=0x{:x}", conn_id); return (tGATT_STATUS)GATT_INVALID_CONN_ID; } @@ -644,18 +643,18 @@ tGATT_STATUS GATTS_SendRsp(uint16_t conn_id, uint32_t trans_id, tGATT_REG* p_reg = gatt_get_regcb(gatt_if); tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx); - log::verbose("conn_id={}, trans_id={}, status={}", loghex(conn_id), - loghex(trans_id), loghex(static_cast<uint8_t>(status))); + log::verbose("conn_id=0x{:x}, trans_id=0x{:x}, status=0x{:x}", conn_id, + trans_id, static_cast<uint8_t>(status)); if ((p_reg == NULL) || (p_tcb == NULL)) { - log::error("Unknown conn_id={}", loghex(conn_id)); + log::error("Unknown conn_id=0x{:x}", conn_id); return (tGATT_STATUS)GATT_INVALID_CONN_ID; } tGATT_SR_CMD* sr_res_p = gatt_sr_get_cmd_by_trans_id(p_tcb, trans_id); if (!sr_res_p) { - log::error("conn_id={} waiting for other op_code", loghex(conn_id)); + log::error("conn_id=0x{:x} waiting for other op_code", conn_id); return (GATT_WRONG_STATE); } @@ -876,8 +875,8 @@ tGATT_STATUS GATTC_Discover(uint16_t conn_id, tGATT_DISC_TYPE disc_type, tGATT_REG* p_reg = gatt_get_regcb(gatt_if); if ((p_tcb == NULL) || (p_reg == NULL) || (disc_type >= GATT_DISC_MAX)) { - log::error("Illegal param: disc_type={} conn_id={}", disc_type, - loghex(conn_id)); + log::error("Illegal param: disc_type={} conn_id=0x{:x}", disc_type, + conn_id); return GATT_ILLEGAL_PARAMETER; } @@ -886,16 +885,18 @@ tGATT_STATUS GATTC_Discover(uint16_t conn_id, tGATT_DISC_TYPE disc_type, /* search by type does not have a valid UUID param */ (disc_type == GATT_DISC_SRVC_BY_UUID && uuid.IsEmpty())) { log::warn( - "Illegal parameter conn_id={}, disc_type={}, s_handle={}, e_handle={}", - loghex(conn_id), disc_type, loghex(start_handle), loghex(end_handle)); + "Illegal parameter conn_id=0x{:x}, disc_type={}, s_handle=0x{:x}, " + "e_handle=0x{:x}", + conn_id, disc_type, start_handle, end_handle); return GATT_ILLEGAL_PARAMETER; } tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id); if (!p_clcb) { - log::warn("No resources conn_id={}, disc_type={}, s_handle={}, e_handle={}", - loghex(conn_id), disc_type, loghex(start_handle), - loghex(end_handle)); + log::warn( + "No resources conn_id=0x{:x}, disc_type={}, s_handle=0x{:x}, " + "e_handle=0x{:x}", + conn_id, disc_type, start_handle, end_handle); return GATT_NO_RESOURCES; } @@ -905,9 +906,8 @@ tGATT_STATUS GATTC_Discover(uint16_t conn_id, tGATT_DISC_TYPE disc_type, p_clcb->e_handle = end_handle; p_clcb->uuid = uuid; - log::info("conn_id={}, disc_type={}, s_handle={}, e_handle={}", - loghex(conn_id), disc_type, loghex(start_handle), - loghex(end_handle)); + log::info("conn_id=0x{:x}, disc_type={}, s_handle=0x{:x}, e_handle=0x{:x}", + conn_id, disc_type, start_handle, end_handle); gatt_act_discovery(p_clcb); return GATT_SUCCESS; @@ -944,12 +944,11 @@ tGATT_STATUS GATTC_Read(uint16_t conn_id, tGATT_READ_TYPE type, static int cached_tcb_idx = -1; #endif - log::verbose("conn_id={}, type={}", loghex(conn_id), loghex(type)); + log::verbose("conn_id=0x{:x}, type=0x{:x}", conn_id, type); if ((p_tcb == NULL) || (p_reg == NULL) || (p_read == NULL) || ((type >= GATT_READ_MAX) || (type == 0))) { - log::error("illegal param: conn_id={}, type={}", loghex(conn_id), - loghex(type)); + log::error("illegal param: conn_id=0x{:x}, type=0x{:x}", conn_id, type); return GATT_ILLEGAL_PARAMETER; } @@ -1051,8 +1050,7 @@ tGATT_STATUS GATTC_Write(uint16_t conn_id, tGATT_WRITE_TYPE type, if ((p_tcb == NULL) || (p_reg == NULL) || (p_write == NULL) || ((type != GATT_WRITE) && (type != GATT_WRITE_PREPARE) && (type != GATT_WRITE_NO_RSP))) { - log::error("Illegal param: conn_id={}, type={}", loghex(conn_id), - loghex(type)); + log::error("Illegal param: conn_id=0x{:x}, type=0x{:x}", conn_id, type); return GATT_ILLEGAL_PARAMETER; } @@ -1097,10 +1095,10 @@ tGATT_STATUS GATTC_ExecuteWrite(uint16_t conn_id, bool is_execute) { tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx); tGATT_REG* p_reg = gatt_get_regcb(gatt_if); - log::verbose("conn_id={}, is_execute={}", loghex(conn_id), is_execute); + log::verbose("conn_id=0x{:x}, is_execute={}", conn_id, is_execute); if ((p_tcb == NULL) || (p_reg == NULL)) { - log::error("Illegal param: conn_id={}", loghex(conn_id)); + log::error("Illegal param: conn_id=0x{:x}", conn_id); return GATT_ILLEGAL_PARAMETER; } @@ -1132,7 +1130,7 @@ tGATT_STATUS GATTC_SendHandleValueConfirm(uint16_t conn_id, uint16_t cid) { tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(GATT_GET_TCB_IDX(conn_id)); if (!p_tcb) { - log::error("Unknown conn_id={}", loghex(conn_id)); + log::error("Unknown conn_id=0x{:x}", conn_id); return GATT_ILLEGAL_PARAMETER; } @@ -1623,7 +1621,7 @@ bool GATT_GetConnectionInfor(uint16_t conn_id, tGATT_IF* p_gatt_if, uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id); tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx); - log::verbose("conn_id={}", loghex(conn_id)); + log::verbose("conn_id=0x{:x}", conn_id); if (!p_tcb || !p_reg) return false; diff --git a/system/stack/gatt/gatt_attr.cc b/system/stack/gatt/gatt_attr.cc index 6ef95b9a01..74cfdf5a94 100644 --- a/system/stack/gatt/gatt_attr.cc +++ b/system/stack/gatt/gatt_attr.cc @@ -86,8 +86,6 @@ static void gatt_cl_op_cmpl_cback(uint16_t conn_id, tGATTC_OPTYPE op, static void gatt_cl_start_config_ccc(tGATT_PROFILE_CLCB* p_clcb); -static bool gatt_cl_is_robust_caching_enabled(); - static bool gatt_sr_is_robust_caching_enabled(); static bool read_sr_supported_feat_req( @@ -335,7 +333,7 @@ static void gatt_request_cback(uint16_t conn_id, uint32_t trans_id, break; default: - log::verbose("Unknown/unexpected LE GAP ATT request: {}", loghex(type)); + log::verbose("Unknown/unexpected LE GAP ATT request: 0x{:x}", type); break; } @@ -355,8 +353,8 @@ static void gatt_connect_cback(UNUSED_ATTR tGATT_IF gatt_if, const RawAddress& bda, uint16_t conn_id, bool connected, tGATT_DISCONN_REASON reason, tBT_TRANSPORT transport) { - log::verbose("from {} connected: {}, conn_id: {}", bda, connected, - loghex(conn_id)); + log::verbose("from {} connected: {}, conn_id: 0x{:x}", bda, connected, + conn_id); // if the device is not trusted, remove data when the link is disconnected if (!connected && !btm_sec_is_a_bonded_dev(bda)) { @@ -448,9 +446,7 @@ void gatt_profile_db_init(void) { gatt_cb.gatt_svr_supported_feat_mask |= BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK; gatt_cb.gatt_cl_supported_feat_mask |= BLE_GATT_CL_ANDROID_SUP_FEAT; - - if (gatt_cl_is_robust_caching_enabled()) - gatt_cb.gatt_cl_supported_feat_mask |= BLE_GATT_CL_SUP_FEAT_CACHING_BITMASK; + gatt_cb.gatt_cl_supported_feat_mask |= BLE_GATT_CL_SUP_FEAT_CACHING_BITMASK; log::verbose("gatt_if={} EATT supported", gatt_cb.gatt_if); } @@ -541,7 +537,7 @@ static bool gatt_svc_read_cl_supp_feat_req(uint16_t conn_id) { tGATT_STATUS status = GATTC_Read(conn_id, GATT_READ_BY_TYPE, ¶m); if (status != GATT_SUCCESS) { - log::error("Read failed. Status: {}", loghex(static_cast<uint8_t>(status))); + log::error("Read failed. Status: 0x{:x}", static_cast<uint8_t>(status)); return false; } @@ -567,8 +563,7 @@ static bool gatt_att_write_cl_supp_feat(uint16_t conn_id, uint16_t handle) { tGATT_STATUS status = GATTC_Write(conn_id, GATT_WRITE, &attr); if (status != GATT_SUCCESS) { - log::error("Write failed. Status: {}", - loghex(static_cast<uint8_t>(status))); + log::error("Write failed. Status: 0x{:x}", static_cast<uint8_t>(status)); return false; } @@ -589,12 +584,11 @@ static void gatt_cl_op_cmpl_cback(uint16_t conn_id, tGATTC_OPTYPE op, tGATT_CL_COMPLETE* p_data) { auto iter = OngoingOps.find(conn_id); - log::verbose("opcode: {} status: {} conn id: {}", - loghex(static_cast<uint8_t>(op)), status, - loghex(static_cast<uint8_t>(conn_id))); + log::verbose("opcode: 0x{:x} status: {} conn id: 0x{:x}", + static_cast<uint8_t>(op), status, static_cast<uint8_t>(conn_id)); if (op != GATTC_OPTYPE_READ && op != GATTC_OPTYPE_WRITE) { - log::debug("Not interested in opcode {}", op); + log::verbose("Not interested in opcode {}", op); return; } @@ -624,7 +618,7 @@ static void gatt_cl_op_cmpl_cback(uint16_t conn_id, tGATTC_OPTYPE op, /* Handle Read operations */ uint8_t* pp = p_data->att_value.value; - log::verbose("cl_op_uuid {}", loghex(cl_op_uuid)); + log::verbose("cl_op_uuid 0x{:x}", cl_op_uuid); switch (cl_op_uuid) { case GATT_UUID_SERVER_SUP_FEAT: { @@ -868,7 +862,7 @@ bool gatt_cl_read_sr_supp_feat_req( } if (!p_clcb) { - log::verbose("p_clcb is NULL {}", loghex(conn_id)); + log::verbose("p_clcb is NULL 0x{:x}", conn_id); return false; } @@ -952,19 +946,6 @@ bool gatt_profile_get_eatt_support(const RawAddress& remote_bda) { /******************************************************************************* * - * Function gatt_cl_is_robust_caching_enabled - * - * Description Check if Robust Caching is enabled on client side. - * - * Returns true if enabled in gd flag, otherwise false - * - ******************************************************************************/ -static bool gatt_cl_is_robust_caching_enabled() { - return bluetooth::common::init_flags::gatt_robust_caching_client_is_enabled(); -} - -/******************************************************************************* - * * Function gatt_sr_is_robust_caching_enabled * * Description Check if Robust Caching is enabled on server side. @@ -1044,8 +1025,8 @@ void gatt_sr_init_cl_status(tGATT_TCB& tcb) { tcb.is_robust_cache_change_aware = true; } - log::info("bda={}, cl_supp_feat={}, aware={}", tcb.peer_bda, - loghex(tcb.cl_supp_feat), tcb.is_robust_cache_change_aware); + log::info("bda={}, cl_supp_feat=0x{:x}, aware={}", tcb.peer_bda, + tcb.cl_supp_feat, tcb.is_robust_cache_change_aware); } /******************************************************************************* @@ -1078,7 +1059,7 @@ void gatt_sr_update_cl_status(tGATT_TCB& tcb, bool chg_aware) { /* handle request for reading database hash */ static tGATT_STATUS gatt_sr_read_db_hash(uint16_t conn_id, tGATT_VALUE* p_value) { - log::info("conn_id={}", loghex(conn_id)); + log::info("conn_id=0x{:x}", conn_id); uint8_t* p = p_value->value; Octet16& db_hash = gatt_cb.database_hash; @@ -1132,13 +1113,12 @@ static tGATT_STATUS gatt_sr_write_cl_supp_feat(uint16_t conn_id, // If input length is zero, return value_not_allowed if (tmp.empty()) { - log::info("zero length, conn_id={}, bda={}", loghex(conn_id), tcb.peer_bda); + log::info("zero length, conn_id=0x{:x}, bda={}", conn_id, tcb.peer_bda); return GATT_VALUE_NOT_ALLOWED; } // if original length is longer than new one, it must be the bit reset case. if (feature_list.size() > tmp.size()) { - log::info("shorter length, conn_id={}, bda={}", loghex(conn_id), - tcb.peer_bda); + log::info("shorter length, conn_id=0x{:x}, bda={}", conn_id, tcb.peer_bda); return GATT_VALUE_NOT_ALLOWED; } // new length is longer or equals to the original, need to check bits @@ -1152,7 +1132,7 @@ static tGATT_STATUS gatt_sr_write_cl_supp_feat(uint16_t conn_id, uint8_t val_xor = *it_old ^ *it_new; uint8_t val_and = val_xor & *it_new; if (val_and != val_xor) { - log::info("bit cannot be reset, conn_id={}, bda={}", loghex(conn_id), + log::info("bit cannot be reset, conn_id=0x{:x}, bda={}", conn_id, tcb.peer_bda); return GATT_VALUE_NOT_ALLOWED; } @@ -1165,7 +1145,7 @@ static tGATT_STATUS gatt_sr_write_cl_supp_feat(uint16_t conn_id, if (!gatt_sr_is_robust_caching_enabled()) { // remove robust caching bit tcb.cl_supp_feat &= ~BLE_GATT_CL_SUP_FEAT_CACHING_BITMASK; - log::info("reset robust caching bit, conn_id={}, bda={}", loghex(conn_id), + log::info("reset robust caching bit, conn_id=0x{:x}, bda={}", conn_id, tcb.peer_bda); } // TODO(hylo): save data as byte array @@ -1175,7 +1155,7 @@ static tGATT_STATUS gatt_sr_write_cl_supp_feat(uint16_t conn_id, bool new_caching_state = gatt_sr_is_cl_robust_caching_supported(tcb); // only when the first time robust caching request, print the log if (!curr_caching_state && new_caching_state) { - log::info("robust caching enabled by client, conn_id={}", loghex(conn_id)); + log::info("robust caching enabled by client, conn_id=0x{:x}", conn_id); } return GATT_SUCCESS; diff --git a/system/stack/gatt/gatt_cl.cc b/system/stack/gatt/gatt_cl.cc index 635e1e65d6..d4d15f5665 100644 --- a/system/stack/gatt/gatt_cl.cc +++ b/system/stack/gatt/gatt_cl.cc @@ -677,8 +677,7 @@ void gatt_process_notification(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, STREAM_TO_UINT16(value.len, p); if (value.len > len - 4) { - log::error("value.len ({}) greater than length ({})", value.len, - (len - 4)); + log::error("value.len ({}) greater than length ({})", value.len, len - 4); return; } @@ -820,7 +819,7 @@ void gatt_process_read_by_type_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, or value_len > message total length -1 */ log::error( "Discard response op_code={} vale_len={} > (MTU-2={} or msg_len-1={})", - op_code, value_len, (payload_size - 2), (len - 1)); + op_code, value_len, payload_size - 2, len - 1); gatt_end_operation(p_clcb, GATT_ERROR, NULL); return; } @@ -1211,7 +1210,7 @@ bool gatt_cl_send_next_cmd_inq(tGATT_TCB& tcb) { void gatt_client_handle_server_rsp(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, uint16_t len, uint8_t* p_data) { - log::verbose("opcode: {} cid{}", loghex(op_code), cid); + log::verbose("opcode: 0x{:x} cid{}", op_code, cid); uint16_t payload_size = gatt_tcb_get_payload_size(tcb, cid); diff --git a/system/stack/gatt/gatt_db.cc b/system/stack/gatt/gatt_db.cc index df68362e11..19daa95848 100644 --- a/system/stack/gatt/gatt_db.cc +++ b/system/stack/gatt/gatt_db.cc @@ -23,7 +23,6 @@ ******************************************************************************/ #include <bluetooth/log.h> -#include <stdio.h> #include <string.h> #include "gatt_int.h" diff --git a/system/stack/gatt/gatt_main.cc b/system/stack/gatt/gatt_main.cc index 03709a4ba2..49ee160469 100644 --- a/system/stack/gatt/gatt_main.cc +++ b/system/stack/gatt/gatt_main.cc @@ -487,7 +487,7 @@ static void gatt_le_connect_cback(uint16_t chan, const RawAddress& bd_addr, } log::verbose("GATT ATT protocol channel with BDA: {} is {}", bd_addr, - ((connected) ? "connected" : "disconnected")); + (connected) ? "connected" : "disconnected"); p_srv_chg_clt = gatt_is_bda_in_the_srv_chg_clt_list(bd_addr); if (p_srv_chg_clt != NULL) { @@ -603,7 +603,7 @@ static void read_dis_cback(const RawAddress& bd_addr, tDIS_VALUE* p_dis_value) { prop.val = p_dis_value->data_string[i]; prop.len = strlen((char*)prop.val); - log::info("Device {}, model name: {}", bd_addr, ((char*)prop.val)); + log::info("Device {}, model name: {}", bd_addr, (char*)prop.val); btif_storage_set_remote_device_property(&bd_addr, &prop); GetInterfaceToProfiles()->events->invoke_remote_device_properties_cb( @@ -1021,7 +1021,7 @@ void gatt_data_process(tGATT_TCB& tcb, uint16_t cid, BT_HDR* p_buf) { if (pseudo_op_code >= GATT_OP_CODE_MAX) { /* Note: PTS: GATT/SR/UNS/BI-01-C mandates error on unsupported ATT request. */ - log::error("ATT - Rcvd L2CAP data, unknown cmd: {}", loghex(op_code)); + log::error("ATT - Rcvd L2CAP data, unknown cmd: 0x{:x}", op_code); gatt_send_error_rsp(tcb, cid, GATT_REQ_NOT_SUPPORTED, op_code, 0, false); return; } @@ -1169,8 +1169,8 @@ void gatt_proc_srv_chg(void) { void gatt_set_ch_state(tGATT_TCB* p_tcb, tGATT_CH_STATE ch_state) { if (!p_tcb) return; - log::verbose("old={} new={}", p_tcb->ch_state, - loghex(static_cast<uint8_t>(ch_state))); + log::verbose("old={} new=0x{:x}", p_tcb->ch_state, + static_cast<uint8_t>(ch_state)); p_tcb->ch_state = ch_state; } diff --git a/system/stack/gatt/gatt_sr.cc b/system/stack/gatt/gatt_sr.cc index 94b7efc405..0e18e82380 100644 --- a/system/stack/gatt/gatt_sr.cc +++ b/system/stack/gatt/gatt_sr.cc @@ -147,7 +147,7 @@ void gatt_dequeue_sr_cmd(tGATT_TCB& tcb, uint16_t cid) { } /* Double check in case any buffers are queued */ - log::verbose("gatt_dequeue_sr_cmd cid: {}", loghex(cid)); + log::verbose("gatt_dequeue_sr_cmd cid: 0x{:x}", cid); if (p_cmd->p_rsp_msg) log::error("free tcb.sr_cmd.p_rsp_msg = {}", fmt::ptr(p_cmd->p_rsp_msg)); osi_free_and_reset((void**)&p_cmd->p_rsp_msg); @@ -1365,8 +1365,8 @@ static bool gatts_process_db_out_of_sync(tGATT_TCB& tcb, uint16_t cid, gatt_send_error_rsp(tcb, cid, GATT_DATABASE_OUT_OF_SYNC, op_code, 0x0000, false); } - log::info("database out of sync, device={}, op_code={}, should_rsp={}", - tcb.peer_bda, loghex((uint16_t)op_code), should_rsp); + log::info("database out of sync, device={}, op_code=0x{:x}, should_rsp={}", + tcb.peer_bda, (uint16_t)op_code, should_rsp); gatt_sr_update_cl_status(tcb, /* chg_aware= */ should_rsp); } diff --git a/system/stack/hid/hidd_api.cc b/system/stack/hid/hidd_api.cc index 602f9a7153..3669a80466 100644 --- a/system/stack/hid/hidd_api.cc +++ b/system/stack/hid/hidd_api.cc @@ -29,7 +29,6 @@ #include <bluetooth/log.h> #include <frameworks/proto_logging/stats/enums/bluetooth/enums.pb.h> -#include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/system/stack/hid/hidd_conn.cc b/system/stack/hid/hidd_conn.cc index ba2822982a..8cf976626b 100644 --- a/system/stack/hid/hidd_conn.cc +++ b/system/stack/hid/hidd_conn.cc @@ -486,7 +486,7 @@ static void hidd_l2cif_data_ind(uint16_t cid, BT_HDR* p_msg) { log::verbose("idle_time = {}", hd_cb.device.idle_time); if (hd_cb.device.idle_time) { log::warn("idle_time of {} ms not supported by HID Device", - (hd_cb.device.idle_time * 4)); + hd_cb.device.idle_time * 4); err = TRUE; } } diff --git a/system/stack/hid/hidh_api.cc b/system/stack/hid/hidh_api.cc index 24f0f18078..b78dcc0a28 100644 --- a/system/stack/hid/hidh_api.cc +++ b/system/stack/hid/hidh_api.cc @@ -28,7 +28,6 @@ #include <bluetooth/log.h> #include <frameworks/proto_logging/stats/enums/bluetooth/enums.pb.h> -#include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/system/stack/l2cap/l2c_api.cc b/system/stack/l2cap/l2c_api.cc index c77d4da59c..fed26ece5b 100644 --- a/system/stack/l2cap/l2c_api.cc +++ b/system/stack/l2cap/l2c_api.cc @@ -324,7 +324,7 @@ uint16_t L2CA_ConnectReq(uint16_t psm, const RawAddress& p_bd_addr) { /* Fail if the PSM is not registered */ tL2C_RCB* p_rcb = l2cu_find_rcb_by_psm(psm); if (p_rcb == nullptr) { - log::warn("no RCB, PSM={}", loghex(psm)); + log::warn("no RCB, PSM=0x{:x}", psm); return 0; } @@ -336,7 +336,7 @@ uint16_t L2CA_ConnectReq(uint16_t psm, const RawAddress& p_bd_addr) { p_lcb = l2cu_allocate_lcb(p_bd_addr, false, BT_TRANSPORT_BR_EDR); /* currently use BR/EDR for ERTM mode l2cap connection */ if (p_lcb == nullptr) { - log::warn("connection not started for PSM={}, p_lcb={}", loghex(psm), + log::warn("connection not started for PSM=0x{:x}, p_lcb={}", psm, fmt::ptr(p_lcb)); return 0; } @@ -346,7 +346,7 @@ uint16_t L2CA_ConnectReq(uint16_t psm, const RawAddress& p_bd_addr) { /* Allocate a channel control block */ tL2C_CCB* p_ccb = l2cu_allocate_ccb(p_lcb, 0); if (p_ccb == nullptr) { - log::warn("no CCB, PSM={}", loghex(psm)); + log::warn("no CCB, PSM=0x{:x}", psm); return 0; } @@ -1003,8 +1003,7 @@ bool L2CA_UseLatencyMode(const RawAddress& bd_addr, bool use_latency_mode) { log::warn("L2CAP - no LCB for L2CA_SetUseLatencyMode, BDA: {}", bd_addr); return false; } - log::info("BDA: {}, use_latency_mode: {}", bd_addr, - use_latency_mode ? "true" : "false"); + log::info("BDA: {}, use_latency_mode: {}", bd_addr, use_latency_mode); p_lcb->use_latency_mode = use_latency_mode; return true; } @@ -1035,7 +1034,7 @@ bool L2CA_SetAclPriority(const RawAddress& bd_addr, tL2CAP_PRIORITY priority) { * ******************************************************************************/ bool L2CA_SetAclLatency(const RawAddress& bd_addr, tL2CAP_LATENCY latency) { - log::info("BDA: {}, latency: {}", bd_addr, std::to_string(latency)); + log::info("BDA: {}, latency: {}", bd_addr, latency); return l2cu_set_acl_latency(bd_addr, latency); } @@ -1657,7 +1656,7 @@ void L2CA_SetMediaStreamChannel(uint16_t local_media_cid, bool status) { } log::debug("local_media_cid={}, status={}", local_media_cid, - (status ? "add" : "remove")); + status ? "add" : "remove"); if (status) { for (i = 0; i < MAX_ACTIVE_AVDT_CONN; i++) { diff --git a/system/stack/l2cap/l2c_csm.cc b/system/stack/l2cap/l2c_csm.cc index c21b69924c..b54208dad4 100644 --- a/system/stack/l2cap/l2c_csm.cc +++ b/system/stack/l2cap/l2c_csm.cc @@ -715,8 +715,8 @@ static void l2c_csm_w4_l2cap_connect_rsp(tL2C_CCB* p_ccb, tL2CEVT event, break; case L2CEVT_L2CAP_CONNECT_RSP_NEG: /* Peer rejected connection */ - log::warn("L2CAP connection rejected, lcid={}, reason={}", - loghex(p_ccb->local_cid), loghex(p_ci->l2cap_result)); + log::warn("L2CAP connection rejected, lcid=0x{:x}, reason=0x{:x}", + p_ccb->local_cid, p_ci->l2cap_result); l2cu_release_ccb(p_ccb); if (p_lcb->transport == BT_TRANSPORT_LE) { (*p_ccb->p_rcb->api.pL2CA_Error_Cb)( @@ -735,7 +735,7 @@ static void l2c_csm_w4_l2cap_connect_rsp(tL2C_CCB* p_ccb, tL2CEVT event, for (int i = 0; i < p_lcb->pending_ecoc_conn_cnt; i++) { uint16_t cid = p_lcb->pending_ecoc_connection_cids[i]; tL2C_CCB* temp_p_ccb = l2cu_find_ccb_by_cid(p_lcb, cid); - log::warn("lcid= {}", loghex(cid)); + log::warn("lcid= 0x{:x}", cid); (*p_ccb->p_rcb->api.pL2CA_Error_Cb)(p_ccb->local_cid, L2CAP_CONN_TIMEOUT); bluetooth::shim::CountCounterMetrics( @@ -749,7 +749,7 @@ static void l2c_csm_w4_l2cap_connect_rsp(tL2C_CCB* p_ccb, tL2CEVT event, L2CAP_CREDIT_BASED_MAX_CIDS); } else { - log::warn("lcid= {}", loghex(p_ccb->local_cid)); + log::warn("lcid= 0x{:x}", p_ccb->local_cid); l2cu_release_ccb(p_ccb); (*p_ccb->p_rcb->api.pL2CA_Error_Cb)(local_cid, L2CAP_CONN_OTHER_ERROR); bluetooth::shim::CountCounterMetrics( @@ -1017,8 +1017,7 @@ static void l2c_csm_config(tL2C_CCB* p_ccb, tL2CEVT event, void* p_data) { cfg_result = l2cu_process_peer_cfg_req(p_ccb, p_cfg); if (cfg_result == L2CAP_PEER_CFG_OK) { log::debug("Calling Config_Req_Cb(), CID: 0x{:04x}, C-bit {}", - p_ccb->local_cid, - (p_cfg->flags & L2CAP_CFG_FLAGS_MASK_CONT)); + p_ccb->local_cid, p_cfg->flags & L2CAP_CFG_FLAGS_MASK_CONT); l2c_csm_send_config_rsp_ok(p_ccb, p_cfg->flags & L2CAP_CFG_FLAGS_MASK_CONT); if (p_ccb->config_done & OB_CFG_DONE) { diff --git a/system/stack/l2cap/l2c_fcr.cc b/system/stack/l2cap/l2c_fcr.cc index 00684daa6c..ea9829c933 100644 --- a/system/stack/l2cap/l2c_fcr.cc +++ b/system/stack/l2cap/l2c_fcr.cc @@ -24,7 +24,6 @@ ******************************************************************************/ #include <bluetooth/log.h> -#include <stdio.h> #include <stdlib.h> #include <string.h> @@ -741,7 +740,7 @@ void l2c_lcc_proc_pdu(tL2C_CCB* p_ccb, BT_HDR* p_buf) { } if (p_buf->len > (p_ccb->ble_sdu_length - p_data->len)) { log::error("buffer length={} too big. max={}. Dropped", p_data->len, - (p_ccb->ble_sdu_length - p_data->len)); + p_ccb->ble_sdu_length - p_data->len); osi_free(p_buf); /* Throw away all pending fragments and disconnects */ diff --git a/system/stack/l2cap/l2c_utils.cc b/system/stack/l2cap/l2c_utils.cc index 68ffd7a985..910e27ff80 100644 --- a/system/stack/l2cap/l2c_utils.cc +++ b/system/stack/l2cap/l2c_utils.cc @@ -24,7 +24,6 @@ #define LOG_TAG "l2c_utils" #include <bluetooth/log.h> -#include <stdio.h> #include <string.h> #include "hal/snoop_logger.h" @@ -851,7 +850,7 @@ void l2cu_send_peer_config_rej(tL2C_CCB* p_ccb, uint8_t* p_data, p_buf->len = len + 4; log::verbose("L2CAP - cfg_rej pkt hci_len={}, l2cap_len={}", len, - (L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN + rej_len)); + L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN + rej_len); l2c_link_check_send_pkts(p_ccb->p_lcb, 0, p_buf); } @@ -3599,4 +3598,4 @@ uint16_t le_result_to_l2c_conn(uint16_t result) { * Description API functions call this function to flush data. * ******************************************************************************/ -void l2c_acl_flush(uint16_t handle) { btm_acl_flush(handle); }
\ No newline at end of file +void l2c_acl_flush(uint16_t handle) { btm_acl_flush(handle); } diff --git a/system/stack/rfcomm/port_api.cc b/system/stack/rfcomm/port_api.cc index 7075a45ffe..c09921d974 100644 --- a/system/stack/rfcomm/port_api.cc +++ b/system/stack/rfcomm/port_api.cc @@ -118,9 +118,9 @@ int RFCOMM_CreateConnectionWithSecurity(uint16_t uuid, uint8_t scn, if ((scn == 0) || (scn > RFCOMM_MAX_SCN)) { // Server Channel Number (SCN) should be in range [1, 30] - log::error("Invalid SCN, bd_addr={}, scn={}, is_server={}, mtu={}, uuid={}", - bd_addr, static_cast<int>(scn), is_server, static_cast<int>(mtu), - loghex(uuid)); + log::error( + "Invalid SCN, bd_addr={}, scn={}, is_server={}, mtu={}, uuid=0x{:x}", + bd_addr, static_cast<int>(scn), is_server, static_cast<int>(mtu), uuid); return (PORT_INVALID_SCN); } @@ -144,13 +144,12 @@ int RFCOMM_CreateConnectionWithSecurity(uint16_t uuid, uint8_t scn, if (!p_port->is_server) { log::error( "already at opened state {}, RFC_state={}, MCB_state={}, " - "bd_addr={}, scn={}, is_server={}, mtu={}, uuid={}, dlci={}, " + "bd_addr={}, scn={}, is_server={}, mtu={}, uuid=0x{:x}, dlci={}, " "p_mcb={}, port={}", static_cast<int>(p_port->state), static_cast<int>(p_port->rfc.state), - (p_port->rfc.p_mcb ? p_port->rfc.p_mcb->state : 0), bd_addr, scn, - is_server, mtu, loghex(uuid), dlci, fmt::ptr(p_mcb), - p_port->handle); + p_port->rfc.p_mcb ? p_port->rfc.p_mcb->state : 0, bd_addr, scn, + is_server, mtu, uuid, dlci, fmt::ptr(p_mcb), p_port->handle); *p_handle = p_port->handle; return (PORT_ALREADY_OPENED); } @@ -161,9 +160,9 @@ int RFCOMM_CreateConnectionWithSecurity(uint16_t uuid, uint8_t scn, p_port = port_allocate_port(dlci, bd_addr); if (p_port == nullptr) { log::error( - "no resources, bd_addr={}, scn={}, is_server={}, mtu={}, uuid={}, " + "no resources, bd_addr={}, scn={}, is_server={}, mtu={}, uuid=0x{:x}, " "dlci={}", - bd_addr, scn, is_server, mtu, loghex(uuid), dlci); + bd_addr, scn, is_server, mtu, uuid, dlci); return PORT_NO_RESOURCES; } p_port->sec_mask = sec_mask; @@ -222,10 +221,10 @@ int RFCOMM_CreateConnectionWithSecurity(uint16_t uuid, uint8_t scn, p_port->bd_addr = bd_addr; log::info( - "bd_addr={}, scn={}, is_server={}, mtu={}, uuid={}, dlci={}, " - "signal_state={}, p_port={}", - bd_addr, scn, is_server, mtu, loghex(uuid), dlci, - loghex(p_port->default_signal_state), fmt::ptr(p_port)); + "bd_addr={}, scn={}, is_server={}, mtu={}, uuid=0x{:x}, dlci={}, " + "signal_state=0x{:x}, p_port={}", + bd_addr, scn, is_server, mtu, uuid, dlci, p_port->default_signal_state, + fmt::ptr(p_port)); // If this is not initiator of the connection need to just wait if (p_port->is_server) { @@ -516,7 +515,7 @@ int PORT_CheckConnection(uint16_t handle, RawAddress* bd_addr, "handle={}, in_use={}, port_state={}, p_mcb={}, peer_ready={}, " "rfc_state={}", handle, p_port->in_use, p_port->state, fmt::ptr(p_port->rfc.p_mcb), - (p_port->rfc.p_mcb ? p_port->rfc.p_mcb->peer_ready : -1), + p_port->rfc.p_mcb ? p_port->rfc.p_mcb->peer_ready : -1, p_port->rfc.state); if (!p_port->in_use || (p_port->state == PORT_CONNECTION_STATE_CLOSED)) { @@ -828,7 +827,7 @@ int PORT_ReadData(uint16_t handle, char* p_data, uint16_t max_len, if (*p_len == 1) { log::verbose("PORT_ReadData queue:{} returned:{} {:x}", - p_port->rx.queue_size, *p_len, (p_data[0])); + p_port->rx.queue_size, *p_len, p_data[0]); } else { log::verbose("PORT_ReadData queue:{} returned:{}", p_port->rx.queue_size, *p_len); @@ -883,9 +882,8 @@ static int port_write(tPORT* p_port, BT_HDR* p_buf) { log::verbose( "PORT_Write : Data is enqued. flow disabled {} peer_ready {} state {} " "ctrl_state {:x}", - p_port->tx.peer_fc, - (p_port->rfc.p_mcb && p_port->rfc.p_mcb->peer_ready), p_port->rfc.state, - p_port->port_ctrl); + p_port->tx.peer_fc, p_port->rfc.p_mcb && p_port->rfc.p_mcb->peer_ready, + p_port->rfc.state, p_port->port_ctrl); fixed_queue_enqueue(p_port->tx.queue, p_buf); p_port->tx.queue_size += p_buf->len; diff --git a/system/stack/rfcomm/port_rfc.cc b/system/stack/rfcomm/port_rfc.cc index 27b840a083..444a3df48b 100644 --- a/system/stack/rfcomm/port_rfc.cc +++ b/system/stack/rfcomm/port_rfc.cc @@ -621,10 +621,10 @@ void PORT_ControlInd(tRFC_MCB* p_mcb, uint8_t dlci, tPORT_CTRL* p_pars) { if (event && p_port->p_callback) (p_port->p_callback)(event, p_port->handle); log::verbose("PORT_ControlInd DTR_DSR : {}, RTS_CTS : {}, RI : {}, DCD : {}", - ((p_port->peer_ctrl.modem_signal & MODEM_SIGNAL_DTRDSR) ? 1 : 0), - ((p_port->peer_ctrl.modem_signal & MODEM_SIGNAL_RTSCTS) ? 1 : 0), - ((p_port->peer_ctrl.modem_signal & MODEM_SIGNAL_RI) ? 1 : 0), - ((p_port->peer_ctrl.modem_signal & MODEM_SIGNAL_DCD) ? 1 : 0)); + (p_port->peer_ctrl.modem_signal & MODEM_SIGNAL_DTRDSR) ? 1 : 0, + (p_port->peer_ctrl.modem_signal & MODEM_SIGNAL_RTSCTS) ? 1 : 0, + (p_port->peer_ctrl.modem_signal & MODEM_SIGNAL_RI) ? 1 : 0, + (p_port->peer_ctrl.modem_signal & MODEM_SIGNAL_DCD) ? 1 : 0); } /******************************************************************************* @@ -1019,10 +1019,10 @@ void port_rfc_closed(tPORT* p_port, uint8_t res) { p_port->rfc.state = RFC_STATE_CLOSED; log::info( - "RFCOMM connection closed, index={}, state={}, reason={}[{}], UUID={}, " - "bd_addr={}, is_server={}", + "RFCOMM connection closed, index={}, state={}, reason={}[{}], " + "UUID=0x{:x}, bd_addr={}, is_server={}", p_port->handle, p_port->state, PORT_GetResultString(res), res, - loghex(p_port->uuid), p_port->bd_addr, p_port->is_server); + p_port->uuid, p_port->bd_addr, p_port->is_server); port_release_port(p_port); } diff --git a/system/stack/rfcomm/port_utils.cc b/system/stack/rfcomm/port_utils.cc index 04cab150d5..05abf99aa8 100644 --- a/system/stack/rfcomm/port_utils.cc +++ b/system/stack/rfcomm/port_utils.cc @@ -284,8 +284,8 @@ tRFC_MCB* port_find_mcb(const RawAddress& bd_addr) { for (tRFC_MCB& mcb : rfc_cb.port.rfc_mcb) { if ((mcb.state != RFC_MX_STATE_IDLE) && (mcb.bd_addr == bd_addr)) { /* Multiplexer channel found do not change anything */ - log::verbose("found, bd_addr:{}, rfc_mcb:{}, lcid:{}", bd_addr, - fmt::ptr(&mcb), loghex(mcb.lcid)); + log::verbose("found, bd_addr:{}, rfc_mcb:{}, lcid:0x{:x}", bd_addr, + fmt::ptr(&mcb), mcb.lcid); return &mcb; } } diff --git a/system/stack/rfcomm/rfc_l2cap_if.cc b/system/stack/rfcomm/rfc_l2cap_if.cc index 5f5099d862..5627b1acec 100644 --- a/system/stack/rfcomm/rfc_l2cap_if.cc +++ b/system/stack/rfcomm/rfc_l2cap_if.cc @@ -235,10 +235,10 @@ void RFCOMM_ConfigCnf(uint16_t lcid, uint16_t /* initiator */, * ******************************************************************************/ void RFCOMM_DisconnectInd(uint16_t lcid, bool is_conf_needed) { - log::verbose("lcid:{}, is_conf_needed:{}", loghex(lcid), is_conf_needed); + log::verbose("lcid:0x{:x}, is_conf_needed:{}", lcid, is_conf_needed); tRFC_MCB* p_mcb = rfc_find_lcid_mcb(lcid); if (!p_mcb) { - log::warn("no mcb for lcid {}", loghex(lcid)); + log::warn("no mcb for lcid 0x{:x}", lcid); return; } rfc_mx_sm_execute(p_mcb, RFC_MX_EVENT_DISC_IND, nullptr); @@ -258,7 +258,7 @@ void RFCOMM_BufDataInd(uint16_t lcid, BT_HDR* p_buf) { tRFC_MCB* p_mcb = rfc_find_lcid_mcb(lcid); if (!p_mcb) { - log::warn("Cannot find RFCOMM multiplexer for lcid {}", loghex(lcid)); + log::warn("Cannot find RFCOMM multiplexer for lcid 0x{:x}", lcid); osi_free(p_buf); return; } @@ -267,8 +267,8 @@ void RFCOMM_BufDataInd(uint16_t lcid, BT_HDR* p_buf) { /* If the frame did not pass validation just ignore it */ if (event == RFC_EVENT_BAD_FRAME) { - log::warn("Bad RFCOMM frame from lcid={}, bd_addr={}, p_mcb={}", - loghex(lcid), p_mcb->bd_addr, fmt::ptr(p_mcb)); + log::warn("Bad RFCOMM frame from lcid=0x{:x}, bd_addr={}, p_mcb={}", lcid, + p_mcb->bd_addr, fmt::ptr(p_mcb)); osi_free(p_buf); return; } @@ -293,12 +293,12 @@ void RFCOMM_BufDataInd(uint16_t lcid, BT_HDR* p_buf) { if (p_port == nullptr || !p_port->rfc.p_mcb) { /* If this is a SABME on new port, check if any app is waiting for it */ if (event != RFC_EVENT_SABME) { - log::warn("no for none-SABME event, lcid={}, bd_addr={}, p_mcb={}", - loghex(lcid), p_mcb->bd_addr, fmt::ptr(p_mcb)); + log::warn("no for none-SABME event, lcid=0x{:x}, bd_addr={}, p_mcb={}", + lcid, p_mcb->bd_addr, fmt::ptr(p_mcb)); if ((p_mcb->is_initiator && !rfc_cb.rfc.rx_frame.cr) || (!p_mcb->is_initiator && rfc_cb.rfc.rx_frame.cr)) { - log::error("Disconnecting RFCOMM, lcid={}, bd_addr={}, p_mcb={}", - loghex(lcid), p_mcb->bd_addr, fmt::ptr(p_mcb)); + log::error("Disconnecting RFCOMM, lcid=0x{:x}, bd_addr={}, p_mcb={}", + lcid, p_mcb->bd_addr, fmt::ptr(p_mcb)); rfc_send_dm(p_mcb, rfc_cb.rfc.rx_frame.dlci, rfc_cb.rfc.rx_frame.pf); } osi_free(p_buf); @@ -308,10 +308,9 @@ void RFCOMM_BufDataInd(uint16_t lcid, BT_HDR* p_buf) { p_port = port_find_dlci_port(rfc_cb.rfc.rx_frame.dlci); if (p_port == nullptr) { log::error( - "Disconnecting RFCOMM, no port for dlci {}, lcid={}, bd_addr={}, " + "Disconnecting RFCOMM, no port for dlci {}, lcid=0x{:x}, bd_addr={}, " "p_mcb={}", - rfc_cb.rfc.rx_frame.dlci, loghex(lcid), p_mcb->bd_addr, - fmt::ptr(p_mcb)); + rfc_cb.rfc.rx_frame.dlci, lcid, p_mcb->bd_addr, fmt::ptr(p_mcb)); rfc_send_dm(p_mcb, rfc_cb.rfc.rx_frame.dlci, true); osi_free(p_buf); return; @@ -374,8 +373,8 @@ tRFC_MCB* rfc_find_lcid_mcb(uint16_t lcid) { tRFC_MCB* p_mcb = rfc_lcid_mcb[lcid]; if (p_mcb != nullptr) { if (p_mcb->lcid != lcid) { - log::warn("LCID reused lcid=:{}, current_lcid={}", loghex(lcid), - loghex(p_mcb->lcid)); + log::warn("LCID reused lcid=:0x{:x}, current_lcid=0x{:x}", lcid, + p_mcb->lcid); return nullptr; } } diff --git a/system/stack/sdp/sdp_utils.cc b/system/stack/sdp/sdp_utils.cc index 14d485aeb9..5ada62c136 100644 --- a/system/stack/sdp/sdp_utils.cc +++ b/system/stack/sdp/sdp_utils.cc @@ -107,8 +107,8 @@ static std::vector<std::pair<uint16_t, uint16_t>> sdpu_find_profile_version( // Safety check - each entry should itself be a sequence if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) != DATA_ELE_SEQ_DESC_TYPE) { - log::warn("Descriptor type is not sequence: {}", - loghex(SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type))); + log::warn("Descriptor type is not sequence: 0x{:x}", + SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type)); return std::vector<std::pair<uint16_t, uint16_t>>(); } // Now, see if the entry contains the profile UUID we are interested in @@ -127,8 +127,8 @@ static std::vector<std::pair<uint16_t, uint16_t>> sdpu_find_profile_version( if (version_attr == nullptr) { log::warn("version attr not found"); } else { - log::warn("Bad version type {}, or length {}", - loghex(SDP_DISC_ATTR_TYPE(version_attr->attr_len_type)), + log::warn("Bad version type 0x{:x}, or length {}", + SDP_DISC_ATTR_TYPE(version_attr->attr_len_type), SDP_DISC_ATTR_LEN(version_attr->attr_len_type)); } return std::vector<std::pair<uint16_t, uint16_t>>(); diff --git a/system/stack/test/a2dp/a2dp_aac_unittest.cc b/system/stack/test/a2dp/a2dp_aac_unittest.cc index 9323214ffc..2ae209b966 100644 --- a/system/stack/test/a2dp/a2dp_aac_unittest.cc +++ b/system/stack/test/a2dp/a2dp_aac_unittest.cc @@ -18,7 +18,6 @@ #include <bluetooth/log.h> #include <gtest/gtest.h> -#include <stdio.h> #include <cstdint> #include <string> diff --git a/system/stack/test/a2dp/a2dp_opus_unittest.cc b/system/stack/test/a2dp/a2dp_opus_unittest.cc index 6ca8a45689..e9feb0efd6 100644 --- a/system/stack/test/a2dp/a2dp_opus_unittest.cc +++ b/system/stack/test/a2dp/a2dp_opus_unittest.cc @@ -15,7 +15,6 @@ */ #include <gtest/gtest.h> -#include <stdio.h> #include <chrono> #include <cstdint> diff --git a/system/stack/test/a2dp/a2dp_sbc_unittest.cc b/system/stack/test/a2dp/a2dp_sbc_unittest.cc index cdd513b76a..9aacf700b0 100644 --- a/system/stack/test/a2dp/a2dp_sbc_unittest.cc +++ b/system/stack/test/a2dp/a2dp_sbc_unittest.cc @@ -17,7 +17,6 @@ #include "stack/include/a2dp_sbc.h" #include <gtest/gtest.h> -#include <stdio.h> #include <chrono> #include <cstdint> diff --git a/system/stack/test/a2dp/a2dp_vendor_ldac_unittest.cc b/system/stack/test/a2dp/a2dp_vendor_ldac_unittest.cc index 96a6461d0f..ea8575df35 100644 --- a/system/stack/test/a2dp/a2dp_vendor_ldac_unittest.cc +++ b/system/stack/test/a2dp/a2dp_vendor_ldac_unittest.cc @@ -17,7 +17,6 @@ #include "stack/include/a2dp_vendor_ldac.h" #include <gtest/gtest.h> -#include <stdio.h> #include "common/init_flags.h" #include "common/time_util.h" diff --git a/system/stack/test/gatt/gatt_sr_test.cc b/system/stack/test/gatt/gatt_sr_test.cc index 8772bc745d..5ec359780f 100644 --- a/system/stack/test/gatt/gatt_sr_test.cc +++ b/system/stack/test/gatt/gatt_sr_test.cc @@ -15,7 +15,6 @@ */ #include <gtest/gtest.h> -#include <stdio.h> #include <cstdint> diff --git a/system/test/common/mock_functions.cc b/system/test/common/mock_functions.cc index 7532d4c982..d69f5a8b16 100644 --- a/system/test/common/mock_functions.cc +++ b/system/test/common/mock_functions.cc @@ -19,8 +19,9 @@ #include <bluetooth/log.h> #include <map> +#include <mutex> -#include "os/log.h" +std::mutex mutex_{}; static std::map<std::string, int>& _get_func_call_count_map() { static std::map<std::string, int> mock_function_count_map; @@ -28,15 +29,26 @@ static std::map<std::string, int>& _get_func_call_count_map() { } int get_func_call_count(const char* fn) { + std::lock_guard<std::mutex> lock(mutex_); return _get_func_call_count_map()[fn]; } -void inc_func_call_count(const char* fn) { _get_func_call_count_map()[fn]++; } +void inc_func_call_count(const char* fn) { + std::lock_guard<std::mutex> lock(mutex_); + _get_func_call_count_map()[fn]++; +} -void reset_mock_function_count_map() { _get_func_call_count_map().clear(); } +void reset_mock_function_count_map() { + std::lock_guard<std::mutex> lock(mutex_); + _get_func_call_count_map().clear(); +} -int get_func_call_size() { return _get_func_call_count_map().size(); } +int get_func_call_size() { + std::lock_guard<std::mutex> lock(mutex_); + return _get_func_call_count_map().size(); +} void dump_mock_function_count_map() { + std::lock_guard<std::mutex> lock(mutex_); bluetooth::log::info("Mock function count map size:{}", _get_func_call_count_map().size()); diff --git a/system/test/headless/get_options.cc b/system/test/headless/get_options.cc index b11944f6b0..79817e1dfe 100644 --- a/system/test/headless/get_options.cc +++ b/system/test/headless/get_options.cc @@ -17,7 +17,6 @@ #include "test/headless/get_options.h" #include <getopt.h> -#include <stdio.h> #include <unistd.h> #include <list> diff --git a/system/test/headless/headless.cc b/system/test/headless/headless.cc index 03651716ce..869373ea90 100644 --- a/system/test/headless/headless.cc +++ b/system/test/headless/headless.cc @@ -146,8 +146,6 @@ void pin_request([[maybe_unused]] RawAddress* remote_bd_addr, } void ssp_request([[maybe_unused]] RawAddress* remote_bd_addr, - [[maybe_unused]] bt_bdname_t* bd_name, - [[maybe_unused]] uint32_t cod, [[maybe_unused]] bt_ssp_variant_t pairing_variant, [[maybe_unused]] uint32_t pass_key) { log::info(""); diff --git a/system/test/headless/main.cc b/system/test/headless/main.cc index 6cba5ac02b..658a60ed32 100644 --- a/system/test/headless/main.cc +++ b/system/test/headless/main.cc @@ -18,7 +18,6 @@ #include <bluetooth/log.h> #include <fcntl.h> -#include <stdio.h> #include <sys/socket.h> #include <sys/wait.h> #include <unistd.h> diff --git a/system/test/headless/sdp/sdp.cc b/system/test/headless/sdp/sdp.cc index 92ce04511e..ece2368629 100644 --- a/system/test/headless/sdp/sdp.cc +++ b/system/test/headless/sdp/sdp.cc @@ -22,8 +22,6 @@ #include "bta/dm/bta_dm_int.h" #include "bta/include/bta_api.h" -#include "os/log.h" -#include "osi/include/osi.h" // UNUSED_ATTR #include "stack/include/sdp_api.h" #include "test/headless/get_options.h" #include "test/headless/headless.h" @@ -34,9 +32,9 @@ using namespace bluetooth::legacy::stack::sdp; using namespace bluetooth::test::headless; -static void bta_jv_start_discovery_callback( - UNUSED_ATTR const RawAddress& bd_addr, tSDP_STATUS result, - const void* user_data) { +static void bta_jv_start_discovery_callback(const RawAddress& /* bd_addr */, + tSDP_STATUS result, + const void* user_data) { auto promise = static_cast<std::promise<uint16_t>*>(const_cast<void*>(user_data)); promise->set_value(result); diff --git a/system/test/mock/mock_bluetooth_interface.cc b/system/test/mock/mock_bluetooth_interface.cc index 86edb3faef..112fd29f0a 100644 --- a/system/test/mock/mock_bluetooth_interface.cc +++ b/system/test/mock/mock_bluetooth_interface.cc @@ -34,8 +34,7 @@ void invoke_device_found_cb(int /* num_properties */, void invoke_discovery_state_changed_cb(bt_discovery_state_t /* state */) {} void invoke_pin_request_cb(RawAddress /* bd_addr */, bt_bdname_t /* bd_name */, uint32_t /* cod */, bool /* min_16_digit */) {} -void invoke_ssp_request_cb(RawAddress /* bd_addr */, bt_bdname_t /* bd_name */, - uint32_t /* cod */, +void invoke_ssp_request_cb(RawAddress /* bd_addr */, bt_ssp_variant_t /* pairing_variant */, uint32_t /* pass_key */) {} void invoke_oob_data_request_cb(tBT_TRANSPORT /* t */, bool /* valid */, diff --git a/system/test/mock/mock_bta_dm_act.cc b/system/test/mock/mock_bta_dm_act.cc index 2e63eb351e..51fd7de097 100644 --- a/system/test/mock/mock_bta_dm_act.cc +++ b/system/test/mock/mock_bta_dm_act.cc @@ -45,7 +45,6 @@ struct BTA_dm_notify_remote_features_complete struct BTA_dm_on_hw_off BTA_dm_on_hw_off; struct BTA_dm_on_hw_on BTA_dm_on_hw_on; struct BTA_dm_report_role_change BTA_dm_report_role_change; -struct bta_dm_acl_up bta_dm_acl_up; struct bta_dm_add_ble_device bta_dm_add_ble_device; struct bta_dm_add_blekey bta_dm_add_blekey; struct bta_dm_ble_config_local_privacy bta_dm_ble_config_local_privacy; @@ -73,7 +72,6 @@ struct bta_dm_process_remove_device bta_dm_process_remove_device; struct bta_dm_remove_device bta_dm_remove_device; struct bta_dm_remote_key_missing bta_dm_remote_key_missing; struct bta_dm_rm_cback bta_dm_rm_cback; -struct bta_dm_sdp_result bta_dm_sdp_result; struct bta_dm_set_dev_name bta_dm_set_dev_name; struct bta_dm_set_encryption bta_dm_set_encryption; struct handle_remote_features_complete handle_remote_features_complete; @@ -119,11 +117,6 @@ void BTA_dm_report_role_change(const RawAddress bd_addr, tHCI_ROLE new_role, test::mock::bta_dm_act::BTA_dm_report_role_change(bd_addr, new_role, hci_status); } -void bta_dm_acl_up(const RawAddress& bd_addr, tBT_TRANSPORT transport, - uint16_t acl_handle) { - inc_func_call_count(__func__); - test::mock::bta_dm_act::bta_dm_acl_up(bd_addr, transport, acl_handle); -} void bta_dm_add_ble_device(const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type, tBT_DEVICE_TYPE dev_type) { inc_func_call_count(__func__); @@ -250,10 +243,6 @@ void bta_dm_rm_cback(tBTA_SYS_CONN_STATUS status, uint8_t id, uint8_t app_id, inc_func_call_count(__func__); test::mock::bta_dm_act::bta_dm_rm_cback(status, id, app_id, peer_addr); } -void bta_dm_sdp_result(tBTA_DM_SDP_RESULT& sdp_event) { - inc_func_call_count(__func__); - test::mock::bta_dm_act::bta_dm_sdp_result(sdp_event); -} void bta_dm_set_dev_name(const std::vector<uint8_t>& name) { inc_func_call_count(__func__); test::mock::bta_dm_act::bta_dm_set_dev_name(name); diff --git a/system/test/mock/mock_bta_dm_act.h b/system/test/mock/mock_bta_dm_act.h index 4ca3c2d716..d16693495b 100644 --- a/system/test/mock/mock_bta_dm_act.h +++ b/system/test/mock/mock_bta_dm_act.h @@ -135,21 +135,6 @@ struct BTA_dm_report_role_change { }; extern struct BTA_dm_report_role_change BTA_dm_report_role_change; -// Name: bta_dm_acl_up -// Params: const RawAddress& bd_addr, tBT_TRANSPORT transport -// Return: void -struct bta_dm_acl_up { - std::function<void(const RawAddress& bd_addr, tBT_TRANSPORT transport, - uint16_t acl_handle)> - body{[](const RawAddress& /* bd_addr */, tBT_TRANSPORT /* transport */, - uint16_t /* acl_handle */) {}}; - void operator()(const RawAddress& bd_addr, tBT_TRANSPORT transport, - uint16_t acl_handle) { - body(bd_addr, transport, acl_handle); - }; -}; -extern struct bta_dm_acl_up bta_dm_acl_up; - // Name: bta_dm_add_ble_device // Params: const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type, tBT_DEVICE_TYPE // dev_type Return: void @@ -504,16 +489,6 @@ struct bta_dm_rm_cback { }; extern struct bta_dm_rm_cback bta_dm_rm_cback; -// Name: bta_dm_sdp_result -// Params: tBTA_DM_SDP_RESULT& sdp_event -// Return: void -struct bta_dm_sdp_result { - std::function<void(tBTA_DM_SDP_RESULT& sdp_event)> body{ - [](tBTA_DM_SDP_RESULT& /* sdp_event */) {}}; - void operator()(tBTA_DM_SDP_RESULT& sdp_event) { body(sdp_event); }; -}; -extern struct bta_dm_sdp_result bta_dm_sdp_result; - // Name: bta_dm_search_cancel_cmpl // Params: // Return: void diff --git a/system/test/mock/mock_bta_jv_api.cc b/system/test/mock/mock_bta_jv_api.cc index 5e9421f078..cb3f02bad7 100644 --- a/system/test/mock/mock_bta_jv_api.cc +++ b/system/test/mock/mock_bta_jv_api.cc @@ -78,7 +78,6 @@ tBTA_JV_STATUS BTA_JvRfcommClose(uint32_t /* handle */, return tBTA_JV_STATUS::SUCCESS; } tBTA_JV_STATUS BTA_JvRfcommConnect(tBTA_SEC /* sec_mask */, - tBTA_JV_ROLE /* role */, uint8_t /* remote_scn */, const RawAddress& /* peer_bd_addr */, tBTA_JV_RFCOMM_CBACK* /* p_cback */, @@ -87,7 +86,6 @@ tBTA_JV_STATUS BTA_JvRfcommConnect(tBTA_SEC /* sec_mask */, return tBTA_JV_STATUS::SUCCESS; } tBTA_JV_STATUS BTA_JvRfcommStartServer(tBTA_SEC /* sec_mask */, - tBTA_JV_ROLE /* role */, uint8_t /* local_scn */, uint8_t /* max_session */, tBTA_JV_RFCOMM_CBACK* /* p_cback */, @@ -127,7 +125,7 @@ void BTA_JvGetChannelId(tBTA_JV_CONN_TYPE /* conn_type */, uint32_t /* id */, inc_func_call_count(__func__); } void BTA_JvL2capConnect(tBTA_JV_CONN_TYPE /* conn_type */, - tBTA_SEC /* sec_mask */, tBTA_JV_ROLE /* role */, + tBTA_SEC /* sec_mask */, std::unique_ptr<tL2CAP_ERTM_INFO> /* ertm_info */, uint16_t /* remote_psm */, uint16_t /* rx_mtu */, std::unique_ptr<tL2CAP_CFG_INFO> /* cfg */, @@ -137,7 +135,7 @@ void BTA_JvL2capConnect(tBTA_JV_CONN_TYPE /* conn_type */, inc_func_call_count(__func__); } void BTA_JvL2capStartServer(tBTA_JV_CONN_TYPE /* conn_type */, - tBTA_SEC /* sec_mask */, tBTA_JV_ROLE /* role */, + tBTA_SEC /* sec_mask */, std::unique_ptr<tL2CAP_ERTM_INFO> /* ertm_info */, uint16_t /* local_psm */, uint16_t /* rx_mtu */, std::unique_ptr<tL2CAP_CFG_INFO> /* cfg */, diff --git a/system/test/mock/mock_btcore_module.h b/system/test/mock/mock_btcore_module.h index 4111626e6d..8b00a5a795 100644 --- a/system/test/mock/mock_btcore_module.h +++ b/system/test/mock/mock_btcore_module.h @@ -39,7 +39,7 @@ namespace btcore_module { struct get_module { const module_t* return_value{0}; std::function<const module_t*(const char* name)> body{ - [this](const char* name) { return return_value; }}; + [this](const char* /* name */) { return return_value; }}; const module_t* operator()(const char* name) { return body(name); }; }; extern struct get_module get_module; @@ -49,7 +49,7 @@ extern struct get_module get_module; // Return: void struct module_clean_up { std::function<void(const module_t* module)> body{ - [](const module_t* module) {}}; + [](const module_t* /* module */) {}}; void operator()(const module_t* module) { body(module); }; }; extern struct module_clean_up module_clean_up; @@ -60,7 +60,7 @@ extern struct module_clean_up module_clean_up; struct module_init { bool return_value{false}; std::function<bool(const module_t* module)> body{ - [this](const module_t* module) { return return_value; }}; + [this](const module_t* /* module */) { return return_value; }}; bool operator()(const module_t* module) { return body(module); }; }; extern struct module_init module_init; @@ -88,7 +88,7 @@ extern struct module_management_stop module_management_stop; // Return: void struct module_shut_down { std::function<void(const module_t* module)> body{ - [](const module_t* module) {}}; + [](const module_t* /* module */) {}}; void operator()(const module_t* module) { body(module); }; }; extern struct module_shut_down module_shut_down; @@ -99,7 +99,7 @@ extern struct module_shut_down module_shut_down; struct module_start_up { bool return_value{false}; std::function<bool(const module_t* module)> body{ - [this](const module_t* module) { return return_value; }}; + [this](const module_t* /* module */) { return return_value; }}; bool operator()(const module_t* module) { return body(module); }; }; extern struct module_start_up module_start_up; @@ -108,4 +108,4 @@ extern struct module_start_up module_start_up; } // namespace mock } // namespace test -// END mockcify generation
\ No newline at end of file +// END mockcify generation diff --git a/system/test/mock/mock_osi_config.h b/system/test/mock/mock_osi_config.h index 672dc1c49f..5b3cd4355b 100644 --- a/system/test/mock/mock_osi_config.h +++ b/system/test/mock/mock_osi_config.h @@ -29,7 +29,6 @@ #include <base/files/file_util.h> #include <fcntl.h> #include <libgen.h> -#include <stdio.h> #include <stdlib.h> #include <sys/stat.h> #include <unistd.h> diff --git a/system/test/mock/mock_stack_arbiter_acl_arbiter.cc b/system/test/mock/mock_stack_arbiter_acl_arbiter.cc index c0086b5f05..4fdd141884 100644 --- a/system/test/mock/mock_stack_arbiter_acl_arbiter.cc +++ b/system/test/mock/mock_stack_arbiter_acl_arbiter.cc @@ -20,32 +20,25 @@ namespace bluetooth { namespace shim { namespace arbiter { -class MockAclArbiter : public AclArbiter { - public: - virtual void OnLeConnect(uint8_t /* tcb_idx */, - uint16_t /* advertiser_id */) override {} +void AclArbiter::OnLeConnect(uint8_t /* tcb_idx */, + uint16_t /* advertiser_id */) {} - virtual void OnLeDisconnect(uint8_t /* tcb_idx */) override {} +void AclArbiter::OnLeDisconnect(uint8_t /* tcb_idx */) {} - virtual InterceptAction InterceptAttPacket( - uint8_t /* tcb_idx */, const BT_HDR* /* packet */) override { - return InterceptAction::FORWARD; - } - - virtual void OnOutgoingMtuReq(uint8_t /* tcb_idx */) override {} +InterceptAction AclArbiter::InterceptAttPacket(uint8_t /* tcb_idx */, + const BT_HDR* /* packet */) { + return InterceptAction::FORWARD; +} - virtual void OnIncomingMtuResp(uint8_t /* tcb_idx */, size_t /* mtu */) {} +void AclArbiter::OnOutgoingMtuReq(uint8_t /* tcb_idx */) {} - virtual void OnIncomingMtuReq(uint8_t /* tcb_idx */, size_t /* mtu */) {} +void AclArbiter::OnIncomingMtuResp(uint8_t /* tcb_idx */, size_t /* mtu */) {} - static MockAclArbiter& Get() { - static auto singleton = MockAclArbiter(); - return singleton; - } -}; +void AclArbiter::OnIncomingMtuReq(uint8_t /* tcb_idx */, size_t /* mtu */) {} AclArbiter& GetArbiter() { - return static_cast<AclArbiter&>(MockAclArbiter::Get()); + static auto singleton = AclArbiter(); + return singleton; } } // namespace arbiter diff --git a/system/test/mock/mock_stack_btm_dev.cc b/system/test/mock/mock_stack_btm_dev.cc index 2359382921..bab842520a 100644 --- a/system/test/mock/mock_stack_btm_dev.cc +++ b/system/test/mock/mock_stack_btm_dev.cc @@ -22,7 +22,6 @@ #include "test/mock/mock_stack_btm_dev.h" #include <stddef.h> -#include <stdio.h> #include <stdlib.h> #include <string> diff --git a/system/test/mock/mock_stack_btm_inq.h b/system/test/mock/mock_stack_btm_inq.h index 139fc36823..205ab037da 100644 --- a/system/test/mock/mock_stack_btm_inq.h +++ b/system/test/mock/mock_stack_btm_inq.h @@ -28,7 +28,6 @@ // Original included files, if any #include <stddef.h> -#include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/system/test/mock/mock_stack_gatt_api.h b/system/test/mock/mock_stack_gatt_api.h index ea487e1b60..d9c5afaa1a 100644 --- a/system/test/mock/mock_stack_gatt_api.h +++ b/system/test/mock/mock_stack_gatt_api.h @@ -29,7 +29,6 @@ // Original included files, if any #include <base/strings/string_number_conversions.h> -#include <stdio.h> #include <string> diff --git a/system/test/mock/mock_stack_hidd_api.cc b/system/test/mock/mock_stack_hidd_api.cc index 581f952902..afff3e5515 100644 --- a/system/test/mock/mock_stack_hidd_api.cc +++ b/system/test/mock/mock_stack_hidd_api.cc @@ -19,7 +19,6 @@ * Functions generated:16 */ -#include <stdio.h> #include <stdlib.h> #include "stack/include/hidd_api.h" diff --git a/system/test/mock/mock_stack_sdp_db.cc b/system/test/mock/mock_stack_sdp_db.cc index f009c982f5..76b68c2cf9 100644 --- a/system/test/mock/mock_stack_sdp_db.cc +++ b/system/test/mock/mock_stack_sdp_db.cc @@ -19,8 +19,6 @@ * Functions generated:14 */ -#include <stdio.h> - #include "stack/sdp/sdpint.h" #include "test/common/mock_functions.h" diff --git a/system/test/stub/osi.cc b/system/test/stub/osi.cc index 894c009886..4566964423 100644 --- a/system/test/stub/osi.cc +++ b/system/test/stub/osi.cc @@ -43,10 +43,6 @@ #include "test/common/fake_osi.h" #include "test/common/mock_functions.h" -#ifndef UNUSED_ATTR -#define UNUSED_ATTR -#endif - OsiObject::OsiObject(void* ptr) : ptr_(ptr) {} OsiObject::OsiObject(const void* ptr) : ptr_(const_cast<void*>(ptr)) {} @@ -467,7 +463,7 @@ list_node_t* list_begin(const list_t* list) { inc_func_call_count(__func__); return nullptr; } -list_node_t* list_end(UNUSED_ATTR const list_t* list) { +list_node_t* list_end(const list_t* /* list */) { inc_func_call_count(__func__); return nullptr; } @@ -513,7 +509,7 @@ int osi_socket_local_client(const char* name, int namespaceId, int type) { return 0; } int osi_socket_local_client_connect(int fd, const char* name, int namespaceId, - int type UNUSED_ATTR) { + int type) { inc_func_call_count(__func__); return 0; } diff --git a/system/test/suite/adapter/bluetooth_test.cc b/system/test/suite/adapter/bluetooth_test.cc index 1f003bbf3f..126ca290a0 100644 --- a/system/test/suite/adapter/bluetooth_test.cc +++ b/system/test/suite/adapter/bluetooth_test.cc @@ -19,7 +19,6 @@ #include "adapter/bluetooth_test.h" #include <binder/ProcessState.h> -#include <stdio.h> #include <mutex> diff --git a/system/udrv/ulinux/uipc.cc b/system/udrv/ulinux/uipc.cc index 7de87c992f..28f59c7d81 100644 --- a/system/udrv/ulinux/uipc.cc +++ b/system/udrv/ulinux/uipc.cc @@ -31,7 +31,6 @@ #include <bluetooth/log.h> #include <fcntl.h> #include <poll.h> -#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/mman.h> @@ -579,9 +578,8 @@ void UIPC_Close(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id) { ** Returns true in case of success, false in case of failure. ** ******************************************************************************/ -bool UIPC_Send(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id, - UNUSED_ATTR uint16_t msg_evt, const uint8_t* p_buf, - uint16_t msglen) { +bool UIPC_Send(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id, uint16_t /* msg_evt */, + const uint8_t* p_buf, uint16_t msglen) { log::verbose("UIPC_Send : ch_id:{} {} bytes", ch_id, msglen); std::lock_guard<std::recursive_mutex> lock(uipc.mutex); diff --git a/tools/OWNERS b/tools/OWNERS index 1979131142..ee61736b29 100644 --- a/tools/OWNERS +++ b/tools/OWNERS @@ -4,5 +4,4 @@ cmanton@google.com jpawlowski@google.com licorne@google.com mylesgw@google.com -sattiraju@google.com siyuanh@google.com diff --git a/tools/rootcanal/model/controller/dual_mode_controller.cc b/tools/rootcanal/model/controller/dual_mode_controller.cc index 9345253261..aa65fe4fd4 100644 --- a/tools/rootcanal/model/controller/dual_mode_controller.cc +++ b/tools/rootcanal/model/controller/dual_mode_controller.cc @@ -49,7 +49,7 @@ constexpr uint16_t kLeMaximumDataLength = 64; constexpr uint16_t kLeMaximumDataTime = 0x148; constexpr uint8_t kTransmitPowerLevel = -20; -constexpr bool kLeApcfTransportDiscoveryDataFilterSupported = true; +constexpr bool kLeApcfTransportDiscoveryDataFilterSupported = false; constexpr bool kLeApcfAdTypeFilterSupported = true; #define CHECK_PACKET_VIEW(view) \ |