633 lines
24 KiB
C++
633 lines
24 KiB
C++
|
/*
|
||
|
* 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"
|
||
|
|
||
|
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;
|
||
|
|
||
|
std::mutex legacy_callback_lock;
|
||
|
std::unordered_map<
|
||
|
SessionType,
|
||
|
std::unordered_map<uint16_t, std::shared_ptr<PortStatusCallbacks_2_0>>>
|
||
|
legacy_callback_table;
|
||
|
|
||
|
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_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},
|
||
|
};
|
||
|
|
||
|
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 SessionType from_session_type_2_0(
|
||
|
const SessionType_2_0& session_type_hidl) {
|
||
|
return from_session_type_2_1(static_cast<SessionType_2_1>(session_type_hidl));
|
||
|
}
|
||
|
|
||
|
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_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 SampleRate_2_0 to_hidl_sample_rate_2_0(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 static_cast<SampleRate_2_0>(it->second);
|
||
|
return SampleRate_2_0::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& unicast_config) {
|
||
|
Lc3CodecConfig_2_1 hidl_lc3_codec_config = {
|
||
|
.audioChannelAllocation = 0,
|
||
|
};
|
||
|
if (unicast_config.leAudioCodecConfig.getTag() ==
|
||
|
LeAudioCodecConfiguration::lc3Config) {
|
||
|
LOG(FATAL) << __func__ << ": unexpected codec type(vendor?)";
|
||
|
}
|
||
|
auto& le_codec_config = unicast_config.leAudioCodecConfig
|
||
|
.get<LeAudioCodecConfiguration::lc3Config>();
|
||
|
|
||
|
hidl_lc3_codec_config.lc3Config = to_hidl_lc3_config_2_1(le_codec_config);
|
||
|
|
||
|
for (const auto& map : unicast_config.streamMap) {
|
||
|
hidl_lc3_codec_config.audioChannelAllocation |= map.audioChannelAllocation;
|
||
|
}
|
||
|
return hidl_lc3_codec_config;
|
||
|
}
|
||
|
|
||
|
inline Lc3CodecConfig_2_1 to_hidl_leaudio_broadcast_config_2_1(
|
||
|
const LeAudioBroadcastConfiguration& broadcast_config) {
|
||
|
Lc3CodecConfig_2_1 hidl_lc3_codec_config = {
|
||
|
.audioChannelAllocation = 0,
|
||
|
};
|
||
|
// NOTE: Broadcast is not officially supported in HIDL
|
||
|
if (broadcast_config.streamMap.empty()) {
|
||
|
return hidl_lc3_codec_config;
|
||
|
}
|
||
|
if (broadcast_config.streamMap[0].leAudioCodecConfig.getTag() !=
|
||
|
LeAudioCodecConfiguration::lc3Config) {
|
||
|
LOG(FATAL) << __func__ << ": unexpected codec type(vendor?)";
|
||
|
}
|
||
|
auto& le_codec_config =
|
||
|
broadcast_config.streamMap[0]
|
||
|
.leAudioCodecConfig.get<LeAudioCodecConfiguration::lc3Config>();
|
||
|
hidl_lc3_codec_config.lc3Config = to_hidl_lc3_config_2_1(le_codec_config);
|
||
|
|
||
|
for (const auto& map : broadcast_config.streamMap) {
|
||
|
hidl_lc3_codec_config.audioChannelAllocation |= map.audioChannelAllocation;
|
||
|
}
|
||
|
return hidl_lc3_codec_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;
|
||
|
case AudioConfiguration::leAudioBroadcastConfig:
|
||
|
hidl_audio_config.leAudioCodecConfig(to_hidl_leaudio_broadcast_config_2_1(
|
||
|
audio_config.get<AudioConfiguration::leAudioBroadcastConfig>()));
|
||
|
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) {
|
||
|
LOG(INFO) << __func__ << ": " << toString(session_type);
|
||
|
auto aidl_session_type = from_session_type_2_0(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);
|
||
|
};
|
||
|
};
|
||
|
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_0>(cbacks);
|
||
|
}
|
||
|
return cookie;
|
||
|
}
|
||
|
|
||
|
void HidlToAidlMiddleware_2_0::UnregisterControlResultCback(
|
||
|
const SessionType_2_0& session_type, uint16_t cookie) {
|
||
|
LOG(INFO) << __func__ << ": " << toString(session_type);
|
||
|
auto aidl_session_type = from_session_type_2_0(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_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);
|
||
|
}
|
||
|
|
||
|
size_t HidlToAidlMiddleware_2_0::InReadPcmData(
|
||
|
const SessionType_2_0& session_type, void* buffer, size_t bytes) {
|
||
|
return BluetoothAudioSessionControl::InReadPcmData(
|
||
|
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)));
|
||
|
}
|
||
|
|
||
|
} // namespace audio
|
||
|
} // namespace bluetooth
|
||
|
} // namespace hardware
|
||
|
} // namespace android
|
||
|
} // namespace aidl
|