diff options
author | Haamed Gheibi <haamed@google.com> | 2022-02-04 13:47:26 -0800 |
---|---|---|
committer | Haamed Gheibi <haamed@google.com> | 2022-02-04 13:55:47 -0800 |
commit | f99b35c293439db0b7436b47b939eb8c7bf21b51 (patch) | |
tree | 6cd9b0719554809447c845616317cca5409b93ae /bluetooth/audio | |
parent | a028272dee9220e6810cbdcfb2328c34f8afe4c2 (diff) | |
parent | 332dead340bb196c6ba3f6978e8fb53966c74bf7 (diff) |
Merge TP1A.220120.003
Change-Id: Ie5eba313ee102e452f5f96942ed2f3a7bb4e8f01
Diffstat (limited to 'bluetooth/audio')
81 files changed, 4181 insertions, 128 deletions
diff --git a/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp b/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp index 9435311b13..490a436b5e 100644 --- a/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp +++ b/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp @@ -233,7 +233,7 @@ Return<void> BluetoothAudioProvidersFactory::getProviderCapabilities_2_2( LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH || sessionType == V2_1::SessionType:: LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) { - std::vector<LeAudioCodecCapabilitiesPair> db_codec_capabilities = + std::vector<LeAudioCodecCapabilitiesSetting> db_codec_capabilities = android::bluetooth::audio::GetLeAudioOffloadCodecCapabilities( sessionType); if (db_codec_capabilities.size()) { diff --git a/bluetooth/audio/2.2/types.hal b/bluetooth/audio/2.2/types.hal index 8ec366060c..67558995f9 100644 --- a/bluetooth/audio/2.2/types.hal +++ b/bluetooth/audio/2.2/types.hal @@ -83,23 +83,22 @@ safe_union AudioConfiguration { safe_union AudioCapabilities { PcmParameters pcmCapabilities; CodecCapabilities codecCapabilities; - LeAudioCodecCapabilitiesPair leAudioCapabilities; + LeAudioCodecCapabilitiesSetting leAudioCapabilities; }; /** - * Used to specify th le audio capabilities pair of the Hardware offload encode and decode. + * Used to specify the le audio capabilities for unicast and broadcast hardware offload. */ -struct LeAudioCodecCapabilitiesPair{ - LeAudioMode mode; - LeAudioCodecCapability encodeCapability; - LeAudioCodecCapability decodeCapability; +struct LeAudioCodecCapabilitiesSetting{ + UnicastCapability unicastEncodeCapability; + UnicastCapability unicastDecodeCapability; + BroadcastCapability broadcastCapability; }; /** - * Used to specify the le audio capabilities of the codecs supported by Hardware offload - * for encode or decode. + * Used to specify the le audio unicast codec capabilities for hardware offload. */ -struct LeAudioCodecCapability { +struct UnicastCapability { CodecType codecType; AudioLocation supportedChannel; @@ -112,3 +111,17 @@ struct LeAudioCodecCapability { // Should use safe union when there is more than one codec Lc3Parameters capabilities; }; + +/** + * Used to specify the le audio broadcast codec capabilities for hardware offload. + */ +struct BroadcastCapability { + CodecType codecType; + AudioLocation supportedChannel; + + // Supported channel count for each stream + uint8_t channelCountPerStream; + + // Should use safe union when there is more than one codec + vec<Lc3Parameters> capabilities; +}; diff --git a/bluetooth/audio/aidl/Android.bp b/bluetooth/audio/aidl/Android.bp index 12eed55072..5107240957 100644 --- a/bluetooth/audio/aidl/Android.bp +++ b/bluetooth/audio/aidl/Android.bp @@ -43,6 +43,10 @@ aidl_interface { vndk: { enabled: true, }, + apex_available: [ + "//apex_available:platform", + "com.android.bluetooth", + ], }, }, } diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacCapabilities.aidl index ad44c26f59..899b8ca6db 100644 --- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacCapabilities.aidl +++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacCapabilities.aidl @@ -34,9 +34,9 @@ package android.hardware.bluetooth.audio; @VintfStability parcelable AacCapabilities { - android.hardware.bluetooth.audio.AacObjectType objectType; + android.hardware.bluetooth.audio.AacObjectType[] objectType; int[] sampleRateHz; - android.hardware.bluetooth.audio.ChannelMode channelMode; + android.hardware.bluetooth.audio.ChannelMode[] channelMode; boolean variableBitRateSupported; byte[] bitsPerSample; } diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacObjectType.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacObjectType.aidl index c129c66b40..2148244d06 100644 --- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacObjectType.aidl +++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacObjectType.aidl @@ -34,8 +34,8 @@ package android.hardware.bluetooth.audio; @Backing(type="byte") @VintfStability enum AacObjectType { - MPEG2_LC = 1, - MPEG4_LC = 2, - MPEG4_LTP = 4, - MPEG4_SCALABLE = 8, + MPEG2_LC = 0, + MPEG4_LC = 1, + MPEG4_LTP = 2, + MPEG4_SCALABLE = 3, } diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxCapabilities.aidl index 4767b696ec..08a38e26e1 100644 --- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxCapabilities.aidl +++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxCapabilities.aidl @@ -35,6 +35,6 @@ package android.hardware.bluetooth.audio; @VintfStability parcelable AptxCapabilities { int[] sampleRateHz; - android.hardware.bluetooth.audio.ChannelMode channelMode; + android.hardware.bluetooth.audio.ChannelMode[] channelMode; byte[] bitsPerSample; } diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioCapabilities.aidl index 20a7731010..8ae716ff23 100644 --- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioCapabilities.aidl +++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioCapabilities.aidl @@ -35,6 +35,6 @@ package android.hardware.bluetooth.audio; @VintfStability union AudioCapabilities { android.hardware.bluetooth.audio.PcmCapabilities pcmCapabilities; - android.hardware.bluetooth.audio.CodecCapabilities codecCapabilities; - android.hardware.bluetooth.audio.LeAudioCapabilities leAudioCapabilities; + android.hardware.bluetooth.audio.CodecCapabilities a2dpCapabilities; + android.hardware.bluetooth.audio.LeAudioCodecCapabilitiesSetting leAudioCapabilities; } diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioConfiguration.aidl index 34f7837967..50b54c30c0 100644 --- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioConfiguration.aidl +++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioConfiguration.aidl @@ -35,6 +35,6 @@ package android.hardware.bluetooth.audio; @VintfStability union AudioConfiguration { android.hardware.bluetooth.audio.PcmConfiguration pcmConfig; - android.hardware.bluetooth.audio.CodecConfiguration codecConfig; + android.hardware.bluetooth.audio.CodecConfiguration a2dpConfig; android.hardware.bluetooth.audio.LeAudioConfiguration leAudioConfig; } diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BroadcastCapability.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BroadcastCapability.aidl new file mode 100644 index 0000000000..58710effe7 --- /dev/null +++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BroadcastCapability.aidl @@ -0,0 +1,50 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.bluetooth.audio; +@VintfStability +parcelable BroadcastCapability { + android.hardware.bluetooth.audio.CodecType codecType; + android.hardware.bluetooth.audio.AudioLocation supportedChannel; + int channelCountPerStream; + android.hardware.bluetooth.audio.BroadcastCapability.LeAudioCodecCapabilities leAudioCodecCapabilities; + @VintfStability + parcelable VendorCapabilities { + ParcelableHolder extension; + } + @VintfStability + union LeAudioCodecCapabilities { + @nullable android.hardware.bluetooth.audio.Lc3Capabilities[] lc3Capabilities; + @nullable android.hardware.bluetooth.audio.BroadcastCapability.VendorCapabilities[] vendorCapabillities; + } +} diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BroadcastConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BroadcastConfiguration.aidl index b3aa709ddd..5fa392631b 100644 --- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BroadcastConfiguration.aidl +++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BroadcastConfiguration.aidl @@ -39,6 +39,6 @@ parcelable BroadcastConfiguration { parcelable BroadcastStreamMap { char streamHandle; int audioChannelAllocation; - android.hardware.bluetooth.audio.LeAudioCodecConfiguration leAudioCondecConfig; + android.hardware.bluetooth.audio.LeAudioCodecConfiguration leAudioCodecConfig; } } diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/ChannelMode.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/ChannelMode.aidl index 3ca93c3e03..c3bc7410e4 100644 --- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/ChannelMode.aidl +++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/ChannelMode.aidl @@ -34,7 +34,7 @@ package android.hardware.bluetooth.audio; @Backing(type="byte") @VintfStability enum ChannelMode { - UNKNOWN = 1, - MONO = 2, - STEREO = 4, + UNKNOWN = 0, + MONO = 1, + STEREO = 2, } diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecCapabilities.aidl index b451880e05..e2a08a0e6d 100644 --- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecCapabilities.aidl +++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecCapabilities.aidl @@ -42,5 +42,6 @@ parcelable CodecCapabilities { android.hardware.bluetooth.audio.AacCapabilities aacCapabilities; android.hardware.bluetooth.audio.LdacCapabilities ldacCapabilities; android.hardware.bluetooth.audio.AptxCapabilities aptxCapabilities; + android.hardware.bluetooth.audio.Lc3Capabilities lc3Capabilities; } } diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecConfiguration.aidl index 863aee244c..34ebd60530 100644 --- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecConfiguration.aidl +++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecConfiguration.aidl @@ -45,5 +45,6 @@ parcelable CodecConfiguration { android.hardware.bluetooth.audio.AacConfiguration aacConfig; android.hardware.bluetooth.audio.LdacConfiguration ldacConfig; android.hardware.bluetooth.audio.AptxConfiguration aptxConfig; + android.hardware.bluetooth.audio.Lc3Configuration lc3Config; } } diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl index e5e79cb1c4..0dcba2e818 100644 --- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl +++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl @@ -38,4 +38,5 @@ interface IBluetoothAudioProvider { android.hardware.common.fmq.MQDescriptor<byte,android.hardware.common.fmq.SynchronizedReadWrite> startSession(in android.hardware.bluetooth.audio.IBluetoothAudioPort hostIf, in android.hardware.bluetooth.audio.AudioConfiguration audioConfig); void streamStarted(in android.hardware.bluetooth.audio.BluetoothAudioStatus status); void streamSuspended(in android.hardware.bluetooth.audio.BluetoothAudioStatus status); + void updateAudioConfiguration(in android.hardware.bluetooth.audio.AudioConfiguration audioConfig); } diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Lc3Capabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Lc3Capabilities.aidl index 3c650da4f7..cc4449aea9 100644 --- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Lc3Capabilities.aidl +++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Lc3Capabilities.aidl @@ -39,4 +39,5 @@ parcelable Lc3Capabilities { int[] frameDurationUs; int[] octetsPerFrame; byte[] blocksPerSdu; + android.hardware.bluetooth.audio.ChannelMode[] channelMode; } diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Lc3Configuration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Lc3Configuration.aidl index ef77da7023..7e8dccff5f 100644 --- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Lc3Configuration.aidl +++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Lc3Configuration.aidl @@ -39,4 +39,5 @@ parcelable Lc3Configuration { int frameDurationUs; int octetsPerFrame; byte blocksPerSdu; + android.hardware.bluetooth.audio.ChannelMode channelMode; } diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacCapabilities.aidl index 19e041a15c..aa4e4c8793 100644 --- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacCapabilities.aidl +++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacCapabilities.aidl @@ -35,7 +35,7 @@ package android.hardware.bluetooth.audio; @VintfStability parcelable LdacCapabilities { int[] sampleRateHz; - android.hardware.bluetooth.audio.LdacChannelMode channelMode; - android.hardware.bluetooth.audio.LdacQualityIndex qualityIndex; + android.hardware.bluetooth.audio.LdacChannelMode[] channelMode; + android.hardware.bluetooth.audio.LdacQualityIndex[] qualityIndex; byte[] bitsPerSample; } diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacChannelMode.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacChannelMode.aidl index a9d6c5e14e..88d6faff53 100644 --- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacChannelMode.aidl +++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacChannelMode.aidl @@ -34,8 +34,8 @@ package android.hardware.bluetooth.audio; @Backing(type="byte") @VintfStability enum LdacChannelMode { - UNKNOWN = 1, - STEREO = 2, - DUAL = 4, - MONO = 8, + UNKNOWN = 0, + STEREO = 1, + DUAL = 2, + MONO = 3, } diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacQualityIndex.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacQualityIndex.aidl index 693392fe51..35e435867e 100644 --- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacQualityIndex.aidl +++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacQualityIndex.aidl @@ -34,8 +34,8 @@ package android.hardware.bluetooth.audio; @Backing(type="byte") @VintfStability enum LdacQualityIndex { - HIGH = 1, - MID = 2, - LOW = 4, - ABR = 8, + HIGH = 0, + MID = 1, + LOW = 2, + ABR = 3, } diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.aidl new file mode 100644 index 0000000000..9818d543ac --- /dev/null +++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.aidl @@ -0,0 +1,40 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.bluetooth.audio; +@VintfStability +parcelable LeAudioCodecCapabilitiesSetting { + android.hardware.bluetooth.audio.UnicastCapability unicastEncodeCapability; + android.hardware.bluetooth.audio.UnicastCapability unicastDecodeCapability; + android.hardware.bluetooth.audio.BroadcastCapability broadcastCapability; +} diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PcmCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PcmCapabilities.aidl index 6cfe5cd78c..0c2f87d599 100644 --- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PcmCapabilities.aidl +++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PcmCapabilities.aidl @@ -35,7 +35,7 @@ package android.hardware.bluetooth.audio; @VintfStability parcelable PcmCapabilities { int[] sampleRateHz; - android.hardware.bluetooth.audio.ChannelMode channelMode; + android.hardware.bluetooth.audio.ChannelMode[] channelMode; byte[] bitsPerSample; int[] dataIntervalUs; } diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcAllocMethod.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcAllocMethod.aidl index 5170f164a3..091f6d7246 100644 --- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcAllocMethod.aidl +++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcAllocMethod.aidl @@ -34,6 +34,6 @@ package android.hardware.bluetooth.audio; @Backing(type="byte") @VintfStability enum SbcAllocMethod { - ALLOC_MD_S = 1, - ALLOC_MD_L = 2, + ALLOC_MD_S = 0, + ALLOC_MD_L = 1, } diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcCapabilities.aidl index ec3aa0f262..c8d7e7e74e 100644 --- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcCapabilities.aidl +++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcCapabilities.aidl @@ -35,10 +35,10 @@ package android.hardware.bluetooth.audio; @VintfStability parcelable SbcCapabilities { int[] sampleRateHz; - android.hardware.bluetooth.audio.SbcChannelMode channelMode; + android.hardware.bluetooth.audio.SbcChannelMode[] channelMode; byte[] blockLength; byte[] numSubbands; - android.hardware.bluetooth.audio.SbcAllocMethod allocMethod; + android.hardware.bluetooth.audio.SbcAllocMethod[] allocMethod; byte[] bitsPerSample; int minBitpool; int maxBitpool; diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcChannelMode.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcChannelMode.aidl index 88fca4aac4..6441a99877 100644 --- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcChannelMode.aidl +++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcChannelMode.aidl @@ -34,9 +34,9 @@ package android.hardware.bluetooth.audio; @Backing(type="byte") @VintfStability enum SbcChannelMode { - UNKNOWN = 1, - JOINT_STEREO = 2, - STEREO = 4, - DUAL = 8, - MONO = 16, + UNKNOWN = 0, + JOINT_STEREO = 1, + STEREO = 2, + DUAL = 3, + MONO = 4, } diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/UnicastCapability.aidl index a7224ca5da..130fef971c 100644 --- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioCapabilities.aidl +++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/UnicastCapability.aidl @@ -33,12 +33,12 @@ package android.hardware.bluetooth.audio; @VintfStability -parcelable LeAudioCapabilities { - android.hardware.bluetooth.audio.LeAudioMode mode; +parcelable UnicastCapability { android.hardware.bluetooth.audio.CodecType codecType; android.hardware.bluetooth.audio.AudioLocation supportedChannel; - int supportedChannelCount; - android.hardware.bluetooth.audio.LeAudioCapabilities.LeAudioCodecCapabilities leAudioCodecCapabilities; + int deviceCount; + int channelCountPerDevice; + android.hardware.bluetooth.audio.UnicastCapability.LeAudioCodecCapabilities leAudioCodecCapabilities; @VintfStability parcelable VendorCapabilities { ParcelableHolder extension; @@ -46,6 +46,6 @@ parcelable LeAudioCapabilities { @VintfStability union LeAudioCodecCapabilities { android.hardware.bluetooth.audio.Lc3Capabilities lc3Capabilities; - android.hardware.bluetooth.audio.LeAudioCapabilities.VendorCapabilities vendorCapabillities; + android.hardware.bluetooth.audio.UnicastCapability.VendorCapabilities vendorCapabillities; } } diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacCapabilities.aidl index 43038836aa..c4153e9ffd 100644 --- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacCapabilities.aidl +++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacCapabilities.aidl @@ -24,11 +24,9 @@ import android.hardware.bluetooth.audio.ChannelMode; */ @VintfStability parcelable AacCapabilities { - /* bitfield */ - AacObjectType objectType; + AacObjectType[] objectType; int[] sampleRateHz; - /* bitfield */ - ChannelMode channelMode; + ChannelMode[] channelMode; boolean variableBitRateSupported; byte[] bitsPerSample; } diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacObjectType.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacObjectType.aidl index 480e422e1c..4e9958c855 100644 --- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacObjectType.aidl +++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacObjectType.aidl @@ -22,17 +22,17 @@ enum AacObjectType { /** * MPEG-2 Low Complexity. Support is Mandatory. */ - MPEG2_LC = 1, + MPEG2_LC, /** * MPEG-4 Low Complexity. Support is Optional. */ - MPEG4_LC = 1 << 1, + MPEG4_LC, /** * MPEG-4 Long Term Prediction. Support is Optional. */ - MPEG4_LTP = 1 << 2, + MPEG4_LTP, /** * MPEG-4 Scalable. Support is Optional. */ - MPEG4_SCALABLE = 1 << 3, + MPEG4_SCALABLE, } diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxCapabilities.aidl index 6a37fc6a41..f5605d31fe 100644 --- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxCapabilities.aidl +++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxCapabilities.aidl @@ -24,7 +24,6 @@ import android.hardware.bluetooth.audio.ChannelMode; @VintfStability parcelable AptxCapabilities { int[] sampleRateHz; - /* bitfield */ - ChannelMode channelMode; + ChannelMode[] channelMode; byte[] bitsPerSample; } diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioCapabilities.aidl index 6ed44722cc..a75c4457e9 100644 --- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioCapabilities.aidl +++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioCapabilities.aidl @@ -17,7 +17,7 @@ package android.hardware.bluetooth.audio; import android.hardware.bluetooth.audio.CodecCapabilities; -import android.hardware.bluetooth.audio.LeAudioCapabilities; +import android.hardware.bluetooth.audio.LeAudioCodecCapabilitiesSetting; import android.hardware.bluetooth.audio.PcmCapabilities; /** @@ -26,6 +26,6 @@ import android.hardware.bluetooth.audio.PcmCapabilities; @VintfStability union AudioCapabilities { PcmCapabilities pcmCapabilities; - CodecCapabilities codecCapabilities; - LeAudioCapabilities leAudioCapabilities; + CodecCapabilities a2dpCapabilities; + LeAudioCodecCapabilitiesSetting leAudioCapabilities; } diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioConfiguration.aidl index ce515b5611..81b41dcf7f 100644 --- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioConfiguration.aidl +++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioConfiguration.aidl @@ -26,6 +26,6 @@ import android.hardware.bluetooth.audio.PcmConfiguration; @VintfStability union AudioConfiguration { PcmConfiguration pcmConfig; - CodecConfiguration codecConfig; + CodecConfiguration a2dpConfig; LeAudioConfiguration leAudioConfig; } diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BroadcastCapability.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BroadcastCapability.aidl new file mode 100644 index 0000000000..cb63f88ea9 --- /dev/null +++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BroadcastCapability.aidl @@ -0,0 +1,43 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.bluetooth.audio; + +import android.hardware.bluetooth.audio.AudioLocation; +import android.hardware.bluetooth.audio.CodecType; +import android.hardware.bluetooth.audio.Lc3Capabilities; +import android.hardware.bluetooth.audio.LeAudioMode; + +/** + * Used to specify the le audio broadcast codec capabilities for hardware offload. + */ +@VintfStability +parcelable BroadcastCapability { + @VintfStability + parcelable VendorCapabilities { + ParcelableHolder extension; + } + @VintfStability + union LeAudioCodecCapabilities { + @nullable Lc3Capabilities[] lc3Capabilities; + @nullable VendorCapabilities[] vendorCapabillities; + } + CodecType codecType; + AudioLocation supportedChannel; + // Supported channel count for each stream + int channelCountPerStream; + LeAudioCodecCapabilities leAudioCodecCapabilities; +} diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BroadcastConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BroadcastConfiguration.aidl index 07d05f1bd7..cfc9d3aa01 100644 --- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BroadcastConfiguration.aidl +++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BroadcastConfiguration.aidl @@ -33,7 +33,7 @@ parcelable BroadcastConfiguration { * least significant bit to the most significant bit. */ int audioChannelAllocation; - LeAudioCodecConfiguration leAudioCondecConfig; + LeAudioCodecConfiguration leAudioCodecConfig; } BroadcastStreamMap[] streamMap; } diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/ChannelMode.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/ChannelMode.aidl index 2df879d837..66138724ae 100644 --- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/ChannelMode.aidl +++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/ChannelMode.aidl @@ -19,7 +19,7 @@ package android.hardware.bluetooth.audio; @VintfStability @Backing(type="byte") enum ChannelMode { - UNKNOWN = 1, - MONO = 1 << 1, - STEREO = 1 << 2, + UNKNOWN, + MONO, + STEREO, } diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecCapabilities.aidl index 0eee8cb55b..5bf0252bf8 100644 --- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecCapabilities.aidl +++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecCapabilities.aidl @@ -19,6 +19,7 @@ package android.hardware.bluetooth.audio; import android.hardware.bluetooth.audio.AacCapabilities; import android.hardware.bluetooth.audio.AptxCapabilities; import android.hardware.bluetooth.audio.CodecType; +import android.hardware.bluetooth.audio.Lc3Capabilities; import android.hardware.bluetooth.audio.LdacCapabilities; import android.hardware.bluetooth.audio.SbcCapabilities; @@ -34,6 +35,7 @@ parcelable CodecCapabilities { AacCapabilities aacCapabilities; LdacCapabilities ldacCapabilities; AptxCapabilities aptxCapabilities; + Lc3Capabilities lc3Capabilities; } CodecType codecType; Capabilities capabilities; diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecConfiguration.aidl index fac90f065d..9e43f2244a 100644 --- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecConfiguration.aidl +++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecConfiguration.aidl @@ -19,6 +19,7 @@ package android.hardware.bluetooth.audio; import android.hardware.bluetooth.audio.AacConfiguration; import android.hardware.bluetooth.audio.AptxConfiguration; import android.hardware.bluetooth.audio.CodecType; +import android.hardware.bluetooth.audio.Lc3Configuration; import android.hardware.bluetooth.audio.LdacConfiguration; import android.hardware.bluetooth.audio.SbcConfiguration; @@ -34,6 +35,7 @@ parcelable CodecConfiguration { AacConfiguration aacConfig; LdacConfiguration ldacConfig; AptxConfiguration aptxConfig; + Lc3Configuration lc3Config; } CodecType codecType; /** diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl index a2c5ae9a76..6f88f3041a 100644 --- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl +++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl @@ -72,4 +72,14 @@ interface IBluetoothAudioProvider { * @param status true for SUCCESS or false for FAILURE */ void streamSuspended(in BluetoothAudioStatus status); + + /** + * Called when the audio configuration of the stream has been changed. + * + * @param audioConfig The audio configuration negotiated with the remote + * device. The PCM parameters are set if software based encoding, + * otherwise the correct codec configuration is used for hardware + * encoding. + */ + void updateAudioConfiguration(in AudioConfiguration audioConfig); } diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Lc3Capabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Lc3Capabilities.aidl index 1aedefd2d5..fc2f382d18 100644 --- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Lc3Capabilities.aidl +++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Lc3Capabilities.aidl @@ -16,6 +16,8 @@ package android.hardware.bluetooth.audio; +import android.hardware.bluetooth.audio.ChannelMode; + /** * Used for Hardware Encoding/Decoding LC3 codec capabilities. */ @@ -41,4 +43,8 @@ parcelable Lc3Capabilities { * Number of blocks of codec frames per single SDU (Service Data Unit) */ byte[] blocksPerSdu; + /* + * Channel mode used in A2DP special audio, ignored in standard LE Audio mode + */ + ChannelMode[] channelMode; } diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Lc3Configuration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Lc3Configuration.aidl index 77c04c1b6e..e8a93b27d8 100644 --- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Lc3Configuration.aidl +++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Lc3Configuration.aidl @@ -16,6 +16,8 @@ package android.hardware.bluetooth.audio; +import android.hardware.bluetooth.audio.ChannelMode; + /** * Used for Hardware Encoding/Decoding LC3 codec configuration. */ @@ -41,4 +43,8 @@ parcelable Lc3Configuration { * Number of blocks of codec frames per single SDU (Service Data Unit) */ byte blocksPerSdu; + /* + * Channel mode used in A2DP special audio, ignored in standard LE Audio mode + */ + ChannelMode channelMode; } diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacCapabilities.aidl index 44cca7e071..1dbec0896b 100644 --- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacCapabilities.aidl +++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacCapabilities.aidl @@ -26,9 +26,7 @@ import android.hardware.bluetooth.audio.LdacQualityIndex; @VintfStability parcelable LdacCapabilities { int[] sampleRateHz; - /* bitfiled */ - LdacChannelMode channelMode; - /* bitfiled */ - LdacQualityIndex qualityIndex; + LdacChannelMode[] channelMode; + LdacQualityIndex[] qualityIndex; byte[] bitsPerSample; } diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacChannelMode.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacChannelMode.aidl index 3acca32fc2..3cc910f49c 100644 --- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacChannelMode.aidl +++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacChannelMode.aidl @@ -22,8 +22,8 @@ package android.hardware.bluetooth.audio; @VintfStability @Backing(type="byte") enum LdacChannelMode { - UNKNOWN = 1, - STEREO = 1 << 1, - DUAL = 1 << 2, - MONO = 1 << 3, + UNKNOWN, + STEREO, + DUAL, + MONO, } diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacQualityIndex.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacQualityIndex.aidl index cb125839ef..9993b8b6d2 100644 --- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacQualityIndex.aidl +++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacQualityIndex.aidl @@ -22,17 +22,17 @@ enum LdacQualityIndex { /** * 990kbps */ - HIGH = 1, + HIGH, /** * 660kbps */ - MID = 1 << 1, + MID, /** * 330kbps */ - LOW = 1 << 2, + LOW, /** * Adaptive Bit Rate mode */ - ABR = 1 << 3, + ABR, } diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.aidl new file mode 100644 index 0000000000..58dac06080 --- /dev/null +++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.aidl @@ -0,0 +1,30 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.bluetooth.audio; + +import android.hardware.bluetooth.audio.BroadcastCapability; +import android.hardware.bluetooth.audio.UnicastCapability; + +/** + * Used to specify the le audio capabilities for unicast and broadcast hardware offload. + */ +@VintfStability +parcelable LeAudioCodecCapabilitiesSetting { + UnicastCapability unicastEncodeCapability; + UnicastCapability unicastDecodeCapability; + BroadcastCapability broadcastCapability; +} diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PcmCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PcmCapabilities.aidl index f5d699edf1..776b777f50 100644 --- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PcmCapabilities.aidl +++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PcmCapabilities.aidl @@ -24,7 +24,7 @@ import android.hardware.bluetooth.audio.ChannelMode; @VintfStability parcelable PcmCapabilities { int[] sampleRateHz; - ChannelMode channelMode; + ChannelMode[] channelMode; byte[] bitsPerSample; /** * Data interval for data transfer diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcAllocMethod.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcAllocMethod.aidl index 7047e346dc..1159f30374 100644 --- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcAllocMethod.aidl +++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcAllocMethod.aidl @@ -22,9 +22,9 @@ enum SbcAllocMethod { /** * SNR */ - ALLOC_MD_S = 1, + ALLOC_MD_S, /** * Loudness */ - ALLOC_MD_L = 1 << 1, + ALLOC_MD_L, } diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcCapabilities.aidl index cf62ed4e5e..743a1f73e2 100644 --- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcCapabilities.aidl +++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcCapabilities.aidl @@ -25,12 +25,10 @@ import android.hardware.bluetooth.audio.SbcChannelMode; @VintfStability parcelable SbcCapabilities { int[] sampleRateHz; - /* bitfield */ - SbcChannelMode channelMode; + SbcChannelMode[] channelMode; byte[] blockLength; byte[] numSubbands; - /* bitfield */ - SbcAllocMethod allocMethod; + SbcAllocMethod[] allocMethod; byte[] bitsPerSample; /* * range from 2 to 250. diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcChannelMode.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcChannelMode.aidl index 7eb38cd9f7..68e32670e8 100644 --- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcChannelMode.aidl +++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcChannelMode.aidl @@ -19,9 +19,9 @@ package android.hardware.bluetooth.audio; @VintfStability @Backing(type="byte") enum SbcChannelMode { - UNKNOWN = 1, - JOINT_STEREO = 1 << 1, - STEREO = 1 << 2, - DUAL = 1 << 3, - MONO = 1 << 4, + UNKNOWN, + JOINT_STEREO, + STEREO, + DUAL, + MONO, } diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/UnicastCapability.aidl index 732427f060..cd8a4c1971 100644 --- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioCapabilities.aidl +++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/UnicastCapability.aidl @@ -22,10 +22,10 @@ import android.hardware.bluetooth.audio.Lc3Capabilities; import android.hardware.bluetooth.audio.LeAudioMode; /** - * Used to specify the capabilities of the LC3 codecs supported by Hardware Encoding. + * Used to specify the le audio unicast codec capabilities for hardware offload. */ @VintfStability -parcelable LeAudioCapabilities { +parcelable UnicastCapability { @VintfStability parcelable VendorCapabilities { ParcelableHolder extension; @@ -35,13 +35,11 @@ parcelable LeAudioCapabilities { Lc3Capabilities lc3Capabilities; VendorCapabilities vendorCapabillities; } - LeAudioMode mode; CodecType codecType; - /* - * This is bitfield, if bit N is set, HW Offloader supports N+1 channels at the same time. - * Example: 0x27 = 0b00100111: One, two, three or six channels supported. - */ AudioLocation supportedChannel; - int supportedChannelCount; + // The number of connected device + int deviceCount; + // Supported channel count for each device + int channelCountPerDevice; LeAudioCodecCapabilities leAudioCodecCapabilities; } diff --git a/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp new file mode 100644 index 0000000000..fc8a911145 --- /dev/null +++ b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "BTAudioProviderA2dpHW" + +#include "A2dpOffloadAudioProvider.h" + +#include <BluetoothAudioCodecs.h> +#include <BluetoothAudioSessionReport.h> +#include <android-base/logging.h> + +namespace aidl { +namespace android { +namespace hardware { +namespace bluetooth { +namespace audio { + +A2dpOffloadAudioProvider::A2dpOffloadAudioProvider() { + session_type_ = SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH; +} + +bool A2dpOffloadAudioProvider::isValid(const SessionType& session_type) { + return (session_type == session_type_); +} + +ndk::ScopedAStatus A2dpOffloadAudioProvider::startSession( + const std::shared_ptr<IBluetoothAudioPort>& host_if, + const AudioConfiguration& audio_config, DataMQDesc* _aidl_return) { + if (audio_config.getTag() != AudioConfiguration::a2dpConfig) { + LOG(WARNING) << __func__ << " - Invalid Audio Configuration=" + << audio_config.toString(); + *_aidl_return = DataMQDesc(); + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + if (!BluetoothAudioCodecs::IsOffloadCodecConfigurationValid( + session_type_, audio_config.get<AudioConfiguration::a2dpConfig>())) { + LOG(WARNING) << __func__ << " - Invalid Audio Configuration=" + << audio_config.toString(); + *_aidl_return = DataMQDesc(); + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + return BluetoothAudioProvider::startSession(host_if, audio_config, + _aidl_return); +} + +ndk::ScopedAStatus A2dpOffloadAudioProvider::onSessionReady( + DataMQDesc* _aidl_return) { + *_aidl_return = DataMQDesc(); + BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_, + nullptr, *audio_config_); + return ndk::ScopedAStatus::ok(); +} + +} // namespace audio +} // namespace bluetooth +} // namespace hardware +} // namespace android +} // namespace aidl
\ No newline at end of file diff --git a/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h new file mode 100644 index 0000000000..5934f5b32d --- /dev/null +++ b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "BluetoothAudioProvider.h" + +namespace aidl { +namespace android { +namespace hardware { +namespace bluetooth { +namespace audio { + +class A2dpOffloadAudioProvider : public BluetoothAudioProvider { + public: + A2dpOffloadAudioProvider(); + + bool isValid(const SessionType& session_type) override; + + ndk::ScopedAStatus startSession( + const std::shared_ptr<IBluetoothAudioPort>& host_if, + const AudioConfiguration& audio_config, DataMQDesc* _aidl_return); + + private: + ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override; +}; + +} // namespace audio +} // namespace bluetooth +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp new file mode 100644 index 0000000000..7e4907409e --- /dev/null +++ b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "BTAudioProviderA2dpSW" + +#include "A2dpSoftwareAudioProvider.h" + +#include <BluetoothAudioCodecs.h> +#include <BluetoothAudioSessionReport.h> +#include <android-base/logging.h> + +namespace aidl { +namespace android { +namespace hardware { +namespace bluetooth { +namespace audio { + +// Here the buffer size is based on SBC +static constexpr uint32_t kPcmFrameSize = 4; // 16 bits per sample / stereo +// SBC is 128, and here we choose the LCM of 16, 24, and 32 +static constexpr uint32_t kPcmFrameCount = 96; +static constexpr uint32_t kRtpFrameSize = kPcmFrameSize * kPcmFrameCount; +// The max counts by 1 tick (20ms) for SBC is about 7. Since using 96 for the +// PCM counts, here we just choose a greater number +static constexpr uint32_t kRtpFrameCount = 10; +static constexpr uint32_t kBufferSize = kRtpFrameSize * kRtpFrameCount; +static constexpr uint32_t kBufferCount = 2; // double buffer +static constexpr uint32_t kDataMqSize = kBufferSize * kBufferCount; + +A2dpSoftwareAudioProvider::A2dpSoftwareAudioProvider() + : BluetoothAudioProvider(), data_mq_(nullptr) { + LOG(INFO) << __func__ << " - size of audio buffer " << kDataMqSize + << " byte(s)"; + std::unique_ptr<DataMQ> data_mq( + new DataMQ(kDataMqSize, /* EventFlag */ true)); + if (data_mq && data_mq->isValid()) { + data_mq_ = std::move(data_mq); + session_type_ = SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH; + } else { + ALOGE_IF(!data_mq, "failed to allocate data MQ"); + ALOGE_IF(data_mq && !data_mq->isValid(), "data MQ is invalid"); + } +} + +bool A2dpSoftwareAudioProvider::isValid(const SessionType& sessionType) { + return (sessionType == session_type_ && data_mq_ && data_mq_->isValid()); +} + +ndk::ScopedAStatus A2dpSoftwareAudioProvider::startSession( + const std::shared_ptr<IBluetoothAudioPort>& host_if, + const AudioConfiguration& audio_config, DataMQDesc* _aidl_return) { + if (audio_config.getTag() != AudioConfiguration::pcmConfig) { + LOG(WARNING) << __func__ << " - Invalid Audio Configuration=" + << audio_config.toString(); + *_aidl_return = DataMQDesc(); + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + const PcmConfiguration& pcm_config = + audio_config.get<AudioConfiguration::pcmConfig>(); + if (!BluetoothAudioCodecs::IsSoftwarePcmConfigurationValid(pcm_config)) { + LOG(WARNING) << __func__ << " - Unsupported PCM Configuration=" + << pcm_config.toString(); + *_aidl_return = DataMQDesc(); + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + + return BluetoothAudioProvider::startSession(host_if, audio_config, + _aidl_return); +} + +ndk::ScopedAStatus A2dpSoftwareAudioProvider::onSessionReady( + DataMQDesc* _aidl_return) { + if (data_mq_ == nullptr || !data_mq_->isValid()) { + *_aidl_return = DataMQDesc(); + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + *_aidl_return = data_mq_->dupeDesc(); + BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_, + _aidl_return, *audio_config_); + return ndk::ScopedAStatus::ok(); +} + +} // namespace audio +} // namespace bluetooth +} // namespace hardware +} // namespace android +} // namespace aidl
\ No newline at end of file diff --git a/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.h b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.h new file mode 100644 index 0000000000..3bc0a135dd --- /dev/null +++ b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "BluetoothAudioProvider.h" + +namespace aidl { +namespace android { +namespace hardware { +namespace bluetooth { +namespace audio { + +class A2dpSoftwareAudioProvider : public BluetoothAudioProvider { + public: + A2dpSoftwareAudioProvider(); + + bool isValid(const SessionType& sessionType) override; + + ndk::ScopedAStatus startSession( + const std::shared_ptr<IBluetoothAudioPort>& host_if, + const AudioConfiguration& audio_config, DataMQDesc* _aidl_return); + + private: + // audio data queue for software encoding + std::unique_ptr<DataMQ> data_mq_; + + ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override; +}; + +} // namespace audio +} // namespace bluetooth +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/bluetooth/audio/aidl/default/Android.bp b/bluetooth/audio/aidl/default/Android.bp new file mode 100644 index 0000000000..846702fa0e --- /dev/null +++ b/bluetooth/audio/aidl/default/Android.bp @@ -0,0 +1,34 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_library_shared { + name: "android.hardware.bluetooth.audio-V1-impl", + vendor: true, + vintf_fragments: ["bluetooth_audio.xml"], + srcs: [ + "BluetoothAudioProvider.cpp", + "BluetoothAudioProviderFactory.cpp", + "A2dpOffloadAudioProvider.cpp", + "A2dpSoftwareAudioProvider.cpp", + "HearingAidAudioProvider.cpp", + "LeAudioOffloadAudioProvider.cpp", + "LeAudioSoftwareAudioProvider.cpp", + ], + export_include_dirs: ["."], + header_libs: ["libhardware_headers"], + shared_libs: [ + "libbase", + "libbinder_ndk", + "libcutils", + "libfmq", + "liblog", + "android.hardware.bluetooth.audio-V1-ndk", + "libbluetooth_audio_session_aidl", + ], +} diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp b/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp new file mode 100644 index 0000000000..c2ffa2efa2 --- /dev/null +++ b/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "BTAudioProviderStub" + +#include "BluetoothAudioProvider.h" + +#include <BluetoothAudioSessionReport.h> +#include <android-base/logging.h> + +namespace aidl { +namespace android { +namespace hardware { +namespace bluetooth { +namespace audio { + +BluetoothAudioProvider::BluetoothAudioProvider() { + death_recipient_ = ::ndk::ScopedAIBinder_DeathRecipient( + AIBinder_DeathRecipient_new(binderDiedCallbackAidl)); +} + +ndk::ScopedAStatus BluetoothAudioProvider::startSession( + const std::shared_ptr<IBluetoothAudioPort>& host_if, + const AudioConfiguration& audio_config, DataMQDesc* _aidl_return) { + if (host_if == nullptr) { + *_aidl_return = DataMQDesc(); + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + audio_config_ = std::make_unique<AudioConfiguration>(audio_config); + stack_iface_ = host_if; + + AIBinder_linkToDeath(stack_iface_->asBinder().get(), death_recipient_.get(), + this); + + onSessionReady(_aidl_return); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus BluetoothAudioProvider::endSession() { + LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_); + + if (stack_iface_ != nullptr) { + BluetoothAudioSessionReport::OnSessionEnded(session_type_); + + AIBinder_unlinkToDeath(stack_iface_->asBinder().get(), + death_recipient_.get(), this); + } else { + LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) + << " has NO session"; + } + + stack_iface_ = nullptr; + audio_config_ = nullptr; + + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus BluetoothAudioProvider::streamStarted( + BluetoothAudioStatus status) { + LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) + << ", status=" << toString(status); + + if (stack_iface_ != nullptr) { + BluetoothAudioSessionReport::ReportControlStatus(session_type_, true, + status); + } else { + LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_) + << ", status=" << toString(status) << " has NO session"; + } + + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus BluetoothAudioProvider::streamSuspended( + BluetoothAudioStatus status) { + LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) + << ", status=" << toString(status); + + if (stack_iface_ != nullptr) { + BluetoothAudioSessionReport::ReportControlStatus(session_type_, false, + status); + } else { + LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_) + << ", status=" << toString(status) << " has NO session"; + } + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus BluetoothAudioProvider::updateAudioConfiguration( + const AudioConfiguration& audio_config) { + LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_); + + if (stack_iface_ == nullptr || audio_config_ == nullptr) { + LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) + << " has NO session"; + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + + if (audio_config.getTag() != audio_config_->getTag()) { + LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) + << " audio config type is not match"; + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + + audio_config_ = std::make_unique<AudioConfiguration>(audio_config); + BluetoothAudioSessionReport::ReportAudioConfigChanged(session_type_, + *audio_config_); + return ndk::ScopedAStatus::ok(); +} + +void BluetoothAudioProvider::binderDiedCallbackAidl(void* ptr) { + LOG(ERROR) << __func__ << " - BluetoothAudio Service died"; + auto provider = static_cast<BluetoothAudioProvider*>(ptr); + if (provider == nullptr) { + LOG(ERROR) << __func__ << ": Null AudioProvider HAL died"; + return; + } + provider->endSession(); +} + +} // namespace audio +} // namespace bluetooth +} // namespace hardware +} // namespace android +} // namespace aidl
\ No newline at end of file diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProvider.h b/bluetooth/audio/aidl/default/BluetoothAudioProvider.h new file mode 100644 index 0000000000..f7acbdf7e3 --- /dev/null +++ b/bluetooth/audio/aidl/default/BluetoothAudioProvider.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include <aidl/android/hardware/bluetooth/audio/BnBluetoothAudioProvider.h> +#include <aidl/android/hardware/bluetooth/audio/SessionType.h> +#include <fmq/AidlMessageQueue.h> + +using ::aidl::android::hardware::common::fmq::MQDescriptor; +using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite; +using ::android::AidlMessageQueue; + +using MqDataType = int8_t; +using MqDataMode = SynchronizedReadWrite; +using DataMQ = AidlMessageQueue<MqDataType, MqDataMode>; +using DataMQDesc = MQDescriptor<MqDataType, MqDataMode>; + +namespace aidl { +namespace android { +namespace hardware { +namespace bluetooth { +namespace audio { + +class BluetoothAudioProvider : public BnBluetoothAudioProvider { + public: + BluetoothAudioProvider(); + + ndk::ScopedAStatus startSession( + const std::shared_ptr<IBluetoothAudioPort>& host_if, + const AudioConfiguration& audio_config, DataMQDesc* _aidl_return); + ndk::ScopedAStatus endSession(); + ndk::ScopedAStatus streamStarted(BluetoothAudioStatus status); + ndk::ScopedAStatus streamSuspended(BluetoothAudioStatus status); + ndk::ScopedAStatus updateAudioConfiguration( + const AudioConfiguration& audio_config); + + virtual bool isValid(const SessionType& sessionType) = 0; + + protected: + virtual ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) = 0; + static void binderDiedCallbackAidl(void* cookie_ptr); + + ::ndk::ScopedAIBinder_DeathRecipient death_recipient_; + + std::shared_ptr<IBluetoothAudioPort> stack_iface_; + std::unique_ptr<AudioConfiguration> audio_config_ = nullptr; + SessionType session_type_; +}; + +} // namespace audio +} // namespace bluetooth +} // namespace hardware +} // namespace android +} // namespace aidl
\ No newline at end of file diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp new file mode 100644 index 0000000000..8e6cee7b2f --- /dev/null +++ b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "BTAudioProvidersFactory" + +#include "BluetoothAudioProviderFactory.h" + +#include <BluetoothAudioCodecs.h> +#include <android-base/logging.h> + +#include "A2dpOffloadAudioProvider.h" +#include "A2dpSoftwareAudioProvider.h" +#include "BluetoothAudioProvider.h" +#include "HearingAidAudioProvider.h" +#include "LeAudioOffloadAudioProvider.h" +#include "LeAudioSoftwareAudioProvider.h" + +namespace aidl { +namespace android { +namespace hardware { +namespace bluetooth { +namespace audio { + +BluetoothAudioProviderFactory::BluetoothAudioProviderFactory() {} + +ndk::ScopedAStatus BluetoothAudioProviderFactory::openProvider( + const SessionType session_type, + std::shared_ptr<IBluetoothAudioProvider>* _aidl_return) { + LOG(INFO) << __func__ << " - SessionType=" << toString(session_type); + std::shared_ptr<BluetoothAudioProvider> provider = nullptr; + + switch (session_type) { + case SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH: + provider = ndk::SharedRefBase::make<A2dpSoftwareAudioProvider>(); + break; + case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH: + provider = ndk::SharedRefBase::make<A2dpOffloadAudioProvider>(); + break; + case SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH: + provider = ndk::SharedRefBase::make<HearingAidAudioProvider>(); + break; + case SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH: + provider = ndk::SharedRefBase::make<LeAudioSoftwareOutputAudioProvider>(); + break; + case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH: + provider = ndk::SharedRefBase::make<LeAudioOffloadOutputAudioProvider>(); + break; + case SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH: + provider = ndk::SharedRefBase::make<LeAudioSoftwareInputAudioProvider>(); + break; + case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH: + provider = ndk::SharedRefBase::make<LeAudioOffloadInputAudioProvider>(); + break; + default: + provider = nullptr; + break; + } + + if (provider == nullptr || !provider->isValid(session_type)) { + provider = nullptr; + LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type); + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + *_aidl_return = provider; + + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus BluetoothAudioProviderFactory::getProviderCapabilities( + const SessionType session_type, + std::vector<AudioCapabilities>* _aidl_return) { + if (session_type == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) { + auto codec_capabilities = + BluetoothAudioCodecs::GetA2dpOffloadCodecCapabilities(session_type); + _aidl_return->resize(codec_capabilities.size()); + for (int i = 0; i < codec_capabilities.size(); i++) { + _aidl_return->at(i).set<AudioCapabilities::a2dpCapabilities>( + codec_capabilities[i]); + } + } else if (session_type == + SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH || + session_type == + SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) { + std::vector<LeAudioCodecCapabilitiesSetting> db_codec_capabilities = + BluetoothAudioCodecs::GetLeAudioOffloadCodecCapabilities(session_type); + if (db_codec_capabilities.size()) { + _aidl_return->resize(db_codec_capabilities.size()); + for (int i = 0; i < db_codec_capabilities.size(); ++i) { + _aidl_return->at(i).set<AudioCapabilities::leAudioCapabilities>( + db_codec_capabilities[i]); + } + } + } else if (session_type != SessionType::UNKNOWN) { + auto pcm_capabilities = BluetoothAudioCodecs::GetSoftwarePcmCapabilities(); + _aidl_return->resize(pcm_capabilities.size()); + for (int i = 0; i < pcm_capabilities.size(); i++) { + _aidl_return->at(i).set<AudioCapabilities::pcmCapabilities>( + pcm_capabilities[i]); + } + } + + LOG(INFO) << __func__ << " - SessionType=" << toString(session_type) + << " supports " << _aidl_return->size() << " codecs"; + return ndk::ScopedAStatus::ok(); +} + +} // namespace audio +} // namespace bluetooth +} // namespace hardware +} // namespace android +} // namespace aidl
\ No newline at end of file diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.h b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.h new file mode 100644 index 0000000000..96d888c166 --- /dev/null +++ b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <aidl/android/hardware/bluetooth/audio/BnBluetoothAudioProviderFactory.h> + +#include "A2dpOffloadAudioProvider.h" +#include "A2dpSoftwareAudioProvider.h" +#include "BluetoothAudioProvider.h" +#include "HearingAidAudioProvider.h" +#include "LeAudioOffloadAudioProvider.h" +#include "LeAudioSoftwareAudioProvider.h" + +namespace aidl { +namespace android { +namespace hardware { +namespace bluetooth { +namespace audio { + +class BluetoothAudioProviderFactory : public BnBluetoothAudioProviderFactory { + public: + BluetoothAudioProviderFactory(); + + ndk::ScopedAStatus openProvider( + const SessionType session_type, + std::shared_ptr<IBluetoothAudioProvider>* _aidl_return) override; + + ndk::ScopedAStatus getProviderCapabilities( + const SessionType session_type, + std::vector<AudioCapabilities>* _aidl_return) override; +}; + +} // namespace audio +} // namespace bluetooth +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp b/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp new file mode 100644 index 0000000000..a993059b65 --- /dev/null +++ b/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "BTAudioProviderHearingAid" + +#include "HearingAidAudioProvider.h" + +#include <BluetoothAudioCodecs.h> +#include <BluetoothAudioSessionReport.h> +#include <android-base/logging.h> + +namespace aidl { +namespace android { +namespace hardware { +namespace bluetooth { +namespace audio { + +static constexpr uint32_t kPcmFrameSize = 4; // 16 bits per sample / stereo +static constexpr uint32_t kPcmFrameCount = 128; +static constexpr uint32_t kRtpFrameSize = kPcmFrameSize * kPcmFrameCount; +static constexpr uint32_t kRtpFrameCount = 7; // max counts by 1 tick (20ms) +static constexpr uint32_t kBufferSize = kRtpFrameSize * kRtpFrameCount; +static constexpr uint32_t kBufferCount = 1; // single buffer +static constexpr uint32_t kDataMqSize = kBufferSize * kBufferCount; + +HearingAidAudioProvider::HearingAidAudioProvider() + : BluetoothAudioProvider(), data_mq_(nullptr) { + LOG(INFO) << __func__ << " - size of audio buffer " << kDataMqSize + << " byte(s)"; + std::unique_ptr<DataMQ> data_mq( + new DataMQ(kDataMqSize, /* EventFlag */ true)); + if (data_mq && data_mq->isValid()) { + data_mq_ = std::move(data_mq); + session_type_ = SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH; + } else { + ALOGE_IF(!data_mq, "failed to allocate data MQ"); + ALOGE_IF(data_mq && !data_mq->isValid(), "data MQ is invalid"); + } +} +bool HearingAidAudioProvider::isValid(const SessionType& sessionType) { + return (sessionType == session_type_ && data_mq_ && data_mq_->isValid()); +} + +ndk::ScopedAStatus HearingAidAudioProvider::startSession( + const std::shared_ptr<IBluetoothAudioPort>& host_if, + const AudioConfiguration& audio_config, DataMQDesc* _aidl_return) { + if (audio_config.getTag() != AudioConfiguration::pcmConfig) { + LOG(WARNING) << __func__ << " - Invalid Audio Configuration=" + << audio_config.toString(); + *_aidl_return = DataMQDesc(); + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + const auto& pcm_config = audio_config.get<AudioConfiguration::pcmConfig>(); + if (!BluetoothAudioCodecs::IsSoftwarePcmConfigurationValid(pcm_config)) { + LOG(WARNING) << __func__ << " - Unsupported PCM Configuration=" + << pcm_config.toString(); + *_aidl_return = DataMQDesc(); + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + + return BluetoothAudioProvider::startSession(host_if, audio_config, + _aidl_return); +} + +ndk::ScopedAStatus HearingAidAudioProvider::onSessionReady( + DataMQDesc* _aidl_return) { + if (data_mq_ == nullptr || !data_mq_->isValid()) { + *_aidl_return = DataMQDesc(); + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + auto desc = data_mq_->dupeDesc(); + BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_, + &desc, *audio_config_); + *_aidl_return = data_mq_->dupeDesc(); + return ndk::ScopedAStatus::ok(); +} + +} // namespace audio +} // namespace bluetooth +} // namespace hardware +} // namespace android +} // namespace aidl
\ No newline at end of file diff --git a/bluetooth/audio/aidl/default/HearingAidAudioProvider.h b/bluetooth/audio/aidl/default/HearingAidAudioProvider.h new file mode 100644 index 0000000000..a7e19e982d --- /dev/null +++ b/bluetooth/audio/aidl/default/HearingAidAudioProvider.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "BluetoothAudioProvider.h" + +namespace aidl { +namespace android { +namespace hardware { +namespace bluetooth { +namespace audio { + +class HearingAidAudioProvider : public BluetoothAudioProvider { + public: + HearingAidAudioProvider(); + + bool isValid(const SessionType& sessionType) override; + + ndk::ScopedAStatus startSession( + const std::shared_ptr<IBluetoothAudioPort>& host_if, + const AudioConfiguration& audio_config, DataMQDesc* _aidl_return); + + private: + // audio data queue for software encoding + std::unique_ptr<DataMQ> data_mq_; + + ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override; +}; + +} // namespace audio +} // namespace bluetooth +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp new file mode 100644 index 0000000000..4078783c99 --- /dev/null +++ b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "BTAudioProviderLeAudioSW" + +#include "LeAudioOffloadAudioProvider.h" + +#include <BluetoothAudioCodecs.h> +#include <BluetoothAudioSessionReport.h> +#include <android-base/logging.h> + +namespace aidl { +namespace android { +namespace hardware { +namespace bluetooth { +namespace audio { + +LeAudioOffloadOutputAudioProvider::LeAudioOffloadOutputAudioProvider() + : LeAudioOffloadAudioProvider() { + session_type_ = SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH; +} + +LeAudioOffloadInputAudioProvider::LeAudioOffloadInputAudioProvider() + : LeAudioOffloadAudioProvider() { + session_type_ = SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH; +} + +LeAudioOffloadAudioProvider::LeAudioOffloadAudioProvider() + : BluetoothAudioProvider() {} + +bool LeAudioOffloadAudioProvider::isValid(const SessionType& sessionType) { + return (sessionType == session_type_); +} + +ndk::ScopedAStatus LeAudioOffloadAudioProvider::startSession( + const std::shared_ptr<IBluetoothAudioPort>& host_if, + const AudioConfiguration& audio_config, DataMQDesc* _aidl_return) { + if (audio_config.getTag() != AudioConfiguration::leAudioConfig) { + LOG(WARNING) << __func__ << " - Invalid Audio Configuration=" + << audio_config.toString(); + *_aidl_return = DataMQDesc(); + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + const auto& le_audio_config = + audio_config.get<AudioConfiguration::leAudioConfig>(); + if (!BluetoothAudioCodecs::IsOffloadLeAudioConfigurationValid( + session_type_, le_audio_config)) { + LOG(WARNING) << __func__ << " - Unsupported LC3 Offloaded Configuration=" + << le_audio_config.toString(); + *_aidl_return = DataMQDesc(); + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + + return BluetoothAudioProvider::startSession(host_if, audio_config, + _aidl_return); +} + +ndk::ScopedAStatus LeAudioOffloadAudioProvider::onSessionReady( + DataMQDesc* _aidl_return) { + BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_, + nullptr, *audio_config_); + *_aidl_return = DataMQDesc(); + return ndk::ScopedAStatus::ok(); +} + +} // namespace audio +} // namespace bluetooth +} // namespace hardware +} // namespace android +} // namespace aidl
\ No newline at end of file diff --git a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h new file mode 100644 index 0000000000..a27a2e71ce --- /dev/null +++ b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "BluetoothAudioProvider.h" + +namespace aidl { +namespace android { +namespace hardware { +namespace bluetooth { +namespace audio { + +class LeAudioOffloadAudioProvider : public BluetoothAudioProvider { + public: + LeAudioOffloadAudioProvider(); + + bool isValid(const SessionType& sessionType) override; + + ndk::ScopedAStatus startSession( + const std::shared_ptr<IBluetoothAudioPort>& host_if, + const AudioConfiguration& audio_config, DataMQDesc* _aidl_return); + + private: + ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override; +}; + +class LeAudioOffloadOutputAudioProvider : public LeAudioOffloadAudioProvider { + public: + LeAudioOffloadOutputAudioProvider(); +}; + +class LeAudioOffloadInputAudioProvider : public LeAudioOffloadAudioProvider { + public: + LeAudioOffloadInputAudioProvider(); +}; + +} // namespace audio +} // namespace bluetooth +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp new file mode 100644 index 0000000000..f9962fd9d9 --- /dev/null +++ b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "BTAudioProviderLeAudioHW" + +#include "LeAudioSoftwareAudioProvider.h" + +#include <BluetoothAudioCodecs.h> +#include <BluetoothAudioSessionReport.h> +#include <android-base/logging.h> + +#include <cstdint> + +namespace aidl { +namespace android { +namespace hardware { +namespace bluetooth { +namespace audio { + +static constexpr uint32_t kBufferOutCount = 2; // two frame buffer +static constexpr uint32_t kBufferInCount = 2; // two frame buffer + +inline uint32_t channel_mode_to_channel_count(ChannelMode channel_mode) { + switch (channel_mode) { + case ChannelMode::MONO: + return 1; + case ChannelMode::STEREO: + return 2; + default: + return 0; + } + return 0; +} + +LeAudioSoftwareOutputAudioProvider::LeAudioSoftwareOutputAudioProvider() + : LeAudioSoftwareAudioProvider() { + session_type_ = SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH; +} + +LeAudioSoftwareInputAudioProvider::LeAudioSoftwareInputAudioProvider() + : LeAudioSoftwareAudioProvider() { + session_type_ = SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH; +} + +LeAudioSoftwareAudioProvider::LeAudioSoftwareAudioProvider() + : BluetoothAudioProvider(), data_mq_(nullptr) {} + +bool LeAudioSoftwareAudioProvider::isValid(const SessionType& sessionType) { + return (sessionType == session_type_); +} + +ndk::ScopedAStatus LeAudioSoftwareAudioProvider::startSession( + const std::shared_ptr<IBluetoothAudioPort>& host_if, + const AudioConfiguration& audio_config, DataMQDesc* _aidl_return) { + if (audio_config.getTag() != AudioConfiguration::pcmConfig) { + LOG(WARNING) << __func__ << " - Invalid Audio Configuration=" + << audio_config.toString(); + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + const auto& pcm_config = audio_config.get<AudioConfiguration::pcmConfig>(); + if (!BluetoothAudioCodecs::IsSoftwarePcmConfigurationValid(pcm_config)) { + LOG(WARNING) << __func__ << " - Unsupported PCM Configuration=" + << pcm_config.toString(); + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + + uint32_t buffer_modifier = 0; + if (session_type_ == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH) + buffer_modifier = kBufferOutCount; + else if (session_type_ == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH) + buffer_modifier = kBufferInCount; + + uint32_t data_mq_size = + (ceil(pcm_config.sampleRateHz) / 1000) * + channel_mode_to_channel_count(pcm_config.channelMode) * + (pcm_config.bitsPerSample / 8) * (pcm_config.dataIntervalUs / 1000) * + buffer_modifier; + + LOG(INFO) << __func__ << " - size of audio buffer " << data_mq_size + << " byte(s)"; + + std::unique_ptr<DataMQ> temp_data_mq( + new DataMQ(data_mq_size, /* EventFlag */ true)); + if (temp_data_mq == nullptr || !temp_data_mq->isValid()) { + ALOGE_IF(!temp_data_mq, "failed to allocate data MQ"); + ALOGE_IF(temp_data_mq && !temp_data_mq->isValid(), "data MQ is invalid"); + *_aidl_return = DataMQDesc(); + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + data_mq_ = std::move(temp_data_mq); + + return BluetoothAudioProvider::startSession(host_if, audio_config, + _aidl_return); +} + +ndk::ScopedAStatus LeAudioSoftwareAudioProvider::onSessionReady( + DataMQDesc* _aidl_return) { + if (data_mq_ == nullptr || !data_mq_->isValid()) { + *_aidl_return = DataMQDesc(); + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + *_aidl_return = data_mq_->dupeDesc(); + BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_, + _aidl_return, *audio_config_); + return ndk::ScopedAStatus::ok(); +} + +} // namespace audio +} // namespace bluetooth +} // namespace hardware +} // namespace android +} // namespace aidl
\ No newline at end of file diff --git a/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.h b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.h new file mode 100644 index 0000000000..fa581820c6 --- /dev/null +++ b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "BluetoothAudioProvider.h" + +namespace aidl { +namespace android { +namespace hardware { +namespace bluetooth { +namespace audio { + +class LeAudioSoftwareAudioProvider : public BluetoothAudioProvider { + public: + LeAudioSoftwareAudioProvider(); + + bool isValid(const SessionType& sessionType) override; + + ndk::ScopedAStatus startSession( + const std::shared_ptr<IBluetoothAudioPort>& host_if, + const AudioConfiguration& audio_config, DataMQDesc* _aidl_return); + + private: + // audio data queue for software encoding + std::unique_ptr<DataMQ> data_mq_; + + ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override; +}; + +class LeAudioSoftwareOutputAudioProvider : public LeAudioSoftwareAudioProvider { + public: + LeAudioSoftwareOutputAudioProvider(); +}; + +class LeAudioSoftwareInputAudioProvider : public LeAudioSoftwareAudioProvider { + public: + LeAudioSoftwareInputAudioProvider(); +}; + +} // namespace audio +} // namespace bluetooth +} // namespace hardware +} // namespace android +} // namespace aidl
\ No newline at end of file diff --git a/bluetooth/audio/aidl/default/bluetooth_audio.xml b/bluetooth/audio/aidl/default/bluetooth_audio.xml new file mode 100644 index 0000000000..1859a1a366 --- /dev/null +++ b/bluetooth/audio/aidl/default/bluetooth_audio.xml @@ -0,0 +1,6 @@ +<manifest version="1.0" type="device"> + <hal format="aidl"> + <name>android.hardware.bluetooth.audio</name> + <fqname>IBluetoothAudioProviderFactory/default</fqname> + </hal> +</manifest>
\ No newline at end of file diff --git a/bluetooth/audio/utils/Android.bp b/bluetooth/audio/utils/Android.bp index 4f712bffab..974357e278 100644 --- a/bluetooth/audio/utils/Android.bp +++ b/bluetooth/audio/utils/Android.bp @@ -32,5 +32,30 @@ cc_library_shared { "libhidlbase", "liblog", "libutils", + "libbluetooth_audio_session_aidl", + ], +} + +cc_library_shared { + name: "libbluetooth_audio_session_aidl", + vendor: true, + srcs: [ + "aidl_session/BluetoothAudioCodecs.cpp", + "aidl_session/BluetoothAudioSession.cpp", + "aidl_session/HidlToAidlMiddleware.cpp", + ], + export_include_dirs: ["aidl_session/"], + header_libs: ["libhardware_headers"], + shared_libs: [ + "android.hardware.bluetooth.audio@2.0", + "android.hardware.bluetooth.audio@2.1", + "android.hardware.bluetooth.audio@2.2", + "libbase", + "libcutils", + "libbinder_ndk", + "libfmq", + "liblog", + "android.hardware.bluetooth.audio-V1-ndk", + "libhidlbase", ], } diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp new file mode 100644 index 0000000000..92cd0f5b14 --- /dev/null +++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp @@ -0,0 +1,489 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "BTAudioCodecsAidl" + +#include "BluetoothAudioCodecs.h" + +#include <aidl/android/hardware/bluetooth/audio/AacCapabilities.h> +#include <aidl/android/hardware/bluetooth/audio/AacObjectType.h> +#include <aidl/android/hardware/bluetooth/audio/AptxCapabilities.h> +#include <aidl/android/hardware/bluetooth/audio/ChannelMode.h> +#include <aidl/android/hardware/bluetooth/audio/LdacCapabilities.h> +#include <aidl/android/hardware/bluetooth/audio/LdacChannelMode.h> +#include <aidl/android/hardware/bluetooth/audio/LdacQualityIndex.h> +#include <aidl/android/hardware/bluetooth/audio/LeAudioConfiguration.h> +#include <aidl/android/hardware/bluetooth/audio/SbcCapabilities.h> +#include <aidl/android/hardware/bluetooth/audio/SbcChannelMode.h> +#include <android-base/logging.h> + +namespace aidl { +namespace android { +namespace hardware { +namespace bluetooth { +namespace audio { + +static const PcmCapabilities kDefaultSoftwarePcmCapabilities = { + .sampleRateHz = {16000, 24000, 44100, 48000, 88200, 96000}, + .channelMode = {ChannelMode::MONO, ChannelMode::STEREO}, + .bitsPerSample = {16, 24, 32}, + .dataIntervalUs = {}, +}; + +static const SbcCapabilities kDefaultOffloadSbcCapability = { + .sampleRateHz = {44100}, + .channelMode = {SbcChannelMode::MONO, SbcChannelMode::JOINT_STEREO}, + .blockLength = {4, 8, 12, 16}, + .numSubbands = {8}, + .allocMethod = {SbcAllocMethod::ALLOC_MD_L}, + .bitsPerSample = {16}, + .minBitpool = 2, + .maxBitpool = 53}; + +static const AacCapabilities kDefaultOffloadAacCapability = { + .objectType = {AacObjectType::MPEG2_LC}, + .sampleRateHz = {44100}, + .channelMode = {ChannelMode::STEREO}, + .variableBitRateSupported = true, + .bitsPerSample = {16}}; + +static const LdacCapabilities kDefaultOffloadLdacCapability = { + .sampleRateHz = {44100, 48000, 88200, 96000}, + .channelMode = {LdacChannelMode::DUAL, LdacChannelMode::STEREO}, + .qualityIndex = {LdacQualityIndex::HIGH}, + .bitsPerSample = {16, 24, 32}}; + +static const AptxCapabilities kDefaultOffloadAptxCapability = { + .sampleRateHz = {44100, 48000}, + .channelMode = {ChannelMode::STEREO}, + .bitsPerSample = {16}, +}; + +static const AptxCapabilities kDefaultOffloadAptxHdCapability = { + .sampleRateHz = {44100, 48000}, + .channelMode = {ChannelMode::STEREO}, + .bitsPerSample = {24}, +}; + +static const Lc3Capabilities kDefaultOffloadLc3Capability = { + .samplingFrequencyHz = {44100, 48000}, + .frameDurationUs = {7500, 10000}, + .channelMode = {ChannelMode::MONO, ChannelMode::STEREO}, +}; + +const std::vector<CodecCapabilities> kDefaultOffloadA2dpCodecCapabilities = { + {.codecType = CodecType::SBC, .capabilities = {}}, + {.codecType = CodecType::AAC, .capabilities = {}}, + {.codecType = CodecType::LDAC, .capabilities = {}}, + {.codecType = CodecType::APTX, .capabilities = {}}, + {.codecType = CodecType::APTX_HD, .capabilities = {}}, + {.codecType = CodecType::LC3, .capabilities = {}}}; + +std::vector<LeAudioCodecCapabilitiesSetting> kDefaultOffloadLeAudioCapabilities; + +static const UnicastCapability kInvalidUnicastCapability = { + .codecType = CodecType::UNKNOWN}; + +static const BroadcastCapability kInvalidBroadcastCapability = { + .codecType = CodecType::UNKNOWN}; + +// Default Supported Codecs +// LC3 16_1: sample rate: 16 kHz, frame duration: 7.5 ms, octets per frame: 30 +static const Lc3Capabilities kLc3Capability_16_1 = { + .samplingFrequencyHz = {16000}, + .frameDurationUs = {7500}, + .octetsPerFrame = {30}}; + +// Default Supported Codecs +// LC3 16_2: sample rate: 16 kHz, frame duration: 10 ms, octets per frame: 40 +static const Lc3Capabilities kLc3Capability_16_2 = { + .samplingFrequencyHz = {16000}, + .frameDurationUs = {10000}, + .octetsPerFrame = {40}}; + +// Default Supported Codecs +// LC3 48_4: sample rate: 48 kHz, frame duration: 10 ms, octets per frame: 120 +static const Lc3Capabilities kLc3Capability_48_4 = { + .samplingFrequencyHz = {48000}, + .frameDurationUs = {10000}, + .octetsPerFrame = {120}}; + +static const std::vector<Lc3Capabilities> supportedLc3CapabilityList = { + kLc3Capability_48_4, kLc3Capability_16_2, kLc3Capability_16_1}; + +static AudioLocation stereoAudio = static_cast<AudioLocation>( + static_cast<uint8_t>(AudioLocation::FRONT_LEFT) | + static_cast<uint8_t>(AudioLocation::FRONT_RIGHT)); +static AudioLocation monoAudio = AudioLocation::UNKNOWN; + +// Stores the supported setting of audio location, connected device, and the +// channel count for each device +std::vector<std::tuple<AudioLocation, uint8_t, uint8_t>> + supportedDeviceSetting = {std::make_tuple(stereoAudio, 2, 1), + std::make_tuple(monoAudio, 1, 2), + std::make_tuple(monoAudio, 1, 1)}; + +template <class T> +bool BluetoothAudioCodecs::ContainedInVector( + const std::vector<T>& vector, const typename identity<T>::type& target) { + return std::find(vector.begin(), vector.end(), target) != vector.end(); +} + +bool BluetoothAudioCodecs::IsOffloadSbcConfigurationValid( + const CodecConfiguration::CodecSpecific& codec_specific) { + if (codec_specific.getTag() != CodecConfiguration::CodecSpecific::sbcConfig) { + LOG(WARNING) << __func__ + << ": Invalid CodecSpecific=" << codec_specific.toString(); + return false; + } + const SbcConfiguration sbc_data = + codec_specific.get<CodecConfiguration::CodecSpecific::sbcConfig>(); + + if (ContainedInVector(kDefaultOffloadSbcCapability.sampleRateHz, + sbc_data.sampleRateHz) && + ContainedInVector(kDefaultOffloadSbcCapability.blockLength, + sbc_data.blockLength) && + ContainedInVector(kDefaultOffloadSbcCapability.numSubbands, + sbc_data.numSubbands) && + ContainedInVector(kDefaultOffloadSbcCapability.bitsPerSample, + sbc_data.bitsPerSample) && + ContainedInVector(kDefaultOffloadSbcCapability.channelMode, + sbc_data.channelMode) && + ContainedInVector(kDefaultOffloadSbcCapability.allocMethod, + sbc_data.allocMethod) && + sbc_data.minBitpool <= sbc_data.maxBitpool && + kDefaultOffloadSbcCapability.minBitpool <= sbc_data.minBitpool && + kDefaultOffloadSbcCapability.maxBitpool >= sbc_data.maxBitpool) { + return true; + } + LOG(WARNING) << __func__ + << ": Unsupported CodecSpecific=" << codec_specific.toString(); + return false; +} + +bool BluetoothAudioCodecs::IsOffloadAacConfigurationValid( + const CodecConfiguration::CodecSpecific& codec_specific) { + if (codec_specific.getTag() != CodecConfiguration::CodecSpecific::aacConfig) { + LOG(WARNING) << __func__ + << ": Invalid CodecSpecific=" << codec_specific.toString(); + return false; + } + const AacConfiguration aac_data = + codec_specific.get<CodecConfiguration::CodecSpecific::aacConfig>(); + + if (ContainedInVector(kDefaultOffloadAacCapability.sampleRateHz, + aac_data.sampleRateHz) && + ContainedInVector(kDefaultOffloadAacCapability.bitsPerSample, + aac_data.bitsPerSample) && + ContainedInVector(kDefaultOffloadAacCapability.channelMode, + aac_data.channelMode) && + ContainedInVector(kDefaultOffloadAacCapability.objectType, + aac_data.objectType) && + (!aac_data.variableBitRateEnabled || + kDefaultOffloadAacCapability.variableBitRateSupported)) { + return true; + } + LOG(WARNING) << __func__ + << ": Unsupported CodecSpecific=" << codec_specific.toString(); + return false; +} + +bool BluetoothAudioCodecs::IsOffloadLdacConfigurationValid( + const CodecConfiguration::CodecSpecific& codec_specific) { + if (codec_specific.getTag() != + CodecConfiguration::CodecSpecific::ldacConfig) { + LOG(WARNING) << __func__ + << ": Invalid CodecSpecific=" << codec_specific.toString(); + return false; + } + const LdacConfiguration ldac_data = + codec_specific.get<CodecConfiguration::CodecSpecific::ldacConfig>(); + + if (ContainedInVector(kDefaultOffloadLdacCapability.sampleRateHz, + ldac_data.sampleRateHz) && + ContainedInVector(kDefaultOffloadLdacCapability.bitsPerSample, + ldac_data.bitsPerSample) && + ContainedInVector(kDefaultOffloadLdacCapability.channelMode, + ldac_data.channelMode) && + ContainedInVector(kDefaultOffloadLdacCapability.qualityIndex, + ldac_data.qualityIndex)) { + return true; + } + LOG(WARNING) << __func__ + << ": Unsupported CodecSpecific=" << codec_specific.toString(); + return false; +} + +bool BluetoothAudioCodecs::IsOffloadAptxConfigurationValid( + const CodecConfiguration::CodecSpecific& codec_specific) { + if (codec_specific.getTag() != + CodecConfiguration::CodecSpecific::aptxConfig) { + LOG(WARNING) << __func__ + << ": Invalid CodecSpecific=" << codec_specific.toString(); + return false; + } + const AptxConfiguration aptx_data = + codec_specific.get<CodecConfiguration::CodecSpecific::aptxConfig>(); + + if (ContainedInVector(kDefaultOffloadAptxCapability.sampleRateHz, + aptx_data.sampleRateHz) && + ContainedInVector(kDefaultOffloadAptxCapability.bitsPerSample, + aptx_data.bitsPerSample) && + ContainedInVector(kDefaultOffloadAptxCapability.channelMode, + aptx_data.channelMode)) { + return true; + } + LOG(WARNING) << __func__ + << ": Unsupported CodecSpecific=" << codec_specific.toString(); + return false; +} + +bool BluetoothAudioCodecs::IsOffloadAptxHdConfigurationValid( + const CodecConfiguration::CodecSpecific& codec_specific) { + if (codec_specific.getTag() != + CodecConfiguration::CodecSpecific::aptxConfig) { + LOG(WARNING) << __func__ + << ": Invalid CodecSpecific=" << codec_specific.toString(); + return false; + } + const AptxConfiguration aptx_data = + codec_specific.get<CodecConfiguration::CodecSpecific::aptxConfig>(); + + if (ContainedInVector(kDefaultOffloadAptxHdCapability.sampleRateHz, + aptx_data.sampleRateHz) && + ContainedInVector(kDefaultOffloadAptxHdCapability.bitsPerSample, + aptx_data.bitsPerSample) && + ContainedInVector(kDefaultOffloadAptxHdCapability.channelMode, + aptx_data.channelMode)) { + return true; + } + LOG(WARNING) << __func__ + << ": Unsupported CodecSpecific=" << codec_specific.toString(); + return false; +} + +bool BluetoothAudioCodecs::IsOffloadLc3ConfigurationValid( + const CodecConfiguration::CodecSpecific& codec_specific) { + if (codec_specific.getTag() != CodecConfiguration::CodecSpecific::lc3Config) { + LOG(WARNING) << __func__ + << ": Invalid CodecSpecific=" << codec_specific.toString(); + return false; + } + const Lc3Configuration lc3_data = + codec_specific.get<CodecConfiguration::CodecSpecific::lc3Config>(); + + if (ContainedInVector(kDefaultOffloadLc3Capability.samplingFrequencyHz, + lc3_data.samplingFrequencyHz) && + ContainedInVector(kDefaultOffloadLc3Capability.frameDurationUs, + lc3_data.frameDurationUs) && + ContainedInVector(kDefaultOffloadLc3Capability.channelMode, + lc3_data.channelMode)) { + return true; + } + LOG(WARNING) << __func__ + << ": Unsupported CodecSpecific=" << codec_specific.toString(); + return false; +} + +bool BluetoothAudioCodecs::IsOffloadLeAudioConfigurationValid( + const SessionType& session_type, const LeAudioConfiguration&) { + if (session_type != + SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH && + session_type != + SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) { + return false; + } + return true; +} + +std::vector<PcmCapabilities> +BluetoothAudioCodecs::GetSoftwarePcmCapabilities() { + return {kDefaultSoftwarePcmCapabilities}; +} + +std::vector<CodecCapabilities> +BluetoothAudioCodecs::GetA2dpOffloadCodecCapabilities( + const SessionType& session_type) { + if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) { + return {}; + } + std::vector<CodecCapabilities> offload_a2dp_codec_capabilities = + kDefaultOffloadA2dpCodecCapabilities; + for (auto& codec_capability : offload_a2dp_codec_capabilities) { + switch (codec_capability.codecType) { + case CodecType::SBC: + codec_capability.capabilities + .set<CodecCapabilities::Capabilities::sbcCapabilities>( + kDefaultOffloadSbcCapability); + break; + case CodecType::AAC: + codec_capability.capabilities + .set<CodecCapabilities::Capabilities::aacCapabilities>( + kDefaultOffloadAacCapability); + break; + case CodecType::LDAC: + codec_capability.capabilities + .set<CodecCapabilities::Capabilities::ldacCapabilities>( + kDefaultOffloadLdacCapability); + break; + case CodecType::APTX: + codec_capability.capabilities + .set<CodecCapabilities::Capabilities::aptxCapabilities>( + kDefaultOffloadAptxCapability); + break; + case CodecType::APTX_HD: + codec_capability.capabilities + .set<CodecCapabilities::Capabilities::aptxCapabilities>( + kDefaultOffloadAptxHdCapability); + break; + case CodecType::LC3: + codec_capability.capabilities + .set<CodecCapabilities::Capabilities::lc3Capabilities>( + kDefaultOffloadLc3Capability); + break; + case CodecType::UNKNOWN: + codec_capability = {}; + break; + } + } + return offload_a2dp_codec_capabilities; +} + +bool BluetoothAudioCodecs::IsSoftwarePcmConfigurationValid( + const PcmConfiguration& pcm_config) { + if (ContainedInVector(kDefaultSoftwarePcmCapabilities.sampleRateHz, + pcm_config.sampleRateHz) && + ContainedInVector(kDefaultSoftwarePcmCapabilities.bitsPerSample, + pcm_config.bitsPerSample) && + ContainedInVector(kDefaultSoftwarePcmCapabilities.channelMode, + pcm_config.channelMode) + // data interval is not checked for now + // && pcm_config.dataIntervalUs != 0 + ) { + return true; + } + LOG(WARNING) << __func__ + << ": Unsupported CodecSpecific=" << pcm_config.toString(); + return false; +} + +bool BluetoothAudioCodecs::IsOffloadCodecConfigurationValid( + const SessionType& session_type, const CodecConfiguration& codec_config) { + if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) { + LOG(ERROR) << __func__ + << ": Invalid SessionType=" << toString(session_type); + return false; + } + const CodecConfiguration::CodecSpecific& codec_specific = codec_config.config; + switch (codec_config.codecType) { + case CodecType::SBC: + if (IsOffloadSbcConfigurationValid(codec_specific)) { + return true; + } + break; + case CodecType::AAC: + if (IsOffloadAacConfigurationValid(codec_specific)) { + return true; + } + break; + case CodecType::LDAC: + if (IsOffloadLdacConfigurationValid(codec_specific)) { + return true; + } + break; + case CodecType::APTX: + if (IsOffloadAptxConfigurationValid(codec_specific)) { + return true; + } + break; + case CodecType::APTX_HD: + if (IsOffloadAptxHdConfigurationValid(codec_specific)) { + return true; + } + break; + case CodecType::LC3: + if (IsOffloadLc3ConfigurationValid(codec_specific)) { + return true; + } + break; + case CodecType::UNKNOWN: + break; + } + return false; +} + +UnicastCapability composeUnicastLc3Capability( + AudioLocation audioLocation, uint8_t deviceCnt, uint8_t channelCount, + const Lc3Capabilities& capability) { + return { + .codecType = CodecType::LC3, + .supportedChannel = audioLocation, + .deviceCount = deviceCnt, + .channelCountPerDevice = channelCount, + .leAudioCodecCapabilities = + UnicastCapability::LeAudioCodecCapabilities(capability), + }; +} + +std::vector<LeAudioCodecCapabilitiesSetting> +BluetoothAudioCodecs::GetLeAudioOffloadCodecCapabilities( + const SessionType& session_type) { + if (session_type != + SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH && + session_type != + SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) { + return std::vector<LeAudioCodecCapabilitiesSetting>(0); + } + + if (kDefaultOffloadLeAudioCapabilities.empty()) { + for (auto [audioLocation, deviceCnt, channelCount] : + supportedDeviceSetting) { + for (auto capability : supportedLc3CapabilityList) { + UnicastCapability lc3Capability = composeUnicastLc3Capability( + audioLocation, deviceCnt, channelCount, capability); + UnicastCapability lc3MonoDecodeCapability = + composeUnicastLc3Capability(monoAudio, 1, 1, capability); + + // Adds the capability for encode only + kDefaultOffloadLeAudioCapabilities.push_back( + {.unicastEncodeCapability = lc3Capability, + .unicastDecodeCapability = kInvalidUnicastCapability, + .broadcastCapability = kInvalidBroadcastCapability}); + + // Adds the capability for decode only + kDefaultOffloadLeAudioCapabilities.push_back( + {.unicastEncodeCapability = kInvalidUnicastCapability, + .unicastDecodeCapability = lc3Capability, + .broadcastCapability = kInvalidBroadcastCapability}); + + // Adds the capability for the case that encode and decode exist at the + // same time + kDefaultOffloadLeAudioCapabilities.push_back( + {.unicastEncodeCapability = lc3Capability, + .unicastDecodeCapability = lc3MonoDecodeCapability, + .broadcastCapability = kInvalidBroadcastCapability}); + } + } + } + + return kDefaultOffloadLeAudioCapabilities; +} + +} // namespace audio +} // namespace bluetooth +} // namespace hardware +} // namespace android +} // namespace aidl
\ No newline at end of file diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h new file mode 100644 index 0000000000..c542ce5be7 --- /dev/null +++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <aidl/android/hardware/bluetooth/audio/CodecCapabilities.h> +#include <aidl/android/hardware/bluetooth/audio/CodecConfiguration.h> +#include <aidl/android/hardware/bluetooth/audio/Lc3Configuration.h> +#include <aidl/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.h> +#include <aidl/android/hardware/bluetooth/audio/LeAudioConfiguration.h> +#include <aidl/android/hardware/bluetooth/audio/PcmCapabilities.h> +#include <aidl/android/hardware/bluetooth/audio/PcmConfiguration.h> +#include <aidl/android/hardware/bluetooth/audio/SessionType.h> + +#include <vector> + +namespace aidl { +namespace android { +namespace hardware { +namespace bluetooth { +namespace audio { + +class BluetoothAudioCodecs { + public: + static std::vector<PcmCapabilities> GetSoftwarePcmCapabilities(); + static std::vector<CodecCapabilities> GetA2dpOffloadCodecCapabilities( + const SessionType& session_type); + + static bool IsSoftwarePcmConfigurationValid( + const PcmConfiguration& pcm_config); + static bool IsOffloadCodecConfigurationValid( + const SessionType& session_type, const CodecConfiguration& codec_config); + + static bool IsOffloadLeAudioConfigurationValid( + const SessionType& session_type, const Lc3Configuration& codec_config); + + static bool IsOffloadLeAudioConfigurationValid( + const SessionType& session_type, + const LeAudioConfiguration& codec_config); + + static std::vector<LeAudioCodecCapabilitiesSetting> + GetLeAudioOffloadCodecCapabilities(const SessionType& session_type); + + private: + template <typename T> + struct identity { + typedef T type; + }; + template <class T> + static bool ContainedInVector(const std::vector<T>& vector, + const typename identity<T>::type& target); + template <class T> + static bool ContainedInBitmask(const T& bitmask, const T& target); + static bool IsSingleBit(uint32_t bitmasks, uint32_t bitfield); + static bool IsOffloadSbcConfigurationValid( + const CodecConfiguration::CodecSpecific& codec_specific); + static bool IsOffloadAacConfigurationValid( + const CodecConfiguration::CodecSpecific& codec_specific); + static bool IsOffloadLdacConfigurationValid( + const CodecConfiguration::CodecSpecific& codec_specific); + static bool IsOffloadAptxConfigurationValid( + const CodecConfiguration::CodecSpecific& codec_specific); + static bool IsOffloadAptxHdConfigurationValid( + const CodecConfiguration::CodecSpecific& codec_specific); + static bool IsOffloadLc3ConfigurationValid( + const CodecConfiguration::CodecSpecific& codec_specific); + static bool IsOffloadLeAudioConfigurationValid( + const SessionType& session_type, const LeAudioCodecConfiguration&); +}; + +} // namespace audio +} // namespace bluetooth +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp new file mode 100644 index 0000000000..95e473e5b9 --- /dev/null +++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp @@ -0,0 +1,581 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <sys/types.h> +#define LOG_TAG "BTAudioSessionAidl" + +#include <android-base/logging.h> +#include <android-base/stringprintf.h> +#include <android/binder_manager.h> + +#include "BluetoothAudioSession.h" + +namespace aidl { +namespace android { +namespace hardware { +namespace bluetooth { +namespace audio { + +static constexpr int kFmqSendTimeoutMs = 1000; // 1000 ms timeout for sending +static constexpr int kFmqReceiveTimeoutMs = + 1000; // 1000 ms timeout for receiving +static constexpr int kWritePollMs = 1; // polled non-blocking interval +static constexpr int kReadPollMs = 1; // polled non-blocking interval + +const CodecConfiguration BluetoothAudioSession::kInvalidCodecConfiguration = {}; +const LeAudioConfiguration kInvalidLeAudioConfiguration = {}; +AudioConfiguration BluetoothAudioSession::invalidSoftwareAudioConfiguration = + {}; +AudioConfiguration BluetoothAudioSession::invalidOffloadAudioConfiguration = {}; +AudioConfiguration BluetoothAudioSession::invalidLeOffloadAudioConfig = {}; + +BluetoothAudioSession::BluetoothAudioSession(const SessionType& session_type) + : session_type_(session_type), stack_iface_(nullptr), data_mq_(nullptr) { + invalidSoftwareAudioConfiguration.set<AudioConfiguration::pcmConfig>( + kInvalidPcmConfiguration); + invalidOffloadAudioConfiguration.set<AudioConfiguration::a2dpConfig>( + kInvalidCodecConfiguration); + invalidLeOffloadAudioConfig.set<AudioConfiguration::leAudioConfig>( + kInvalidLeAudioConfiguration); +} + +/*** + * + * Callback methods + * + ***/ + +void BluetoothAudioSession::OnSessionStarted( + const std::shared_ptr<IBluetoothAudioPort> stack_iface, + const DataMQDesc* mq_desc, const AudioConfiguration& audio_config) { + std::lock_guard<std::recursive_mutex> guard(mutex_); + if (stack_iface == nullptr) { + LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_) + << ", IBluetoothAudioPort Invalid"; + } else if (!UpdateAudioConfig(audio_config)) { + LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_) + << ", AudioConfiguration=" << audio_config.toString() + << " Invalid"; + } else if (!UpdateDataPath(mq_desc)) { + LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_) + << " MqDescriptor Invalid"; + if (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) { + audio_config_ = std::make_unique<AudioConfiguration>( + invalidOffloadAudioConfiguration); + } else { + audio_config_ = std::make_unique<AudioConfiguration>( + invalidSoftwareAudioConfiguration); + } + } else { + stack_iface_ = stack_iface; + LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) + << ", AudioConfiguration=" << audio_config.toString(); + ReportSessionStatus(); + } +} + +void BluetoothAudioSession::OnSessionEnded() { + std::lock_guard<std::recursive_mutex> guard(mutex_); + bool toggled = IsSessionReady(); + LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_); + if (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) { + audio_config_ = + std::make_unique<AudioConfiguration>(invalidOffloadAudioConfiguration); + } else { + audio_config_ = + std::make_unique<AudioConfiguration>(invalidSoftwareAudioConfiguration); + } + stack_iface_ = nullptr; + UpdateDataPath(nullptr); + if (toggled) { + ReportSessionStatus(); + } +} + +/*** + * + * Util methods + * + ***/ + +const AudioConfiguration& BluetoothAudioSession::GetAudioConfig() { + std::lock_guard<std::recursive_mutex> guard(mutex_); + if (!IsSessionReady()) { + if (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) { + return invalidOffloadAudioConfiguration; + } else { + return invalidSoftwareAudioConfiguration; + } + switch (session_type_) { + case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH: + return invalidOffloadAudioConfiguration; + case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH: + case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH: + return invalidLeOffloadAudioConfig; + default: + return invalidSoftwareAudioConfiguration; + } + } + return *audio_config_; +} + +void BluetoothAudioSession::ReportAudioConfigChanged( + const AudioConfiguration& audio_config) { + if (session_type_ != + SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH && + session_type_ != + SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) { + return; + } + std::lock_guard<std::recursive_mutex> guard(mutex_); + audio_config_ = std::make_unique<AudioConfiguration>(audio_config); + if (observers_.empty()) { + LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_) + << " has NO port state observer"; + return; + } + for (auto& observer : observers_) { + uint16_t cookie = observer.first; + std::shared_ptr<struct PortStatusCallbacks> cb = observer.second; + LOG(INFO) << __func__ << " for SessionType=" << toString(session_type_) + << ", bluetooth_audio=0x" + << ::android::base::StringPrintf("%04x", cookie); + if (cb->audio_configuration_changed_cb_ != nullptr) { + cb->audio_configuration_changed_cb_(cookie); + } + } +} + +bool BluetoothAudioSession::IsSessionReady() { + std::lock_guard<std::recursive_mutex> guard(mutex_); + + bool is_mq_valid = + (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH || + session_type_ == + SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH || + session_type_ == + SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH || + (data_mq_ != nullptr && data_mq_->isValid())); + return stack_iface_ != nullptr && is_mq_valid; +} + +/*** + * + * Status callback methods + * + ***/ + +uint16_t BluetoothAudioSession::RegisterStatusCback( + const PortStatusCallbacks& callbacks) { + std::lock_guard<std::recursive_mutex> guard(mutex_); + uint16_t cookie = ObserversCookieGetInitValue(session_type_); + uint16_t cookie_upper_bound = ObserversCookieGetUpperBound(session_type_); + + while (cookie < cookie_upper_bound) { + if (observers_.find(cookie) == observers_.end()) { + break; + } + ++cookie; + } + if (cookie >= cookie_upper_bound) { + LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_) + << " has " << observers_.size() + << " observers already (No Resource)"; + return kObserversCookieUndefined; + } + std::shared_ptr<PortStatusCallbacks> cb = + std::make_shared<PortStatusCallbacks>(); + *cb = callbacks; + observers_[cookie] = cb; + return cookie; +} + +void BluetoothAudioSession::UnregisterStatusCback(uint16_t cookie) { + std::lock_guard<std::recursive_mutex> guard(mutex_); + if (observers_.erase(cookie) != 1) { + LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_) + << " no such provider=0x" + << ::android::base::StringPrintf("%04x", cookie); + } +} + +/*** + * + * Stream methods + * + ***/ + +bool BluetoothAudioSession::StartStream() { + std::lock_guard<std::recursive_mutex> guard(mutex_); + if (!IsSessionReady()) { + LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_) + << " has NO session"; + return false; + } + auto hal_retval = stack_iface_->startStream(); + if (!hal_retval.isOk()) { + LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType=" + << toString(session_type_) << " failed"; + return false; + } + return true; +} + +bool BluetoothAudioSession::SuspendStream() { + std::lock_guard<std::recursive_mutex> guard(mutex_); + if (!IsSessionReady()) { + LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_) + << " has NO session"; + return false; + } + auto hal_retval = stack_iface_->suspendStream(); + if (!hal_retval.isOk()) { + LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType=" + << toString(session_type_) << " failed"; + return false; + } + return true; +} + +void BluetoothAudioSession::StopStream() { + std::lock_guard<std::recursive_mutex> guard(mutex_); + if (!IsSessionReady()) { + return; + } + auto hal_retval = stack_iface_->stopStream(); + if (!hal_retval.isOk()) { + LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType=" + << toString(session_type_) << " failed"; + } +} + +/*** + * + * Private methods + * + ***/ + +bool BluetoothAudioSession::UpdateDataPath(const DataMQDesc* mq_desc) { + if (mq_desc == nullptr) { + // usecase of reset by nullptr + data_mq_ = nullptr; + return true; + } + std::unique_ptr<DataMQ> temp_mq; + temp_mq.reset(new DataMQ(*mq_desc)); + if (!temp_mq || !temp_mq->isValid()) { + data_mq_ = nullptr; + return false; + } + data_mq_ = std::move(temp_mq); + return true; +} + +bool BluetoothAudioSession::UpdateAudioConfig( + const AudioConfiguration& audio_config) { + bool is_software_session = + (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH || + session_type_ == SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH || + session_type_ == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH || + session_type_ == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH); + bool is_offload_a2dp_session = + (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH); + bool is_offload_le_audio_session = + (session_type_ == + SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH || + session_type_ == + SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH); + auto audio_config_tag = audio_config.getTag(); + bool is_software_audio_config = + (is_software_session && + audio_config_tag == AudioConfiguration::pcmConfig); + bool is_a2dp_offload_audio_config = + (is_offload_a2dp_session && + audio_config_tag == AudioConfiguration::a2dpConfig); + bool is_le_audio_offload_audio_config = + (is_offload_le_audio_session && + audio_config_tag == AudioConfiguration::leAudioConfig); + if (!is_software_audio_config && !is_a2dp_offload_audio_config && + !is_le_audio_offload_audio_config) { + return false; + } + audio_config_ = std::make_unique<AudioConfiguration>(audio_config); + return true; +} + +void BluetoothAudioSession::ReportSessionStatus() { + // This is locked already by OnSessionStarted / OnSessionEnded + if (observers_.empty()) { + LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) + << " has NO port state observer"; + return; + } + for (auto& observer : observers_) { + uint16_t cookie = observer.first; + std::shared_ptr<PortStatusCallbacks> callback = observer.second; + LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) + << " notify to bluetooth_audio=0x" + << ::android::base::StringPrintf("%04x", cookie); + callback->session_changed_cb_(cookie); + } +} + +/*** + * + * PCM methods + * + ***/ + +size_t BluetoothAudioSession::OutWritePcmData(const void* buffer, + size_t bytes) { + if (buffer == nullptr || bytes <= 0) { + return 0; + } + size_t total_written = 0; + int timeout_ms = kFmqSendTimeoutMs; + do { + std::unique_lock<std::recursive_mutex> lock(mutex_); + if (!IsSessionReady()) { + break; + } + size_t num_bytes_to_write = data_mq_->availableToWrite(); + if (num_bytes_to_write) { + if (num_bytes_to_write > (bytes - total_written)) { + num_bytes_to_write = bytes - total_written; + } + + if (!data_mq_->write( + static_cast<const MQDataType*>(buffer) + total_written, + num_bytes_to_write)) { + LOG(ERROR) << "FMQ datapath writing " << total_written << "/" << bytes + << " failed"; + return total_written; + } + total_written += num_bytes_to_write; + } else if (timeout_ms >= kWritePollMs) { + lock.unlock(); + usleep(kWritePollMs * 1000); + timeout_ms -= kWritePollMs; + } else { + LOG(DEBUG) << "Data " << total_written << "/" << bytes << " overflow " + << (kFmqSendTimeoutMs - timeout_ms) << " ms"; + return total_written; + } + } while (total_written < bytes); + return total_written; +} + +size_t BluetoothAudioSession::InReadPcmData(void* buffer, size_t bytes) { + if (buffer == nullptr || bytes <= 0) { + return 0; + } + size_t total_read = 0; + int timeout_ms = kFmqReceiveTimeoutMs; + do { + std::unique_lock<std::recursive_mutex> lock(mutex_); + if (!IsSessionReady()) { + break; + } + size_t num_bytes_to_read = data_mq_->availableToRead(); + if (num_bytes_to_read) { + if (num_bytes_to_read > (bytes - total_read)) { + num_bytes_to_read = bytes - total_read; + } + if (!data_mq_->read(static_cast<MQDataType*>(buffer) + total_read, + num_bytes_to_read)) { + LOG(ERROR) << "FMQ datapath reading " << total_read << "/" << bytes + << " failed"; + return total_read; + } + total_read += num_bytes_to_read; + } else if (timeout_ms >= kReadPollMs) { + lock.unlock(); + usleep(kReadPollMs * 1000); + timeout_ms -= kReadPollMs; + continue; + } else { + LOG(DEBUG) << "Data " << total_read << "/" << bytes << " overflow " + << (kFmqReceiveTimeoutMs - timeout_ms) << " ms"; + return total_read; + } + } while (total_read < bytes); + return total_read; +} + +/*** + * + * Other methods + * + ***/ + +void BluetoothAudioSession::ReportControlStatus(bool start_resp, + BluetoothAudioStatus status) { + std::lock_guard<std::recursive_mutex> guard(mutex_); + if (observers_.empty()) { + LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_) + << " has NO port state observer"; + return; + } + for (auto& observer : observers_) { + uint16_t cookie = observer.first; + std::shared_ptr<PortStatusCallbacks> callback = observer.second; + LOG(INFO) << __func__ << " - status=" << toString(status) + << " for SessionType=" << toString(session_type_) + << ", bluetooth_audio=0x" + << ::android::base::StringPrintf("%04x", cookie) + << (start_resp ? " started" : " suspended"); + callback->control_result_cb_(cookie, start_resp, status); + } +} + +bool BluetoothAudioSession::GetPresentationPosition( + PresentationPosition& presentation_position) { + std::lock_guard<std::recursive_mutex> guard(mutex_); + if (!IsSessionReady()) { + LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_) + << " has NO session"; + return false; + } + bool retval = false; + + if (!stack_iface_->getPresentationPosition(&presentation_position).isOk()) { + LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType=" + << toString(session_type_) << " failed"; + return false; + } + return retval; +} + +void BluetoothAudioSession::UpdateSourceMetadata( + const struct source_metadata& source_metadata) { + std::lock_guard<std::recursive_mutex> guard(mutex_); + if (!IsSessionReady()) { + LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_) + << " has NO session"; + return; + } + + ssize_t track_count = source_metadata.track_count; + LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << "," + << track_count << " track(s)"; + if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH || + session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) { + return; + } + + SourceMetadata hal_source_metadata; + hal_source_metadata.tracks.resize(track_count); + for (int i = 0; i < track_count; i++) { + hal_source_metadata.tracks[i].usage = + static_cast<media::audio::common::AudioUsage>( + source_metadata.tracks[i].usage); + hal_source_metadata.tracks[i].contentType = + static_cast<media::audio::common::AudioContentType>( + source_metadata.tracks[i].content_type); + hal_source_metadata.tracks[i].gain = source_metadata.tracks[i].gain; + LOG(VERBOSE) << __func__ << " - SessionType=" << toString(session_type_) + << ", usage=" << toString(hal_source_metadata.tracks[i].usage) + << ", content=" + << toString(hal_source_metadata.tracks[i].contentType) + << ", gain=" << hal_source_metadata.tracks[i].gain; + } + + auto hal_retval = stack_iface_->updateSourceMetadata(hal_source_metadata); + if (!hal_retval.isOk()) { + LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType=" + << toString(session_type_) << " failed"; + } +} + +void BluetoothAudioSession::UpdateSinkMetadata( + const struct sink_metadata& sink_metadata) { + std::lock_guard<std::recursive_mutex> guard(mutex_); + if (!IsSessionReady()) { + LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_) + << " has NO session"; + return; + } + + ssize_t track_count = sink_metadata.track_count; + LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << "," + << track_count << " track(s)"; + if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH || + session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) { + return; + } + + SinkMetadata hal_sink_metadata; + hal_sink_metadata.tracks.resize(track_count); + for (int i = 0; i < track_count; i++) { + hal_sink_metadata.tracks[i].source = + static_cast<media::audio::common::AudioSource>( + sink_metadata.tracks[i].source); + hal_sink_metadata.tracks[i].gain = sink_metadata.tracks[i].gain; + LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) + << ", source=" << sink_metadata.tracks[i].source + << ", dest_device=" << sink_metadata.tracks[i].dest_device + << ", gain=" << sink_metadata.tracks[i].gain + << ", dest_device_address=" + << sink_metadata.tracks[i].dest_device_address; + } + + auto hal_retval = stack_iface_->updateSinkMetadata(hal_sink_metadata); + if (!hal_retval.isOk()) { + LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType=" + << toString(session_type_) << " failed"; + } +} + +bool BluetoothAudioSession::IsAidlAvailable() { + if (is_aidl_checked) return is_aidl_available; + is_aidl_available = + (AServiceManager_checkService( + kDefaultAudioProviderFactoryInterface.c_str()) != nullptr); + is_aidl_checked = true; + return is_aidl_available; +} + +/*** + * + * BluetoothAudioSessionInstance + * + ***/ +std::mutex BluetoothAudioSessionInstance::mutex_; +std::unordered_map<SessionType, std::shared_ptr<BluetoothAudioSession>> + BluetoothAudioSessionInstance::sessions_map_; + +std::shared_ptr<BluetoothAudioSession> +BluetoothAudioSessionInstance::GetSessionInstance( + const SessionType& session_type) { + std::lock_guard<std::mutex> guard(mutex_); + + if (!sessions_map_.empty()) { + auto entry = sessions_map_.find(session_type); + if (entry != sessions_map_.end()) { + return entry->second; + } + } + std::shared_ptr<BluetoothAudioSession> session_ptr = + std::make_shared<BluetoothAudioSession>(session_type); + sessions_map_[session_type] = session_ptr; + return session_ptr; +} + +} // namespace audio +} // namespace bluetooth +} // namespace hardware +} // namespace android +} // namespace aidl
\ No newline at end of file diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h new file mode 100644 index 0000000000..85fd571f28 --- /dev/null +++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <aidl/android/hardware/audio/common/SinkMetadata.h> +#include <aidl/android/hardware/audio/common/SourceMetadata.h> +#include <aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.h> +#include <aidl/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.h> +#include <aidl/android/hardware/bluetooth/audio/SessionType.h> +#include <fmq/AidlMessageQueue.h> +#include <hardware/audio.h> + +#include <mutex> +#include <unordered_map> + +namespace aidl { +namespace android { +namespace hardware { +namespace bluetooth { +namespace audio { + +using ::aidl::android::hardware::common::fmq::MQDescriptor; +using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite; +using ::android::AidlMessageQueue; + +using ::aidl::android::hardware::audio::common::SinkMetadata; +using ::aidl::android::hardware::audio::common::SourceMetadata; + +using MQDataType = int8_t; +using MQDataMode = SynchronizedReadWrite; +using DataMQ = AidlMessageQueue<MQDataType, MQDataMode>; +using DataMQDesc = + ::aidl::android::hardware::common::fmq::MQDescriptor<MQDataType, + MQDataMode>; + +static constexpr uint16_t kObserversCookieSize = 0x0010; // 0x0000 ~ 0x000f +static constexpr uint16_t kObserversCookieUndefined = + (static_cast<uint16_t>(SessionType::UNKNOWN) << 8 & 0xff00); +inline SessionType ObserversCookieGetSessionType(uint16_t cookie) { + return static_cast<SessionType>(cookie >> 8 & 0x00ff); +} +inline uint16_t ObserversCookieGetInitValue(SessionType session_type) { + return (static_cast<uint16_t>(session_type) << 8 & 0xff00); +} +inline uint16_t ObserversCookieGetUpperBound(SessionType session_type) { + return (static_cast<uint16_t>(session_type) << 8 & 0xff00) + + kObserversCookieSize; +} + +/*** + * This presents the callbacks of started / suspended and session changed, + * and the bluetooth_audio module uses to receive the status notification + ***/ +struct PortStatusCallbacks { + /*** + * control_result_cb_ - when the Bluetooth stack reports results of + * streamStarted or streamSuspended, the BluetoothAudioProvider will invoke + * this callback to report to the bluetooth_audio module. + * @param: cookie - indicates which bluetooth_audio output should handle + * @param: start_resp - this report is for startStream or not + * @param: status - the result of startStream + ***/ + std::function<void(uint16_t cookie, bool start_resp, + BluetoothAudioStatus status)> + control_result_cb_; + /*** + * session_changed_cb_ - when the Bluetooth stack start / end session, the + * BluetoothAudioProvider will invoke this callback to notify to the + * bluetooth_audio module. + * @param: cookie - indicates which bluetooth_audio output should handle + ***/ + std::function<void(uint16_t cookie)> session_changed_cb_; + /*** + * audio_configuration_changed_cb_ - when the Bluetooth stack change the audio + * configuration, the BluetoothAudioProvider will invoke this callback to + * notify to the bluetooth_audio module. + * @param: cookie - indicates which bluetooth_audio output should handle + ***/ + std::function<void(uint16_t cookie)> audio_configuration_changed_cb_; +}; + +class BluetoothAudioSession { + public: + BluetoothAudioSession(const SessionType& session_type); + + /*** + * The function helps to check if this session is ready or not + * @return: true if the Bluetooth stack has started the specified session + ***/ + bool IsSessionReady(); + + /*** + * The report function is used to report that the Bluetooth stack has started + * this session without any failure, and will invoke session_changed_cb_ to + * notify those registered bluetooth_audio outputs + ***/ + void OnSessionStarted(const std::shared_ptr<IBluetoothAudioPort> stack_iface, + const DataMQDesc* mq_desc, + const AudioConfiguration& audio_config); + + /*** + * The report function is used to report that the Bluetooth stack has ended + * the session, and will invoke session_changed_cb_ to notify registered + * bluetooth_audio outputs + ***/ + void OnSessionEnded(); + + /*** + * The report function is used to report that the Bluetooth stack has notified + * the result of startStream or suspendStream, and will invoke + * control_result_cb_ to notify registered bluetooth_audio outputs + ***/ + void ReportControlStatus(bool start_resp, BluetoothAudioStatus status); + + /*** + * The control function helps the bluetooth_audio module to register + * PortStatusCallbacks + * @return: cookie - the assigned number to this bluetooth_audio output + ***/ + uint16_t RegisterStatusCback(const PortStatusCallbacks& cbacks); + + /*** + * The control function helps the bluetooth_audio module to unregister + * PortStatusCallbacks + * @param: cookie - indicates which bluetooth_audio output is + ***/ + void UnregisterStatusCback(uint16_t cookie); + + /*** + * The control function is for the bluetooth_audio module to get the current + * AudioConfiguration + ***/ + const AudioConfiguration& GetAudioConfig(); + + /*** + * The report function is used to report that the Bluetooth stack has notified + * the audio configuration changed, and will invoke + * audio_configuration_changed_cb_ to notify registered bluetooth_audio + * outputs + ***/ + void ReportAudioConfigChanged(const AudioConfiguration& audio_config); + + /*** + * Those control functions are for the bluetooth_audio module to start, + * suspend, stop stream, to check position, and to update metadata. + ***/ + bool StartStream(); + bool SuspendStream(); + void StopStream(); + bool GetPresentationPosition(PresentationPosition& presentation_position); + void UpdateSourceMetadata(const struct source_metadata& source_metadata); + void UpdateSinkMetadata(const struct sink_metadata& sink_metadata); + + // The control function writes stream to FMQ + size_t OutWritePcmData(const void* buffer, size_t bytes); + // The control function read stream from FMQ + size_t InReadPcmData(void* buffer, size_t bytes); + + // Return if IBluetoothAudioProviderFactory implementation existed + static bool IsAidlAvailable(); + + static constexpr PcmConfiguration kInvalidPcmConfiguration = {}; + // can't be constexpr because of non-literal type + static const CodecConfiguration kInvalidCodecConfiguration; + + static AudioConfiguration invalidSoftwareAudioConfiguration; + static AudioConfiguration invalidOffloadAudioConfiguration; + static AudioConfiguration invalidLeOffloadAudioConfig; + + private: + // using recursive_mutex to allow hwbinder to re-enter again. + std::recursive_mutex mutex_; + SessionType session_type_; + + // audio control path to use for both software and offloading + std::shared_ptr<IBluetoothAudioPort> stack_iface_; + // audio data path (FMQ) for software encoding + std::unique_ptr<DataMQ> data_mq_; + // audio data configuration for both software and offloading + std::unique_ptr<AudioConfiguration> audio_config_; + + // saving those registered bluetooth_audio's callbacks + std::unordered_map<uint16_t, std::shared_ptr<struct PortStatusCallbacks>> + observers_; + + bool UpdateDataPath(const DataMQDesc* mq_desc); + bool UpdateAudioConfig(const AudioConfiguration& audio_config); + // invoking the registered session_changed_cb_ + void ReportSessionStatus(); + + static inline std::atomic<bool> is_aidl_checked = false; + static inline std::atomic<bool> is_aidl_available = false; + static inline const std::string kDefaultAudioProviderFactoryInterface = + std::string() + IBluetoothAudioProviderFactory::descriptor + "/default"; +}; + +class BluetoothAudioSessionInstance { + public: + // The API is to fetch the specified session of A2DP / Hearing Aid + static std::shared_ptr<BluetoothAudioSession> GetSessionInstance( + const SessionType& session_type); + + private: + static std::mutex mutex_; + static std::unordered_map<SessionType, std::shared_ptr<BluetoothAudioSession>> + sessions_map_; +}; + +} // namespace audio +} // namespace bluetooth +} // namespace hardware +} // namespace android +} // namespace aidl
\ No newline at end of file diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h new file mode 100644 index 0000000000..a3ed42894c --- /dev/null +++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h @@ -0,0 +1,182 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "BluetoothAudioSession.h" + +namespace aidl { +namespace android { +namespace hardware { +namespace bluetooth { +namespace audio { + +class BluetoothAudioSessionControl { + public: + /*** + * The control API helps to check if session is ready or not + * @return: true if the Bluetooth stack has started th specified session + ***/ + static bool IsSessionReady(const SessionType& session_type) { + std::shared_ptr<BluetoothAudioSession> session_ptr = + BluetoothAudioSessionInstance::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + return session_ptr->IsSessionReady(); + } + + return false; + } + + /*** + * The control API helps the bluetooth_audio module to register + * PortStatusCallbacks + * @return: cookie - the assigned number to this bluetooth_audio output + ***/ + static uint16_t RegisterControlResultCback( + const SessionType& session_type, const PortStatusCallbacks& cbacks) { + std::shared_ptr<BluetoothAudioSession> session_ptr = + BluetoothAudioSessionInstance::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + return session_ptr->RegisterStatusCback(cbacks); + } + return kObserversCookieUndefined; + } + + /*** + * The control API helps the bluetooth_audio module to unregister + * PortStatusCallbacks + * @param: cookie - indicates which bluetooth_audio output is + ***/ + static void UnregisterControlResultCback(const SessionType& session_type, + uint16_t cookie) { + std::shared_ptr<BluetoothAudioSession> session_ptr = + BluetoothAudioSessionInstance::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + session_ptr->UnregisterStatusCback(cookie); + } + } + + /*** + * The control API for the bluetooth_audio module to get current + * AudioConfiguration + ***/ + static const AudioConfiguration GetAudioConfig( + const SessionType& session_type) { + std::shared_ptr<BluetoothAudioSession> session_ptr = + BluetoothAudioSessionInstance::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + return session_ptr->GetAudioConfig(); + } else if (session_type == + SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) { + return BluetoothAudioSession::invalidOffloadAudioConfiguration; + } else { + return BluetoothAudioSession::invalidSoftwareAudioConfiguration; + } + } + + /*** + * Those control APIs for the bluetooth_audio module to start / suspend / + stop + * stream, to check position, and to update metadata. + ***/ + static bool StartStream(const SessionType& session_type) { + std::shared_ptr<BluetoothAudioSession> session_ptr = + BluetoothAudioSessionInstance::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + return session_ptr->StartStream(); + } + return false; + } + + static bool SuspendStream(const SessionType& session_type) { + std::shared_ptr<BluetoothAudioSession> session_ptr = + BluetoothAudioSessionInstance::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + return session_ptr->SuspendStream(); + } + return false; + } + + static void StopStream(const SessionType& session_type) { + std::shared_ptr<BluetoothAudioSession> session_ptr = + BluetoothAudioSessionInstance::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + session_ptr->StopStream(); + } + } + + static bool GetPresentationPosition( + const SessionType& session_type, + PresentationPosition& presentation_position) { + std::shared_ptr<BluetoothAudioSession> session_ptr = + BluetoothAudioSessionInstance::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + return session_ptr->GetPresentationPosition(presentation_position); + } + return false; + } + + static void UpdateSourceMetadata( + const SessionType& session_type, + const struct source_metadata& source_metadata) { + std::shared_ptr<BluetoothAudioSession> session_ptr = + BluetoothAudioSessionInstance::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + session_ptr->UpdateSourceMetadata(source_metadata); + } + } + + static void UpdateSinkMetadata(const SessionType& session_type, + const struct sink_metadata& sink_metadata) { + std::shared_ptr<BluetoothAudioSession> session_ptr = + BluetoothAudioSessionInstance::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + session_ptr->UpdateSinkMetadata(sink_metadata); + } + } + + /*** + * The control API writes stream to FMQ + ***/ + static size_t OutWritePcmData(const SessionType& session_type, + const void* buffer, size_t bytes) { + std::shared_ptr<BluetoothAudioSession> session_ptr = + BluetoothAudioSessionInstance::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + return session_ptr->OutWritePcmData(buffer, bytes); + } + return 0; + } + + /*** + * The control API reads stream from FMQ + ***/ + static size_t InReadPcmData(const SessionType& session_type, void* buffer, + size_t bytes) { + std::shared_ptr<BluetoothAudioSession> session_ptr = + BluetoothAudioSessionInstance::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + return session_ptr->InReadPcmData(buffer, bytes); + } + return 0; + } +}; + +} // namespace audio +} // namespace bluetooth +} // namespace hardware +} // namespace android +} // namespace aidl
\ No newline at end of file diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionReport.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionReport.h new file mode 100644 index 0000000000..18569c3827 --- /dev/null +++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionReport.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "BluetoothAudioSession.h" + +namespace aidl { +namespace android { +namespace hardware { +namespace bluetooth { +namespace audio { + +class BluetoothAudioSessionReport { + public: + /*** + * The API reports the Bluetooth stack has started the session, and will + * inform registered bluetooth_audio outputs + ***/ + static void OnSessionStarted( + const SessionType& session_type, + const std::shared_ptr<IBluetoothAudioPort> host_iface, + const DataMQDesc* data_mq, const AudioConfiguration& audio_config) { + std::shared_ptr<BluetoothAudioSession> session_ptr = + BluetoothAudioSessionInstance::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + session_ptr->OnSessionStarted(host_iface, data_mq, audio_config); + } + } + + /*** + * The API reports the Bluetooth stack has ended the session, and will + * inform registered bluetooth_audio outputs + ***/ + static void OnSessionEnded(const SessionType& session_type) { + std::shared_ptr<BluetoothAudioSession> session_ptr = + BluetoothAudioSessionInstance::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + session_ptr->OnSessionEnded(); + } + } + + /*** + * The API reports the Bluetooth stack has replied the result of startStream + * or suspendStream, and will inform registered bluetooth_audio outputs + ***/ + static void ReportControlStatus(const SessionType& session_type, + const bool& start_resp, + BluetoothAudioStatus status) { + std::shared_ptr<BluetoothAudioSession> session_ptr = + BluetoothAudioSessionInstance::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + session_ptr->ReportControlStatus(start_resp, status); + } + } + /*** + * The API reports the Bluetooth stack has replied the changed of the audio + * configuration, and will inform registered bluetooth_audio outputs + ***/ + static void ReportAudioConfigChanged(const SessionType& session_type, + const AudioConfiguration& audio_config) { + std::shared_ptr<BluetoothAudioSession> session_ptr = + BluetoothAudioSessionInstance::GetSessionInstance(session_type); + if (session_ptr != nullptr) { + session_ptr->ReportAudioConfigChanged(audio_config); + } + } +}; + +} // namespace audio +} // namespace bluetooth +} // namespace hardware +} // namespace android +} // namespace aidl
\ No newline at end of file diff --git a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp new file mode 100644 index 0000000000..91e0238783 --- /dev/null +++ b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp @@ -0,0 +1,775 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "BtAudioNakahara" + +#include <aidl/android/hardware/bluetooth/audio/AudioConfiguration.h> +#include <aidl/android/hardware/bluetooth/audio/BluetoothAudioStatus.h> +#include <aidl/android/hardware/bluetooth/audio/SessionType.h> +#include <android-base/logging.h> + +#include <functional> +#include <unordered_map> + +#include "../aidl_session/BluetoothAudioSession.h" +#include "../aidl_session/BluetoothAudioSessionControl.h" +#include "HidlToAidlMiddleware_2_0.h" +#include "HidlToAidlMiddleware_2_1.h" +#include "HidlToAidlMiddleware_2_2.h" + +namespace aidl { +namespace android { +namespace hardware { +namespace bluetooth { +namespace audio { + +using HidlStatus = ::android::hardware::bluetooth::audio::V2_0::Status; +using PcmConfig_2_0 = + ::android::hardware::bluetooth::audio::V2_0::PcmParameters; +using SampleRate_2_0 = ::android::hardware::bluetooth::audio::V2_0::SampleRate; +using ChannelMode_2_0 = + ::android::hardware::bluetooth::audio::V2_0::ChannelMode; +using BitsPerSample_2_0 = + ::android::hardware::bluetooth::audio::V2_0::BitsPerSample; +using CodecConfig_2_0 = + ::android::hardware::bluetooth::audio::V2_0::CodecConfiguration; +using CodecType_2_0 = ::android::hardware::bluetooth::audio::V2_0::CodecType; +using SbcConfig_2_0 = + ::android::hardware::bluetooth::audio::V2_0::SbcParameters; +using AacConfig_2_0 = + ::android::hardware::bluetooth::audio::V2_0::AacParameters; +using LdacConfig_2_0 = + ::android::hardware::bluetooth::audio::V2_0::LdacParameters; +using AptxConfig_2_0 = + ::android::hardware::bluetooth::audio::V2_0::AptxParameters; +using SbcAllocMethod_2_0 = + ::android::hardware::bluetooth::audio::V2_0::SbcAllocMethod; +using SbcBlockLength_2_0 = + ::android::hardware::bluetooth::audio::V2_0::SbcBlockLength; +using SbcChannelMode_2_0 = + ::android::hardware::bluetooth::audio::V2_0::SbcChannelMode; +using SbcNumSubbands_2_0 = + ::android::hardware::bluetooth::audio::V2_0::SbcNumSubbands; +using AacObjectType_2_0 = + ::android::hardware::bluetooth::audio::V2_0::AacObjectType; +using AacVarBitRate_2_0 = + ::android::hardware::bluetooth::audio::V2_0::AacVariableBitRate; +using LdacChannelMode_2_0 = + ::android::hardware::bluetooth::audio::V2_0::LdacChannelMode; +using LdacQualityIndex_2_0 = + ::android::hardware::bluetooth::audio::V2_0::LdacQualityIndex; + +using PcmConfig_2_1 = + ::android::hardware::bluetooth::audio::V2_1::PcmParameters; +using SampleRate_2_1 = ::android::hardware::bluetooth::audio::V2_1::SampleRate; +using Lc3CodecConfig_2_1 = + ::android::hardware::bluetooth::audio::V2_1::Lc3CodecConfiguration; +using Lc3Config_2_1 = + ::android::hardware::bluetooth::audio::V2_1::Lc3Parameters; +using Lc3FrameDuration_2_1 = + ::android::hardware::bluetooth::audio::V2_1::Lc3FrameDuration; + +using LeAudioConfig_2_2 = + ::android::hardware::bluetooth::audio::V2_2::LeAudioConfiguration; +using LeAudioMode_2_2 = + ::android::hardware::bluetooth::audio::V2_2::LeAudioMode; + +std::mutex legacy_callback_lock; +std::unordered_map< + SessionType, + std::unordered_map<uint16_t, std::shared_ptr<PortStatusCallbacks_2_2>>> + legacy_callback_table; + +const static std::unordered_map<SessionType_2_0, SessionType> + session_type_2_0_to_aidl_map{ + {SessionType_2_0::A2DP_SOFTWARE_ENCODING_DATAPATH, + SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH}, + {SessionType_2_0::A2DP_HARDWARE_OFFLOAD_DATAPATH, + SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH}, + {SessionType_2_0::HEARING_AID_SOFTWARE_ENCODING_DATAPATH, + SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH}, + }; + +const static std::unordered_map<SessionType_2_1, SessionType> + session_type_2_1_to_aidl_map{ + {SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH, + SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH}, + {SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH, + SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH}, + {SessionType_2_1::HEARING_AID_SOFTWARE_ENCODING_DATAPATH, + SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH}, + {SessionType_2_1::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH, + SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH}, + {SessionType_2_1::LE_AUDIO_SOFTWARE_DECODED_DATAPATH, + SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH}, + {SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH, + SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH}, + {SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH, + SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH}, + }; + +const static std::unordered_map<int32_t, SampleRate_2_0> + sample_rate_to_hidl_2_0_map{ + {44100, SampleRate_2_0::RATE_44100}, + {48000, SampleRate_2_0::RATE_48000}, + {88200, SampleRate_2_0::RATE_88200}, + {96000, SampleRate_2_0::RATE_96000}, + {176400, SampleRate_2_0::RATE_176400}, + {192000, SampleRate_2_0::RATE_192000}, + {16000, SampleRate_2_0::RATE_16000}, + {24000, SampleRate_2_0::RATE_24000}, + }; + +const static std::unordered_map<int32_t, SampleRate_2_1> + sample_rate_to_hidl_2_1_map{ + {44100, SampleRate_2_1::RATE_44100}, + {48000, SampleRate_2_1::RATE_48000}, + {88200, SampleRate_2_1::RATE_88200}, + {96000, SampleRate_2_1::RATE_96000}, + {176400, SampleRate_2_1::RATE_176400}, + {192000, SampleRate_2_1::RATE_192000}, + {16000, SampleRate_2_1::RATE_16000}, + {24000, SampleRate_2_1::RATE_24000}, + {8000, SampleRate_2_1::RATE_8000}, + {32000, SampleRate_2_1::RATE_32000}, + }; + +const static std::unordered_map<CodecType, CodecType_2_0> + codec_type_to_hidl_2_0_map{ + {CodecType::UNKNOWN, CodecType_2_0::UNKNOWN}, + {CodecType::SBC, CodecType_2_0::SBC}, + {CodecType::AAC, CodecType_2_0::AAC}, + {CodecType::APTX, CodecType_2_0::APTX}, + {CodecType::APTX_HD, CodecType_2_0::APTX_HD}, + {CodecType::LDAC, CodecType_2_0::LDAC}, + {CodecType::LC3, CodecType_2_0::UNKNOWN}, + }; + +const static std::unordered_map<SbcChannelMode, SbcChannelMode_2_0> + sbc_channel_mode_to_hidl_2_0_map{ + {SbcChannelMode::UNKNOWN, SbcChannelMode_2_0::UNKNOWN}, + {SbcChannelMode::JOINT_STEREO, SbcChannelMode_2_0::JOINT_STEREO}, + {SbcChannelMode::STEREO, SbcChannelMode_2_0::STEREO}, + {SbcChannelMode::DUAL, SbcChannelMode_2_0::DUAL}, + {SbcChannelMode::MONO, SbcChannelMode_2_0::MONO}, + }; + +const static std::unordered_map<int8_t, SbcBlockLength_2_0> + sbc_block_length_to_hidl_map{ + {4, SbcBlockLength_2_0::BLOCKS_4}, + {8, SbcBlockLength_2_0::BLOCKS_8}, + {12, SbcBlockLength_2_0::BLOCKS_12}, + {16, SbcBlockLength_2_0::BLOCKS_16}, + }; + +const static std::unordered_map<int8_t, SbcNumSubbands_2_0> + sbc_subbands_to_hidl_map{ + {4, SbcNumSubbands_2_0::SUBBAND_4}, + {8, SbcNumSubbands_2_0::SUBBAND_8}, + }; + +const static std::unordered_map<SbcAllocMethod, SbcAllocMethod_2_0> + sbc_alloc_method_to_hidl_map{ + {SbcAllocMethod::ALLOC_MD_S, SbcAllocMethod_2_0::ALLOC_MD_S}, + {SbcAllocMethod::ALLOC_MD_L, SbcAllocMethod_2_0::ALLOC_MD_L}, + }; + +const static std::unordered_map<AacObjectType, AacObjectType_2_0> + aac_object_type_to_hidl_map{ + {AacObjectType::MPEG2_LC, AacObjectType_2_0::MPEG2_LC}, + {AacObjectType::MPEG4_LC, AacObjectType_2_0::MPEG4_LC}, + {AacObjectType::MPEG4_LTP, AacObjectType_2_0::MPEG4_LTP}, + {AacObjectType::MPEG4_SCALABLE, AacObjectType_2_0::MPEG4_SCALABLE}, + }; + +const static std::unordered_map<LdacChannelMode, LdacChannelMode_2_0> + ldac_channel_mode_to_hidl_map{ + {LdacChannelMode::UNKNOWN, LdacChannelMode_2_0::UNKNOWN}, + {LdacChannelMode::STEREO, LdacChannelMode_2_0::STEREO}, + {LdacChannelMode::DUAL, LdacChannelMode_2_0::DUAL}, + {LdacChannelMode::MONO, LdacChannelMode_2_0::MONO}, + }; + +const static std::unordered_map<LdacQualityIndex, LdacQualityIndex_2_0> + ldac_qindex_to_hidl_map{ + {LdacQualityIndex::HIGH, LdacQualityIndex_2_0::QUALITY_HIGH}, + {LdacQualityIndex::MID, LdacQualityIndex_2_0::QUALITY_MID}, + {LdacQualityIndex::LOW, LdacQualityIndex_2_0::QUALITY_LOW}, + {LdacQualityIndex::ABR, LdacQualityIndex_2_0::QUALITY_ABR}, + }; + +const static std::unordered_map<LeAudioMode, LeAudioMode_2_2> + leaudio_mode_to_hidl_map{ + {LeAudioMode::UNKNOWN, LeAudioMode_2_2::UNKNOWN}, + {LeAudioMode::UNICAST, LeAudioMode_2_2::UNICAST}, + {LeAudioMode::BROADCAST, LeAudioMode_2_2::BROADCAST}, + }; + +inline SessionType from_session_type_2_0( + const SessionType_2_0& session_type_hidl) { + auto it = session_type_2_0_to_aidl_map.find(session_type_hidl); + if (it != session_type_2_0_to_aidl_map.end()) return it->second; + return SessionType::UNKNOWN; +} + +inline SessionType from_session_type_2_1( + const SessionType_2_1& session_type_hidl) { + auto it = session_type_2_1_to_aidl_map.find(session_type_hidl); + if (it != session_type_2_1_to_aidl_map.end()) return it->second; + return SessionType::UNKNOWN; +} + +inline HidlStatus to_hidl_status(const BluetoothAudioStatus& status) { + switch (status) { + case BluetoothAudioStatus::SUCCESS: + return HidlStatus::SUCCESS; + case BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION: + return HidlStatus::UNSUPPORTED_CODEC_CONFIGURATION; + default: + return HidlStatus::FAILURE; + } +} + +inline SampleRate_2_0 to_hidl_sample_rate_2_0(const int32_t sample_rate_hz) { + auto it = sample_rate_to_hidl_2_0_map.find(sample_rate_hz); + if (it != sample_rate_to_hidl_2_0_map.end()) return it->second; + return SampleRate_2_0::RATE_UNKNOWN; +} + +inline SampleRate_2_1 to_hidl_sample_rate_2_1(const int32_t sample_rate_hz) { + auto it = sample_rate_to_hidl_2_1_map.find(sample_rate_hz); + if (it != sample_rate_to_hidl_2_1_map.end()) return it->second; + return SampleRate_2_1::RATE_UNKNOWN; +} + +inline BitsPerSample_2_0 to_hidl_bits_per_sample(const int8_t bit_per_sample) { + switch (bit_per_sample) { + case 16: + return BitsPerSample_2_0::BITS_16; + case 24: + return BitsPerSample_2_0::BITS_24; + case 32: + return BitsPerSample_2_0::BITS_32; + default: + return BitsPerSample_2_0::BITS_UNKNOWN; + } +} + +inline ChannelMode_2_0 to_hidl_channel_mode(const ChannelMode channel_mode) { + switch (channel_mode) { + case ChannelMode::MONO: + return ChannelMode_2_0::MONO; + case ChannelMode::STEREO: + return ChannelMode_2_0::STEREO; + default: + return ChannelMode_2_0::UNKNOWN; + } +} + +inline PcmConfig_2_0 to_hidl_pcm_config_2_0( + const PcmConfiguration& pcm_config) { + PcmConfig_2_0 hidl_pcm_config; + hidl_pcm_config.sampleRate = to_hidl_sample_rate_2_0(pcm_config.sampleRateHz); + hidl_pcm_config.channelMode = to_hidl_channel_mode(pcm_config.channelMode); + hidl_pcm_config.bitsPerSample = + to_hidl_bits_per_sample(pcm_config.bitsPerSample); + return hidl_pcm_config; +} + +inline CodecType_2_0 to_hidl_codec_type_2_0(const CodecType codec_type) { + auto it = codec_type_to_hidl_2_0_map.find(codec_type); + if (it != codec_type_to_hidl_2_0_map.end()) return it->second; + return CodecType_2_0::UNKNOWN; +} + +inline SbcConfig_2_0 to_hidl_sbc_config(const SbcConfiguration sbc_config) { + SbcConfig_2_0 hidl_sbc_config; + hidl_sbc_config.minBitpool = sbc_config.minBitpool; + hidl_sbc_config.maxBitpool = sbc_config.maxBitpool; + hidl_sbc_config.sampleRate = to_hidl_sample_rate_2_0(sbc_config.sampleRateHz); + hidl_sbc_config.bitsPerSample = + to_hidl_bits_per_sample(sbc_config.bitsPerSample); + if (sbc_channel_mode_to_hidl_2_0_map.find(sbc_config.channelMode) != + sbc_channel_mode_to_hidl_2_0_map.end()) { + hidl_sbc_config.channelMode = + sbc_channel_mode_to_hidl_2_0_map.at(sbc_config.channelMode); + } + if (sbc_block_length_to_hidl_map.find(sbc_config.blockLength) != + sbc_block_length_to_hidl_map.end()) { + hidl_sbc_config.blockLength = + sbc_block_length_to_hidl_map.at(sbc_config.blockLength); + } + if (sbc_subbands_to_hidl_map.find(sbc_config.numSubbands) != + sbc_subbands_to_hidl_map.end()) { + hidl_sbc_config.numSubbands = + sbc_subbands_to_hidl_map.at(sbc_config.numSubbands); + } + if (sbc_alloc_method_to_hidl_map.find(sbc_config.allocMethod) != + sbc_alloc_method_to_hidl_map.end()) { + hidl_sbc_config.allocMethod = + sbc_alloc_method_to_hidl_map.at(sbc_config.allocMethod); + } + return hidl_sbc_config; +} + +inline AacConfig_2_0 to_hidl_aac_config(const AacConfiguration aac_config) { + AacConfig_2_0 hidl_aac_config; + hidl_aac_config.sampleRate = to_hidl_sample_rate_2_0(aac_config.sampleRateHz); + hidl_aac_config.bitsPerSample = + to_hidl_bits_per_sample(aac_config.bitsPerSample); + hidl_aac_config.channelMode = to_hidl_channel_mode(aac_config.channelMode); + if (aac_object_type_to_hidl_map.find(aac_config.objectType) != + aac_object_type_to_hidl_map.end()) { + hidl_aac_config.objectType = + aac_object_type_to_hidl_map.at(aac_config.objectType); + } + hidl_aac_config.variableBitRateEnabled = aac_config.variableBitRateEnabled + ? AacVarBitRate_2_0::ENABLED + : AacVarBitRate_2_0::DISABLED; + return hidl_aac_config; +} + +inline LdacConfig_2_0 to_hidl_ldac_config(const LdacConfiguration ldac_config) { + LdacConfig_2_0 hidl_ldac_config; + hidl_ldac_config.sampleRate = + to_hidl_sample_rate_2_0(ldac_config.sampleRateHz); + hidl_ldac_config.bitsPerSample = + to_hidl_bits_per_sample(ldac_config.bitsPerSample); + if (ldac_channel_mode_to_hidl_map.find(ldac_config.channelMode) != + ldac_channel_mode_to_hidl_map.end()) { + hidl_ldac_config.channelMode = + ldac_channel_mode_to_hidl_map.at(ldac_config.channelMode); + } + if (ldac_qindex_to_hidl_map.find(ldac_config.qualityIndex) != + ldac_qindex_to_hidl_map.end()) { + hidl_ldac_config.qualityIndex = + ldac_qindex_to_hidl_map.at(ldac_config.qualityIndex); + } + return hidl_ldac_config; +} + +inline AptxConfig_2_0 to_hidl_aptx_config(const AptxConfiguration aptx_config) { + AptxConfig_2_0 hidl_aptx_config; + hidl_aptx_config.sampleRate = + to_hidl_sample_rate_2_0(aptx_config.sampleRateHz); + hidl_aptx_config.bitsPerSample = + to_hidl_bits_per_sample(aptx_config.bitsPerSample); + hidl_aptx_config.channelMode = to_hidl_channel_mode(aptx_config.channelMode); + return hidl_aptx_config; +} + +inline CodecConfig_2_0 to_hidl_codec_config_2_0( + const CodecConfiguration& codec_config) { + CodecConfig_2_0 hidl_codec_config; + hidl_codec_config.codecType = to_hidl_codec_type_2_0(codec_config.codecType); + hidl_codec_config.encodedAudioBitrate = + static_cast<uint32_t>(codec_config.encodedAudioBitrate); + hidl_codec_config.peerMtu = static_cast<uint32_t>(codec_config.peerMtu); + hidl_codec_config.isScmstEnabled = codec_config.isScmstEnabled; + switch (codec_config.config.getTag()) { + case CodecConfiguration::CodecSpecific::sbcConfig: + hidl_codec_config.config.sbcConfig(to_hidl_sbc_config( + codec_config.config + .get<CodecConfiguration::CodecSpecific::sbcConfig>())); + break; + case CodecConfiguration::CodecSpecific::aacConfig: + hidl_codec_config.config.aacConfig(to_hidl_aac_config( + codec_config.config + .get<CodecConfiguration::CodecSpecific::aacConfig>())); + break; + case CodecConfiguration::CodecSpecific::ldacConfig: + hidl_codec_config.config.ldacConfig(to_hidl_ldac_config( + codec_config.config + .get<CodecConfiguration::CodecSpecific::ldacConfig>())); + break; + case CodecConfiguration::CodecSpecific::aptxConfig: + hidl_codec_config.config.aptxConfig(to_hidl_aptx_config( + codec_config.config + .get<CodecConfiguration::CodecSpecific::aptxConfig>())); + break; + default: + break; + } + return hidl_codec_config; +} + +inline AudioConfig_2_0 to_hidl_audio_config_2_0( + const AudioConfiguration& audio_config) { + AudioConfig_2_0 hidl_audio_config; + if (audio_config.getTag() == AudioConfiguration::pcmConfig) { + hidl_audio_config.pcmConfig(to_hidl_pcm_config_2_0( + audio_config.get<AudioConfiguration::pcmConfig>())); + } else if (audio_config.getTag() == AudioConfiguration::a2dpConfig) { + hidl_audio_config.codecConfig(to_hidl_codec_config_2_0( + audio_config.get<AudioConfiguration::a2dpConfig>())); + } + return hidl_audio_config; +} + +inline PcmConfig_2_1 to_hidl_pcm_config_2_1( + const PcmConfiguration& pcm_config) { + PcmConfig_2_1 hidl_pcm_config; + hidl_pcm_config.sampleRate = to_hidl_sample_rate_2_1(pcm_config.sampleRateHz); + hidl_pcm_config.channelMode = to_hidl_channel_mode(pcm_config.channelMode); + hidl_pcm_config.bitsPerSample = + to_hidl_bits_per_sample(pcm_config.bitsPerSample); + hidl_pcm_config.dataIntervalUs = + static_cast<uint32_t>(pcm_config.dataIntervalUs); + return hidl_pcm_config; +} + +inline Lc3Config_2_1 to_hidl_lc3_config_2_1( + const Lc3Configuration& lc3_config) { + Lc3Config_2_1 hidl_lc3_config; + hidl_lc3_config.pcmBitDepth = to_hidl_bits_per_sample(lc3_config.pcmBitDepth); + hidl_lc3_config.samplingFrequency = + to_hidl_sample_rate_2_1(lc3_config.samplingFrequencyHz); + if (lc3_config.samplingFrequencyHz == 10000) + hidl_lc3_config.frameDuration = Lc3FrameDuration_2_1::DURATION_10000US; + else if (lc3_config.samplingFrequencyHz == 7500) + hidl_lc3_config.frameDuration = Lc3FrameDuration_2_1::DURATION_7500US; + hidl_lc3_config.octetsPerFrame = + static_cast<uint32_t>(lc3_config.octetsPerFrame); + hidl_lc3_config.blocksPerSdu = static_cast<uint32_t>(lc3_config.blocksPerSdu); + return hidl_lc3_config; +} + +inline Lc3CodecConfig_2_1 to_hidl_leaudio_config_2_1( + const LeAudioConfiguration& leaudio_config) { + auto& unicast_config = + leaudio_config.modeConfig + .get<LeAudioConfiguration::LeAudioModeConfig::unicastConfig>(); + + auto& le_codec_config = unicast_config.leAudioCodecConfig + .get<LeAudioCodecConfiguration::lc3Config>(); + + Lc3CodecConfig_2_1 hidl_lc3_codec_config; + hidl_lc3_codec_config.lc3Config = to_hidl_lc3_config_2_1(le_codec_config); + + hidl_lc3_codec_config.audioChannelAllocation = + unicast_config.streamMap.size(); + + return hidl_lc3_codec_config; +} + +inline LeAudioConfig_2_2 to_hidl_leaudio_config_2_2( + const LeAudioConfiguration& leaudio_config) { + LeAudioConfig_2_2 hidl_leaudio_config; + if (leaudio_mode_to_hidl_map.find(leaudio_config.mode) != + leaudio_mode_to_hidl_map.end()) { + hidl_leaudio_config.mode = leaudio_mode_to_hidl_map.at(leaudio_config.mode); + } + + if (leaudio_config.modeConfig.getTag() == + LeAudioConfiguration::LeAudioModeConfig::unicastConfig) { + auto& unicast_config = + leaudio_config.modeConfig + .get<LeAudioConfiguration::LeAudioModeConfig::unicastConfig>(); + ::android::hardware::bluetooth::audio::V2_2::UnicastConfig + hidl_unicast_config; + hidl_unicast_config.peerDelay = + static_cast<uint32_t>(unicast_config.peerDelay); + + auto& lc3_config = unicast_config.leAudioCodecConfig + .get<LeAudioCodecConfiguration::lc3Config>(); + hidl_unicast_config.lc3Config = to_hidl_lc3_config_2_1(lc3_config); + + hidl_unicast_config.streamMap.resize(unicast_config.streamMap.size()); + for (int i = 0; i < unicast_config.streamMap.size(); i++) { + hidl_unicast_config.streamMap[i].audioChannelAllocation = + static_cast<uint32_t>( + unicast_config.streamMap[i].audioChannelAllocation); + hidl_unicast_config.streamMap[i].streamHandle = + static_cast<uint16_t>(unicast_config.streamMap[i].streamHandle); + } + } else if (leaudio_config.modeConfig.getTag() == + LeAudioConfiguration::LeAudioModeConfig::broadcastConfig) { + auto bcast_config = + leaudio_config.modeConfig + .get<LeAudioConfiguration::LeAudioModeConfig::broadcastConfig>(); + ::android::hardware::bluetooth::audio::V2_2::BroadcastConfig + hidl_bcast_config; + hidl_bcast_config.streamMap.resize(bcast_config.streamMap.size()); + for (int i = 0; i < bcast_config.streamMap.size(); i++) { + hidl_bcast_config.streamMap[i].audioChannelAllocation = + static_cast<uint32_t>( + bcast_config.streamMap[i].audioChannelAllocation); + hidl_bcast_config.streamMap[i].streamHandle = + static_cast<uint16_t>(bcast_config.streamMap[i].streamHandle); + hidl_bcast_config.streamMap[i].lc3Config = to_hidl_lc3_config_2_1( + bcast_config.streamMap[i] + .leAudioCodecConfig.get<LeAudioCodecConfiguration::lc3Config>()); + } + } + return hidl_leaudio_config; +} + +inline AudioConfig_2_1 to_hidl_audio_config_2_1( + const AudioConfiguration& audio_config) { + AudioConfig_2_1 hidl_audio_config; + switch (audio_config.getTag()) { + case AudioConfiguration::pcmConfig: + hidl_audio_config.pcmConfig(to_hidl_pcm_config_2_1( + audio_config.get<AudioConfiguration::pcmConfig>())); + break; + case AudioConfiguration::a2dpConfig: + hidl_audio_config.codecConfig(to_hidl_codec_config_2_0( + audio_config.get<AudioConfiguration::a2dpConfig>())); + break; + case AudioConfiguration::leAudioConfig: + hidl_audio_config.leAudioCodecConfig(to_hidl_leaudio_config_2_1( + audio_config.get<AudioConfiguration::leAudioConfig>())); + break; + } + return hidl_audio_config; +} + +inline AudioConfig_2_2 to_hidl_audio_config_2_2( + const AudioConfiguration& audio_config) { + AudioConfig_2_2 hidl_audio_config; + switch (audio_config.getTag()) { + case AudioConfiguration::pcmConfig: + hidl_audio_config.pcmConfig(to_hidl_pcm_config_2_1( + audio_config.get<AudioConfiguration::pcmConfig>())); + break; + case AudioConfiguration::a2dpConfig: + hidl_audio_config.codecConfig(to_hidl_codec_config_2_0( + audio_config.get<AudioConfiguration::a2dpConfig>())); + break; + case AudioConfiguration::leAudioConfig: + hidl_audio_config.leAudioConfig(to_hidl_leaudio_config_2_2( + audio_config.get<AudioConfiguration::leAudioConfig>())); + break; + } + return hidl_audio_config; +} + +/*** + * + * 2.0 + * + ***/ + +bool HidlToAidlMiddleware_2_0::IsSessionReady( + const SessionType_2_0& session_type) { + return BluetoothAudioSessionControl::IsSessionReady( + from_session_type_2_0(session_type)); +} + +uint16_t HidlToAidlMiddleware_2_0::RegisterControlResultCback( + const SessionType_2_0& session_type, + const PortStatusCallbacks_2_0& cbacks) { + PortStatusCallbacks_2_2 callback_2_2{ + .control_result_cb_ = cbacks.control_result_cb_, + .session_changed_cb_ = cbacks.session_changed_cb_, + }; + return HidlToAidlMiddleware_2_2::RegisterControlResultCback( + static_cast<SessionType_2_1>(session_type), callback_2_2); +} + +void HidlToAidlMiddleware_2_0::UnregisterControlResultCback( + const SessionType_2_0& session_type, uint16_t cookie) { + HidlToAidlMiddleware_2_2::UnregisterControlResultCback( + static_cast<SessionType_2_1>(session_type), cookie); +} + +const AudioConfig_2_0 HidlToAidlMiddleware_2_0::GetAudioConfig( + const SessionType_2_0& session_type) { + return to_hidl_audio_config_2_0(BluetoothAudioSessionControl::GetAudioConfig( + from_session_type_2_0(session_type))); +} + +bool HidlToAidlMiddleware_2_0::StartStream( + const SessionType_2_0& session_type) { + return BluetoothAudioSessionControl::StartStream( + from_session_type_2_0(session_type)); +} + +void HidlToAidlMiddleware_2_0::StopStream(const SessionType_2_0& session_type) { + return BluetoothAudioSessionControl::StopStream( + from_session_type_2_0(session_type)); +} + +bool HidlToAidlMiddleware_2_0::SuspendStream( + const SessionType_2_0& session_type) { + return BluetoothAudioSessionControl::SuspendStream( + from_session_type_2_0(session_type)); +} + +bool HidlToAidlMiddleware_2_0::GetPresentationPosition( + const SessionType_2_0& session_type, uint64_t* remote_delay_report_ns, + uint64_t* total_bytes_readed, timespec* data_position) { + PresentationPosition presentation_position; + auto ret_val = BluetoothAudioSessionControl::GetPresentationPosition( + from_session_type_2_0(session_type), presentation_position); + if (remote_delay_report_ns) + *remote_delay_report_ns = presentation_position.remoteDeviceAudioDelayNanos; + if (total_bytes_readed) + *total_bytes_readed = presentation_position.transmittedOctets; + if (data_position) + *data_position = { + .tv_sec = static_cast<__kernel_old_time_t>( + presentation_position.transmittedOctetsTimestamp.tvSec), + .tv_nsec = static_cast<long>( + presentation_position.transmittedOctetsTimestamp.tvNSec)}; + return ret_val; +} + +void HidlToAidlMiddleware_2_0::UpdateTracksMetadata( + const SessionType_2_0& session_type, + const struct source_metadata* source_metadata) { + return BluetoothAudioSessionControl::UpdateSourceMetadata( + from_session_type_2_0(session_type), *source_metadata); +} + +size_t HidlToAidlMiddleware_2_0::OutWritePcmData( + const SessionType_2_0& session_type, const void* buffer, size_t bytes) { + return BluetoothAudioSessionControl::OutWritePcmData( + from_session_type_2_0(session_type), buffer, bytes); +} + +bool HidlToAidlMiddleware_2_0::IsAidlAvailable() { + return BluetoothAudioSession::IsAidlAvailable(); +} + +/*** + * + * 2.1 + * + ***/ + +const AudioConfig_2_1 HidlToAidlMiddleware_2_1::GetAudioConfig( + const SessionType_2_1& session_type) { + return to_hidl_audio_config_2_1(BluetoothAudioSessionControl::GetAudioConfig( + from_session_type_2_1(session_type))); +} + +/*** + * + * 2.2 + * + ***/ + +bool HidlToAidlMiddleware_2_2::IsSessionReady( + const SessionType_2_1& session_type) { + return BluetoothAudioSessionControl::IsSessionReady( + from_session_type_2_1(session_type)); +} + +uint16_t HidlToAidlMiddleware_2_2::RegisterControlResultCback( + const SessionType_2_1& session_type, + const PortStatusCallbacks_2_2& cbacks) { + LOG(INFO) << __func__ << ": " << toString(session_type); + auto aidl_session_type = from_session_type_2_1(session_type); + // Pass the exact reference to the lambda + auto& session_legacy_callback_table = + legacy_callback_table[aidl_session_type]; + PortStatusCallbacks aidl_callbacks{}; + if (cbacks.control_result_cb_) { + aidl_callbacks.control_result_cb_ = + [&session_legacy_callback_table](uint16_t cookie, bool start_resp, + const BluetoothAudioStatus& status) { + if (session_legacy_callback_table.find(cookie) == + session_legacy_callback_table.end()) { + LOG(ERROR) << __func__ << ": Unknown callback invoked!"; + return; + } + auto& cback = session_legacy_callback_table[cookie]; + cback->control_result_cb_(cookie, start_resp, to_hidl_status(status)); + }; + } + if (cbacks.session_changed_cb_) { + aidl_callbacks.session_changed_cb_ = + [&session_legacy_callback_table](uint16_t cookie) { + if (session_legacy_callback_table.find(cookie) == + session_legacy_callback_table.end()) { + LOG(ERROR) << __func__ << ": Unknown callback invoked!"; + return; + } + auto& cback = session_legacy_callback_table[cookie]; + cback->session_changed_cb_(cookie); + }; + }; + if (cbacks.audio_configuration_changed_cb_) { + aidl_callbacks.audio_configuration_changed_cb_ = + [&session_legacy_callback_table](uint16_t cookie) { + if (session_legacy_callback_table.find(cookie) == + session_legacy_callback_table.end()) { + LOG(ERROR) << __func__ << ": Unknown callback invoked!"; + return; + } + auto& cback = session_legacy_callback_table[cookie]; + cback->audio_configuration_changed_cb_(cookie); + }; + }; + auto cookie = BluetoothAudioSessionControl::RegisterControlResultCback( + aidl_session_type, aidl_callbacks); + { + std::lock_guard<std::mutex> guard(legacy_callback_lock); + session_legacy_callback_table[cookie] = + std::make_shared<PortStatusCallbacks_2_2>(cbacks); + } + return cookie; +} + +void HidlToAidlMiddleware_2_2::UnregisterControlResultCback( + const SessionType_2_1& session_type, uint16_t cookie) { + LOG(INFO) << __func__ << ": " << toString(session_type); + auto aidl_session_type = from_session_type_2_1(session_type); + BluetoothAudioSessionControl::UnregisterControlResultCback(aidl_session_type, + cookie); + auto& session_callback_table = legacy_callback_table[aidl_session_type]; + if (session_callback_table.find(cookie) != session_callback_table.end()) { + std::lock_guard<std::mutex> guard(legacy_callback_lock); + session_callback_table.erase(cookie); + } +} + +const AudioConfig_2_2 HidlToAidlMiddleware_2_2::GetAudioConfig( + const SessionType_2_1& session_type) { + return to_hidl_audio_config_2_2(BluetoothAudioSessionControl::GetAudioConfig( + from_session_type_2_1(session_type))); +} + +bool HidlToAidlMiddleware_2_2::StartStream( + const SessionType_2_1& session_type) { + return BluetoothAudioSessionControl::StartStream( + from_session_type_2_1(session_type)); +} + +bool HidlToAidlMiddleware_2_2::SuspendStream( + const SessionType_2_1& session_type) { + return BluetoothAudioSessionControl::SuspendStream( + from_session_type_2_1(session_type)); +} + +void HidlToAidlMiddleware_2_2::StopStream(const SessionType_2_1& session_type) { + return BluetoothAudioSessionControl::StopStream( + from_session_type_2_1(session_type)); +} + +void HidlToAidlMiddleware_2_2::UpdateSinkMetadata( + const SessionType_2_1& session_type, + const struct sink_metadata* sink_metadata) { + return BluetoothAudioSessionControl::UpdateSinkMetadata( + from_session_type_2_1(session_type), *sink_metadata); +} + +} // namespace audio +} // namespace bluetooth +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_0.h b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_0.h new file mode 100644 index 0000000000..d10ee3759a --- /dev/null +++ b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_0.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <android/hardware/bluetooth/audio/2.0/types.h> + +#include "../session/BluetoothAudioSession.h" + +namespace aidl { +namespace android { +namespace hardware { +namespace bluetooth { +namespace audio { + +using SessionType_2_0 = + ::android::hardware::bluetooth::audio::V2_0::SessionType; +using PortStatusCallbacks_2_0 = + ::android::bluetooth::audio::PortStatusCallbacks; +using AudioConfig_2_0 = + ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration; + +class HidlToAidlMiddleware_2_0 { + public: + static bool IsAidlAvailable(); + + static bool IsSessionReady(const SessionType_2_0& session_type); + + static uint16_t RegisterControlResultCback( + const SessionType_2_0& session_type, + const PortStatusCallbacks_2_0& cbacks); + + static void UnregisterControlResultCback(const SessionType_2_0& session_type, + uint16_t cookie); + + static const AudioConfig_2_0 GetAudioConfig( + const SessionType_2_0& session_type); + + static bool StartStream(const SessionType_2_0& session_type); + + static void StopStream(const SessionType_2_0& session_type); + + static bool SuspendStream(const SessionType_2_0& session_type); + + static bool GetPresentationPosition(const SessionType_2_0& session_type, + uint64_t* remote_delay_report_ns, + uint64_t* total_bytes_readed, + timespec* data_position); + + static void UpdateTracksMetadata( + const SessionType_2_0& session_type, + const struct source_metadata* source_metadata); + + static size_t OutWritePcmData(const SessionType_2_0& session_type, + const void* buffer, size_t bytes); +}; + +} // namespace audio +} // namespace bluetooth +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_1.h b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_1.h new file mode 100644 index 0000000000..82dce96d3e --- /dev/null +++ b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_1.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <android/hardware/bluetooth/audio/2.1/types.h> + +#include "../session/BluetoothAudioSession.h" + +namespace aidl { +namespace android { +namespace hardware { +namespace bluetooth { +namespace audio { + +using SessionType_2_1 = + ::android::hardware::bluetooth::audio::V2_1::SessionType; +using AudioConfig_2_1 = + ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration; + +class HidlToAidlMiddleware_2_1 { + public: + static const AudioConfig_2_1 GetAudioConfig( + const SessionType_2_1& session_type); +}; + +} // namespace audio +} // namespace bluetooth +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_2.h b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_2.h new file mode 100644 index 0000000000..149e4042d1 --- /dev/null +++ b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_2.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <android/hardware/bluetooth/audio/2.2/types.h> + +#include "../session/BluetoothAudioSession.h" +#include "../session/BluetoothAudioSession_2_2.h" + +namespace aidl { +namespace android { +namespace hardware { +namespace bluetooth { +namespace audio { + +using SessionType_2_1 = + ::android::hardware::bluetooth::audio::V2_1::SessionType; +using PortStatusCallbacks_2_0 = + ::android::bluetooth::audio::PortStatusCallbacks; +using PortStatusCallbacks_2_2 = + ::android::bluetooth::audio::PortStatusCallbacks_2_2; +using AudioConfig_2_2 = + ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration; + +class HidlToAidlMiddleware_2_2 { + public: + static bool IsSessionReady(const SessionType_2_1& session_type); + + static uint16_t RegisterControlResultCback( + const SessionType_2_1& session_type, + const PortStatusCallbacks_2_2& cbacks); + + static void UnregisterControlResultCback(const SessionType_2_1& session_type, + uint16_t cookie); + + static const AudioConfig_2_2 GetAudioConfig( + const SessionType_2_1& session_type); + + static bool StartStream(const SessionType_2_1& session_type); + + static bool SuspendStream(const SessionType_2_1& session_type); + + static void StopStream(const SessionType_2_1& session_type); + + static void UpdateSinkMetadata(const SessionType_2_1& session_type, + const struct sink_metadata* sink_metadata); +}; + +} // namespace audio +} // namespace bluetooth +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession.cpp b/bluetooth/audio/utils/session/BluetoothAudioSession.cpp index 2f3ddaf213..6d5608b0a4 100644 --- a/bluetooth/audio/utils/session/BluetoothAudioSession.cpp +++ b/bluetooth/audio/utils/session/BluetoothAudioSession.cpp @@ -21,10 +21,13 @@ #include <android-base/logging.h> #include <android-base/stringprintf.h> +#include "../aidl_session/HidlToAidlMiddleware_2_0.h" + namespace android { namespace bluetooth { namespace audio { +using ::aidl::android::hardware::bluetooth::audio::HidlToAidlMiddleware_2_0; using ::android::hardware::audio::common::V5_0::AudioContentType; using ::android::hardware::audio::common::V5_0::AudioUsage; using ::android::hardware::audio::common::V5_0::PlaybackTrackMetadata; @@ -149,6 +152,8 @@ void BluetoothAudioSession::ReportControlStatus( // The function helps to check if this session is ready or not // @return: true if the Bluetooth stack has started the specified session bool BluetoothAudioSession::IsSessionReady() { + if (HidlToAidlMiddleware_2_0::IsAidlAvailable()) + return HidlToAidlMiddleware_2_0::IsSessionReady(session_type_); std::lock_guard<std::recursive_mutex> guard(mutex_); bool dataMQ_valid = (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH || @@ -200,6 +205,9 @@ bool BluetoothAudioSession::UpdateAudioConfig( // @return: cookie - the assigned number to this bluetooth_audio output uint16_t BluetoothAudioSession::RegisterStatusCback( const PortStatusCallbacks& cbacks) { + if (HidlToAidlMiddleware_2_0::IsAidlAvailable()) + return HidlToAidlMiddleware_2_0::RegisterControlResultCback(session_type_, + cbacks); std::lock_guard<std::recursive_mutex> guard(mutex_); uint16_t cookie = ObserversCookieGetInitValue(session_type_); uint16_t cookie_upper_bound = ObserversCookieGetUpperBound(session_type_); @@ -227,6 +235,9 @@ uint16_t BluetoothAudioSession::RegisterStatusCback( // PortStatusCallbacks // @param: cookie - indicates which bluetooth_audio output is void BluetoothAudioSession::UnregisterStatusCback(uint16_t cookie) { + if (HidlToAidlMiddleware_2_0::IsAidlAvailable()) + return HidlToAidlMiddleware_2_0::UnregisterControlResultCback(session_type_, + cookie); std::lock_guard<std::recursive_mutex> guard(mutex_); if (observers_.erase(cookie) != 1) { LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_) @@ -238,6 +249,9 @@ void BluetoothAudioSession::UnregisterStatusCback(uint16_t cookie) { // The control function is for the bluetooth_audio module to get the current // AudioConfiguration const AudioConfiguration& BluetoothAudioSession::GetAudioConfig() { + if (HidlToAidlMiddleware_2_0::IsAidlAvailable()) + return (audio_config_ = + HidlToAidlMiddleware_2_0::GetAudioConfig(session_type_)); std::lock_guard<std::recursive_mutex> guard(mutex_); if (IsSessionReady()) { return audio_config_; @@ -251,6 +265,8 @@ const AudioConfiguration& BluetoothAudioSession::GetAudioConfig() { // Those control functions are for the bluetooth_audio module to start, suspend, // stop stream, to check position, and to update metadata. bool BluetoothAudioSession::StartStream() { + if (HidlToAidlMiddleware_2_0::IsAidlAvailable()) + return HidlToAidlMiddleware_2_0::StartStream(session_type_); std::lock_guard<std::recursive_mutex> guard(mutex_); if (!IsSessionReady()) { LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_) @@ -267,6 +283,8 @@ bool BluetoothAudioSession::StartStream() { } bool BluetoothAudioSession::SuspendStream() { + if (HidlToAidlMiddleware_2_0::IsAidlAvailable()) + return HidlToAidlMiddleware_2_0::SuspendStream(session_type_); std::lock_guard<std::recursive_mutex> guard(mutex_); if (!IsSessionReady()) { LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_) @@ -283,6 +301,8 @@ bool BluetoothAudioSession::SuspendStream() { } void BluetoothAudioSession::StopStream() { + if (HidlToAidlMiddleware_2_0::IsAidlAvailable()) + return HidlToAidlMiddleware_2_0::StopStream(session_type_); std::lock_guard<std::recursive_mutex> guard(mutex_); if (!IsSessionReady()) { return; @@ -297,6 +317,10 @@ void BluetoothAudioSession::StopStream() { bool BluetoothAudioSession::GetPresentationPosition( uint64_t* remote_delay_report_ns, uint64_t* total_bytes_readed, timespec* data_position) { + if (HidlToAidlMiddleware_2_0::IsAidlAvailable()) + return HidlToAidlMiddleware_2_0::GetPresentationPosition( + session_type_, remote_delay_report_ns, total_bytes_readed, + data_position); std::lock_guard<std::recursive_mutex> guard(mutex_); if (!IsSessionReady()) { LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_) @@ -330,6 +354,9 @@ bool BluetoothAudioSession::GetPresentationPosition( void BluetoothAudioSession::UpdateTracksMetadata( const struct source_metadata* source_metadata) { + if (HidlToAidlMiddleware_2_0::IsAidlAvailable()) + return HidlToAidlMiddleware_2_0::UpdateTracksMetadata(session_type_, + source_metadata); std::lock_guard<std::recursive_mutex> guard(mutex_); if (!IsSessionReady()) { LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_) @@ -374,6 +401,9 @@ void BluetoothAudioSession::UpdateTracksMetadata( // The control function writes stream to FMQ size_t BluetoothAudioSession::OutWritePcmData(const void* buffer, size_t bytes) { + if (HidlToAidlMiddleware_2_0::IsAidlAvailable()) + return HidlToAidlMiddleware_2_0::OutWritePcmData(session_type_, buffer, + bytes); if (buffer == nullptr || !bytes) return 0; size_t totalWritten = 0; int ms_timeout = kFmqSendTimeoutMs; diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp index bf1f9b5b2a..276a291470 100644 --- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp +++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp @@ -21,9 +21,14 @@ #include <android-base/logging.h> #include <android-base/stringprintf.h> +#include "../aidl_session/HidlToAidlMiddleware_2_0.h" +#include "../aidl_session/HidlToAidlMiddleware_2_1.h" + namespace android { namespace bluetooth { namespace audio { +using ::aidl::android::hardware::bluetooth::audio::HidlToAidlMiddleware_2_0; +using ::aidl::android::hardware::bluetooth::audio::HidlToAidlMiddleware_2_1; using SessionType_2_1 = ::android::hardware::bluetooth::audio::V2_1::SessionType; using SessionType_2_0 = @@ -72,6 +77,7 @@ BluetoothAudioSession_2_1::BluetoothAudioSession_2_1( } else { session_type_2_1_ = (session_type); } + raw_session_type_ = session_type; } std::shared_ptr<BluetoothAudioSession> @@ -83,6 +89,8 @@ BluetoothAudioSession_2_1::GetAudioSession() { // AudioConfiguration const ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration BluetoothAudioSession_2_1::GetAudioConfig() { + if (HidlToAidlMiddleware_2_0::IsAidlAvailable()) + return HidlToAidlMiddleware_2_1::GetAudioConfig(raw_session_type_); std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_); if (audio_session->IsSessionReady()) { // If session is unknown it means it should be 2.0 type diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h index 5a351531a3..e6340649d8 100644 --- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h +++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h @@ -31,6 +31,7 @@ class BluetoothAudioSession_2_1 { std::shared_ptr<BluetoothAudioSession> audio_session; ::android::hardware::bluetooth::audio::V2_1::SessionType session_type_2_1_; + ::android::hardware::bluetooth::audio::V2_1::SessionType raw_session_type_; // audio data configuration for both software and offloading ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp index 60ac4ece6f..4613ddc05a 100644 --- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp +++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp @@ -22,10 +22,15 @@ #include <android-base/stringprintf.h> #include <android/hardware/bluetooth/audio/2.2/IBluetoothAudioPort.h> +#include "../aidl_session/HidlToAidlMiddleware_2_0.h" +#include "../aidl_session/HidlToAidlMiddleware_2_2.h" + namespace android { namespace bluetooth { namespace audio { +using ::aidl::android::hardware::bluetooth::audio::HidlToAidlMiddleware_2_0; +using ::aidl::android::hardware::bluetooth::audio::HidlToAidlMiddleware_2_2; using ::android::hardware::audio::common::V5_0::AudioSource; using ::android::hardware::audio::common::V5_0::RecordTrackMetadata; using ::android::hardware::audio::common::V5_0::SinkMetadata; @@ -93,6 +98,7 @@ BluetoothAudioSession_2_2::BluetoothAudioSession_2_2( } else { session_type_2_1_ = (session_type); } + raw_session_type_ = session_type; invalidSoftwareAudioConfiguration.pcmConfig(kInvalidPcmParameters); invalidOffloadAudioConfiguration.codecConfig( audio_session->kInvalidCodecConfiguration); @@ -100,6 +106,8 @@ BluetoothAudioSession_2_2::BluetoothAudioSession_2_2( } bool BluetoothAudioSession_2_2::IsSessionReady() { + if (HidlToAidlMiddleware_2_0::IsAidlAvailable()) + return HidlToAidlMiddleware_2_2::IsSessionReady(raw_session_type_); if (session_type_2_1_ != SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH && session_type_2_1_ != @@ -122,6 +130,9 @@ BluetoothAudioSession_2_2::GetAudioSession_2_1() { void BluetoothAudioSession_2_2::UpdateSinkMetadata( const struct sink_metadata* sink_metadata) { + if (HidlToAidlMiddleware_2_0::IsAidlAvailable()) + return HidlToAidlMiddleware_2_2::UpdateSinkMetadata(raw_session_type_, + sink_metadata); std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_); if (!IsSessionReady()) { LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_2_1_) @@ -172,6 +183,8 @@ void BluetoothAudioSession_2_2::UpdateSinkMetadata( // AudioConfiguration const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration BluetoothAudioSession_2_2::GetAudioConfig() { + if (HidlToAidlMiddleware_2_0::IsAidlAvailable()) + return HidlToAidlMiddleware_2_2::GetAudioConfig(raw_session_type_); std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_); if (IsSessionReady()) { auto audio_config_discriminator = audio_config_2_2_.getDiscriminator(); @@ -226,6 +239,8 @@ BluetoothAudioSession_2_2::GetAudioConfig() { // Those control functions are for the bluetooth_audio module to start, suspend, // stop stream, to check position, and to update metadata. bool BluetoothAudioSession_2_2::StartStream() { + if (HidlToAidlMiddleware_2_0::IsAidlAvailable()) + return HidlToAidlMiddleware_2_2::StartStream(raw_session_type_); std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_); if (!IsSessionReady()) { LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_2_1_) @@ -242,6 +257,8 @@ bool BluetoothAudioSession_2_2::StartStream() { } bool BluetoothAudioSession_2_2::SuspendStream() { + if (HidlToAidlMiddleware_2_0::IsAidlAvailable()) + return HidlToAidlMiddleware_2_2::SuspendStream(raw_session_type_); std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_); if (!IsSessionReady()) { LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_2_1_) @@ -258,6 +275,8 @@ bool BluetoothAudioSession_2_2::SuspendStream() { } void BluetoothAudioSession_2_2::StopStream() { + if (HidlToAidlMiddleware_2_0::IsAidlAvailable()) + return HidlToAidlMiddleware_2_2::StopStream(raw_session_type_); std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_); if (!IsSessionReady()) { return; @@ -395,6 +414,9 @@ void BluetoothAudioSession_2_2::OnSessionEnded() { // @return: cookie - the assigned number to this bluetooth_audio output uint16_t BluetoothAudioSession_2_2::RegisterStatusCback( const PortStatusCallbacks_2_2& cbacks) { + if (HidlToAidlMiddleware_2_0::IsAidlAvailable()) + return HidlToAidlMiddleware_2_2::RegisterControlResultCback( + raw_session_type_, cbacks); if (session_type_2_1_ != SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH && session_type_2_1_ != @@ -432,6 +454,9 @@ uint16_t BluetoothAudioSession_2_2::RegisterStatusCback( // PortStatusCallbacks_2_2 // @param: cookie - indicates which bluetooth_audio output is void BluetoothAudioSession_2_2::UnregisterStatusCback(uint16_t cookie) { + if (HidlToAidlMiddleware_2_0::IsAidlAvailable()) + return HidlToAidlMiddleware_2_2::UnregisterControlResultCback( + raw_session_type_, cookie); std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_); if (session_type_2_1_ != SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH && diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h index 3673fd8ccf..b6f96ab25c 100644 --- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h +++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h @@ -68,6 +68,7 @@ class BluetoothAudioSession_2_2 { std::shared_ptr<BluetoothAudioSession_2_1> audio_session_2_1; ::android::hardware::bluetooth::audio::V2_1::SessionType session_type_2_1_; + ::android::hardware::bluetooth::audio::V2_1::SessionType raw_session_type_; // audio data configuration for both software and offloading ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration diff --git a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.cpp b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.cpp index 34cfd7efb7..4c99b0f620 100644 --- a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.cpp +++ b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.cpp @@ -30,16 +30,20 @@ using ::android::hardware::bluetooth::audio::V2_1::Lc3FrameDuration; using ::android::hardware::bluetooth::audio::V2_1::Lc3Parameters; using ::android::hardware::bluetooth::audio::V2_1::SampleRate; using ::android::hardware::bluetooth::audio::V2_2::AudioLocation; -using ::android::hardware::bluetooth::audio::V2_2::LeAudioCodecCapabilitiesPair; -using ::android::hardware::bluetooth::audio::V2_2::LeAudioCodecCapability; -using ::android::hardware::bluetooth::audio::V2_2::LeAudioMode; +using ::android::hardware::bluetooth::audio::V2_2::BroadcastCapability; +using ::android::hardware::bluetooth::audio::V2_2:: + LeAudioCodecCapabilitiesSetting; +using ::android::hardware::bluetooth::audio::V2_2::UnicastCapability; using SessionType_2_1 = ::android::hardware::bluetooth::audio::V2_1::SessionType; // Stores the list of offload supported capability -std::vector<LeAudioCodecCapabilitiesPair> kDefaultOffloadLeAudioCapabilities; +std::vector<LeAudioCodecCapabilitiesSetting> kDefaultOffloadLeAudioCapabilities; -static const LeAudioCodecCapability kInvalidLc3Capability = { +static const UnicastCapability kInvalidUnicastCapability = { + .codecType = CodecType::UNKNOWN}; + +static const BroadcastCapability kInvalidBroadcastCapability = { .codecType = CodecType::UNKNOWN}; // Default Supported Codecs @@ -94,53 +98,53 @@ bool IsOffloadLeAudioConfigurationValid( return true; } -LeAudioCodecCapability composeLc3Capability(AudioLocation audioLocation, - uint8_t deviceCnt, - uint8_t channelCount, - Lc3Parameters capability) { - return LeAudioCodecCapability{.codecType = CodecType::LC3, - .supportedChannel = audioLocation, - .deviceCount = deviceCnt, - .channelCountPerDevice = channelCount, - .capabilities = capability}; +UnicastCapability composeUnicastLc3Capability(AudioLocation audioLocation, + uint8_t deviceCnt, + uint8_t channelCount, + Lc3Parameters capability) { + return UnicastCapability{.codecType = CodecType::LC3, + .supportedChannel = audioLocation, + .deviceCount = deviceCnt, + .channelCountPerDevice = channelCount, + .capabilities = capability}; } -std::vector<LeAudioCodecCapabilitiesPair> GetLeAudioOffloadCodecCapabilities( +std::vector<LeAudioCodecCapabilitiesSetting> GetLeAudioOffloadCodecCapabilities( const SessionType_2_1& session_type) { if (session_type != SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH && session_type != SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) { - return std::vector<LeAudioCodecCapabilitiesPair>(0); + return std::vector<LeAudioCodecCapabilitiesSetting>(0); } if (kDefaultOffloadLeAudioCapabilities.empty()) { for (auto [audioLocation, deviceCnt, channelCount] : supportedDeviceSetting) { for (auto capability : supportedLc3CapabilityList) { - LeAudioCodecCapability lc3Capability = composeLc3Capability( + UnicastCapability lc3Capability = composeUnicastLc3Capability( audioLocation, deviceCnt, channelCount, capability); - LeAudioCodecCapability lc3MonoCapability = - composeLc3Capability(monoAudio, 1, 1, capability); + UnicastCapability lc3MonoDecodeCapability = + composeUnicastLc3Capability(monoAudio, 1, 1, capability); // Adds the capability for encode only kDefaultOffloadLeAudioCapabilities.push_back( - {.mode = LeAudioMode::UNICAST, - .encodeCapability = lc3Capability, - .decodeCapability = kInvalidLc3Capability}); + {.unicastEncodeCapability = lc3Capability, + .unicastDecodeCapability = kInvalidUnicastCapability, + .broadcastCapability = kInvalidBroadcastCapability}); // Adds the capability for decode only kDefaultOffloadLeAudioCapabilities.push_back( - {.mode = LeAudioMode::UNICAST, - .encodeCapability = kInvalidLc3Capability, - .decodeCapability = lc3Capability}); + {.unicastEncodeCapability = kInvalidUnicastCapability, + .unicastDecodeCapability = lc3Capability, + .broadcastCapability = kInvalidBroadcastCapability}); // Adds the capability for the case that encode and decode exist at the // same time kDefaultOffloadLeAudioCapabilities.push_back( - {.mode = LeAudioMode::UNICAST, - .encodeCapability = lc3Capability, - .decodeCapability = lc3MonoCapability}); + {.unicastEncodeCapability = lc3Capability, + .unicastDecodeCapability = lc3MonoDecodeCapability, + .broadcastCapability = kInvalidBroadcastCapability}); } } } diff --git a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.h index 89da6a383f..34bba5f671 100644 --- a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.h +++ b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.h @@ -31,7 +31,7 @@ bool IsOffloadLeAudioConfigurationValid( const ::android::hardware::bluetooth::audio::V2_2::LeAudioConfiguration& le_audio_codec_config); -std::vector<hardware::bluetooth::audio::V2_2::LeAudioCodecCapabilitiesPair> +std::vector<hardware::bluetooth::audio::V2_2::LeAudioCodecCapabilitiesSetting> GetLeAudioOffloadCodecCapabilities( const ::android::hardware::bluetooth::audio::V2_1::SessionType& session_type); |