Merge "Expose different offload audio capabilities by project" am: 449d7b0f67
am: 464cbaa8f2
am: 67aed07877
Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/2207308 Change-Id: I362fc71e3631fd3296850c319799bf072769e7a6 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
commit
f14b884e6b
10 changed files with 665 additions and 110 deletions
|
@ -40,9 +40,13 @@ cc_library_shared {
|
|||
"aidl_session/BluetoothAudioCodecs.cpp",
|
||||
"aidl_session/BluetoothAudioSession.cpp",
|
||||
"aidl_session/HidlToAidlMiddleware.cpp",
|
||||
"aidl_session/BluetoothLeAudioCodecsProvider.cpp",
|
||||
],
|
||||
export_include_dirs: ["aidl_session/"],
|
||||
header_libs: ["libhardware_headers"],
|
||||
header_libs: [
|
||||
"libhardware_headers",
|
||||
"libxsdc-utils",
|
||||
],
|
||||
shared_libs: [
|
||||
"android.hardware.bluetooth.audio@2.0",
|
||||
"android.hardware.bluetooth.audio@2.1",
|
||||
|
@ -53,5 +57,15 @@ cc_library_shared {
|
|||
"liblog",
|
||||
"android.hardware.bluetooth.audio-V2-ndk",
|
||||
"libhidlbase",
|
||||
"libxml2",
|
||||
],
|
||||
generated_sources: ["le_audio_codec_capabilities"],
|
||||
generated_headers: ["le_audio_codec_capabilities"],
|
||||
}
|
||||
|
||||
xsd_config {
|
||||
name: "le_audio_codec_capabilities",
|
||||
srcs: ["le_audio_codec_capabilities/le_audio_codec_capabilities.xsd"],
|
||||
package_name: "aidl.android.hardware.bluetooth.audio.setting",
|
||||
api_dir: "le_audio_codec_capabilities/schema",
|
||||
}
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include <aidl/android/hardware/bluetooth/audio/SbcChannelMode.h>
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include "BluetoothLeAudioCodecsProvider.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
|
@ -96,67 +98,6 @@ const std::vector<CodecCapabilities> kDefaultOffloadA2dpCodecCapabilities = {
|
|||
|
||||
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 24_2: sample rate: 24 kHz, frame duration: 10 ms, octets per frame: 60
|
||||
static const Lc3Capabilities kLc3Capability_24_2 = {
|
||||
.samplingFrequencyHz = {24000},
|
||||
.frameDurationUs = {10000},
|
||||
.octetsPerFrame = {60}};
|
||||
|
||||
// Default Supported Codecs
|
||||
// LC3 32_2: sample rate: 32 kHz, frame duration: 10 ms, octets per frame: 80
|
||||
static const Lc3Capabilities kLc3Capability_32_2 = {
|
||||
.samplingFrequencyHz = {32000},
|
||||
.frameDurationUs = {10000},
|
||||
.octetsPerFrame = {80}};
|
||||
|
||||
// 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_32_2, kLc3Capability_24_2,
|
||||
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 = {
|
||||
// Stereo, two connected device, one for L one for R
|
||||
std::make_tuple(stereoAudio, 2, 1),
|
||||
// Stereo, one connected device for both L and R
|
||||
std::make_tuple(stereoAudio, 1, 2),
|
||||
// Mono
|
||||
std::make_tuple(monoAudio, 1, 1)};
|
||||
|
||||
template <class T>
|
||||
bool BluetoothAudioCodecs::ContainedInVector(
|
||||
const std::vector<T>& vector, const typename identity<T>::type& target) {
|
||||
|
@ -444,19 +385,6 @@ bool BluetoothAudioCodecs::IsOffloadCodecConfigurationValid(
|
|||
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) {
|
||||
|
@ -470,41 +398,8 @@ BluetoothAudioCodecs::GetLeAudioOffloadCodecCapabilities(
|
|||
}
|
||||
|
||||
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(force one active device for decode)
|
||||
kDefaultOffloadLeAudioCapabilities.push_back(
|
||||
{.unicastEncodeCapability = lc3Capability,
|
||||
.unicastDecodeCapability = lc3MonoDecodeCapability,
|
||||
.broadcastCapability = kInvalidBroadcastCapability});
|
||||
|
||||
// Adds the capability for the case that encode and decode exist at the
|
||||
// same time
|
||||
kDefaultOffloadLeAudioCapabilities.push_back(
|
||||
{.unicastEncodeCapability = lc3Capability,
|
||||
.unicastDecodeCapability = lc3Capability,
|
||||
.broadcastCapability = kInvalidBroadcastCapability});
|
||||
}
|
||||
}
|
||||
kDefaultOffloadLeAudioCapabilities =
|
||||
BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities();
|
||||
}
|
||||
|
||||
return kDefaultOffloadLeAudioCapabilities;
|
||||
|
|
|
@ -0,0 +1,312 @@
|
|||
/*
|
||||
* 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 "BTAudioCodecsProviderAidl"
|
||||
|
||||
#include "BluetoothLeAudioCodecsProvider.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
|
||||
static const char* kLeAudioCodecCapabilitiesFile =
|
||||
"/vendor/etc/le_audio_codec_capabilities.xml";
|
||||
|
||||
static const AudioLocation kStereoAudio = static_cast<AudioLocation>(
|
||||
static_cast<uint8_t>(AudioLocation::FRONT_LEFT) |
|
||||
static_cast<uint8_t>(AudioLocation::FRONT_RIGHT));
|
||||
static const AudioLocation kMonoAudio = AudioLocation::UNKNOWN;
|
||||
|
||||
static std::vector<LeAudioCodecCapabilitiesSetting> leAudioCodecCapabilities;
|
||||
|
||||
std::vector<LeAudioCodecCapabilitiesSetting>
|
||||
BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities() {
|
||||
if (!leAudioCodecCapabilities.empty()) {
|
||||
return leAudioCodecCapabilities;
|
||||
}
|
||||
|
||||
const auto le_audio_offload_setting =
|
||||
setting::readLeAudioOffloadSetting(kLeAudioCodecCapabilitiesFile);
|
||||
if (!le_audio_offload_setting.has_value()) {
|
||||
LOG(ERROR) << __func__ << ": Failed to read "
|
||||
<< kLeAudioCodecCapabilitiesFile;
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<setting::Scenario> supported_scenarios =
|
||||
GetScenarios(le_audio_offload_setting);
|
||||
if (supported_scenarios.empty()) {
|
||||
LOG(ERROR) << __func__ << ": No scenarios in "
|
||||
<< kLeAudioCodecCapabilitiesFile;
|
||||
return {};
|
||||
}
|
||||
|
||||
UpdateConfigurationsToMap(le_audio_offload_setting);
|
||||
if (configuration_map_.empty()) {
|
||||
LOG(ERROR) << __func__ << ": No configurations in "
|
||||
<< kLeAudioCodecCapabilitiesFile;
|
||||
return {};
|
||||
}
|
||||
|
||||
UpdateCodecConfigurationsToMap(le_audio_offload_setting);
|
||||
if (codec_configuration_map_.empty()) {
|
||||
LOG(ERROR) << __func__ << ": No codec configurations in "
|
||||
<< kLeAudioCodecCapabilitiesFile;
|
||||
return {};
|
||||
}
|
||||
|
||||
UpdateStrategyConfigurationsToMap(le_audio_offload_setting);
|
||||
if (strategy_configuration_map_.empty()) {
|
||||
LOG(ERROR) << __func__ << ": No strategy configurations in "
|
||||
<< kLeAudioCodecCapabilitiesFile;
|
||||
return {};
|
||||
}
|
||||
|
||||
leAudioCodecCapabilities =
|
||||
ComposeLeAudioCodecCapabilities(supported_scenarios);
|
||||
return leAudioCodecCapabilities;
|
||||
}
|
||||
|
||||
std::vector<setting::Scenario> BluetoothLeAudioCodecsProvider::GetScenarios(
|
||||
const std::optional<setting::LeAudioOffloadSetting>&
|
||||
le_audio_offload_setting) {
|
||||
std::vector<setting::Scenario> supported_scenarios;
|
||||
if (le_audio_offload_setting->hasScenarioList()) {
|
||||
for (const auto& scenario_list :
|
||||
le_audio_offload_setting->getScenarioList()) {
|
||||
if (!scenario_list.hasScenario()) {
|
||||
continue;
|
||||
}
|
||||
for (const auto& scenario : scenario_list.getScenario()) {
|
||||
if (scenario.hasEncode() && scenario.hasDecode()) {
|
||||
supported_scenarios.push_back(scenario);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return supported_scenarios;
|
||||
}
|
||||
|
||||
void BluetoothLeAudioCodecsProvider::UpdateConfigurationsToMap(
|
||||
const std::optional<setting::LeAudioOffloadSetting>&
|
||||
le_audio_offload_setting) {
|
||||
if (le_audio_offload_setting->hasConfigurationList()) {
|
||||
for (const auto& configuration_list :
|
||||
le_audio_offload_setting->getConfigurationList()) {
|
||||
if (!configuration_list.hasConfiguration()) {
|
||||
continue;
|
||||
}
|
||||
for (const auto& configuration : configuration_list.getConfiguration()) {
|
||||
if (configuration.hasName() && configuration.hasCodecConfiguration() &&
|
||||
configuration.hasStrategyConfiguration()) {
|
||||
configuration_map_.insert(
|
||||
make_pair(configuration.getName(), configuration));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BluetoothLeAudioCodecsProvider::UpdateCodecConfigurationsToMap(
|
||||
const std::optional<setting::LeAudioOffloadSetting>&
|
||||
le_audio_offload_setting) {
|
||||
if (le_audio_offload_setting->hasCodecConfigurationList()) {
|
||||
for (const auto& codec_configuration_list :
|
||||
le_audio_offload_setting->getCodecConfigurationList()) {
|
||||
if (!codec_configuration_list.hasCodecConfiguration()) {
|
||||
continue;
|
||||
}
|
||||
for (const auto& codec_configuration :
|
||||
codec_configuration_list.getCodecConfiguration()) {
|
||||
if (IsValidCodecConfiguration(codec_configuration)) {
|
||||
codec_configuration_map_.insert(
|
||||
make_pair(codec_configuration.getName(), codec_configuration));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BluetoothLeAudioCodecsProvider::UpdateStrategyConfigurationsToMap(
|
||||
const std::optional<setting::LeAudioOffloadSetting>&
|
||||
le_audio_offload_setting) {
|
||||
if (le_audio_offload_setting->hasStrategyConfigurationList()) {
|
||||
for (const auto& strategy_configuration_list :
|
||||
le_audio_offload_setting->getStrategyConfigurationList()) {
|
||||
if (!strategy_configuration_list.hasStrategyConfiguration()) {
|
||||
continue;
|
||||
}
|
||||
for (const auto& strategy_configuration :
|
||||
strategy_configuration_list.getStrategyConfiguration()) {
|
||||
if (IsValidStrategyConfiguration(strategy_configuration)) {
|
||||
strategy_configuration_map_.insert(make_pair(
|
||||
strategy_configuration.getName(), strategy_configuration));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<LeAudioCodecCapabilitiesSetting>
|
||||
BluetoothLeAudioCodecsProvider::ComposeLeAudioCodecCapabilities(
|
||||
const std::vector<setting::Scenario>& supported_scenarios) {
|
||||
std::vector<LeAudioCodecCapabilitiesSetting> le_audio_codec_capabilities;
|
||||
for (const auto& scenario : supported_scenarios) {
|
||||
UnicastCapability unicast_encode_capability =
|
||||
GetUnicastCapability(scenario.getEncode());
|
||||
UnicastCapability unicast_decode_capability =
|
||||
GetUnicastCapability(scenario.getDecode());
|
||||
// encode and decode cannot be unknown at the same time
|
||||
if (unicast_encode_capability.codecType == CodecType::UNKNOWN &&
|
||||
unicast_decode_capability.codecType == CodecType::UNKNOWN) {
|
||||
continue;
|
||||
}
|
||||
BroadcastCapability broadcast_capability = {.codecType =
|
||||
CodecType::UNKNOWN};
|
||||
le_audio_codec_capabilities.push_back(
|
||||
{.unicastEncodeCapability = unicast_encode_capability,
|
||||
.unicastDecodeCapability = unicast_decode_capability,
|
||||
.broadcastCapability = broadcast_capability});
|
||||
}
|
||||
return le_audio_codec_capabilities;
|
||||
}
|
||||
|
||||
UnicastCapability BluetoothLeAudioCodecsProvider::GetUnicastCapability(
|
||||
const std::string& coding_direction) {
|
||||
if (coding_direction == "invalid") {
|
||||
return {.codecType = CodecType::UNKNOWN};
|
||||
}
|
||||
|
||||
auto configuration_iter = configuration_map_.find(coding_direction);
|
||||
if (configuration_iter == configuration_map_.end()) {
|
||||
return {.codecType = CodecType::UNKNOWN};
|
||||
}
|
||||
|
||||
auto codec_configuration_iter = codec_configuration_map_.find(
|
||||
configuration_iter->second.getCodecConfiguration());
|
||||
if (codec_configuration_iter == codec_configuration_map_.end()) {
|
||||
return {.codecType = CodecType::UNKNOWN};
|
||||
}
|
||||
|
||||
auto strategy_configuration_iter = strategy_configuration_map_.find(
|
||||
configuration_iter->second.getStrategyConfiguration());
|
||||
if (strategy_configuration_iter == strategy_configuration_map_.end()) {
|
||||
return {.codecType = CodecType::UNKNOWN};
|
||||
}
|
||||
|
||||
CodecType codec_type =
|
||||
GetCodecType(codec_configuration_iter->second.getCodec());
|
||||
if (codec_type == CodecType::LC3) {
|
||||
return ComposeUnicastCapability(
|
||||
codec_type,
|
||||
GetAudioLocation(
|
||||
strategy_configuration_iter->second.getAudioLocation()),
|
||||
strategy_configuration_iter->second.getConnectedDevice(),
|
||||
strategy_configuration_iter->second.getChannelCount(),
|
||||
ComposeLc3Capability(codec_configuration_iter->second));
|
||||
}
|
||||
return {.codecType = CodecType::UNKNOWN};
|
||||
}
|
||||
|
||||
template <class T>
|
||||
UnicastCapability BluetoothLeAudioCodecsProvider::ComposeUnicastCapability(
|
||||
const CodecType& codec_type, const AudioLocation& audio_location,
|
||||
const uint8_t& device_cnt, const uint8_t& channel_count,
|
||||
const T& capability) {
|
||||
return {
|
||||
.codecType = codec_type,
|
||||
.supportedChannel = audio_location,
|
||||
.deviceCount = device_cnt,
|
||||
.channelCountPerDevice = channel_count,
|
||||
.leAudioCodecCapabilities =
|
||||
UnicastCapability::LeAudioCodecCapabilities(capability),
|
||||
};
|
||||
}
|
||||
|
||||
Lc3Capabilities BluetoothLeAudioCodecsProvider::ComposeLc3Capability(
|
||||
const setting::CodecConfiguration& codec_configuration) {
|
||||
return {.samplingFrequencyHz = {codec_configuration.getSamplingFrequency()},
|
||||
.frameDurationUs = {codec_configuration.getFrameDurationUs()},
|
||||
.octetsPerFrame = {codec_configuration.getOctetsPerCodecFrame()}};
|
||||
}
|
||||
|
||||
AudioLocation BluetoothLeAudioCodecsProvider::GetAudioLocation(
|
||||
const setting::AudioLocation& audio_location) {
|
||||
switch (audio_location) {
|
||||
case setting::AudioLocation::MONO:
|
||||
return kMonoAudio;
|
||||
case setting::AudioLocation::STEREO:
|
||||
return kStereoAudio;
|
||||
default:
|
||||
return AudioLocation::UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
CodecType BluetoothLeAudioCodecsProvider::GetCodecType(
|
||||
const setting::CodecType& codec_type) {
|
||||
switch (codec_type) {
|
||||
case setting::CodecType::LC3:
|
||||
return CodecType::LC3;
|
||||
default:
|
||||
return CodecType::UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
bool BluetoothLeAudioCodecsProvider::IsValidCodecConfiguration(
|
||||
const setting::CodecConfiguration& codec_configuration) {
|
||||
return codec_configuration.hasName() && codec_configuration.hasCodec() &&
|
||||
codec_configuration.hasSamplingFrequency() &&
|
||||
codec_configuration.hasFrameDurationUs() &&
|
||||
codec_configuration.hasOctetsPerCodecFrame();
|
||||
}
|
||||
|
||||
bool BluetoothLeAudioCodecsProvider::IsValidStrategyConfiguration(
|
||||
const setting::StrategyConfiguration& strategy_configuration) {
|
||||
if (!strategy_configuration.hasName() ||
|
||||
!strategy_configuration.hasAudioLocation() ||
|
||||
!strategy_configuration.hasConnectedDevice() ||
|
||||
!strategy_configuration.hasChannelCount()) {
|
||||
return false;
|
||||
}
|
||||
if (strategy_configuration.getAudioLocation() ==
|
||||
setting::AudioLocation::STEREO) {
|
||||
if ((strategy_configuration.getConnectedDevice() == 2 &&
|
||||
strategy_configuration.getChannelCount() == 1) ||
|
||||
(strategy_configuration.getConnectedDevice() == 1 &&
|
||||
strategy_configuration.getChannelCount() == 2)) {
|
||||
// Stereo
|
||||
// 1. two connected device, one for L one for R
|
||||
// 2. one connected device for both L and R
|
||||
return true;
|
||||
}
|
||||
} else if (strategy_configuration.getAudioLocation() ==
|
||||
setting::AudioLocation::MONO) {
|
||||
if (strategy_configuration.getConnectedDevice() == 1 &&
|
||||
strategy_configuration.getChannelCount() == 1) {
|
||||
// Mono
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
|
@ -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 <aidl/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.h>
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "aidl_android_hardware_bluetooth_audio_setting.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
|
||||
class BluetoothLeAudioCodecsProvider {
|
||||
public:
|
||||
static std::vector<LeAudioCodecCapabilitiesSetting>
|
||||
GetLeAudioCodecCapabilities();
|
||||
|
||||
private:
|
||||
static inline std::unordered_map<std::string, setting::Configuration>
|
||||
configuration_map_;
|
||||
static inline std::unordered_map<std::string, setting::CodecConfiguration>
|
||||
codec_configuration_map_;
|
||||
static inline std::unordered_map<std::string, setting::StrategyConfiguration>
|
||||
strategy_configuration_map_;
|
||||
|
||||
static std::vector<setting::Scenario> GetScenarios(
|
||||
const std::optional<setting::LeAudioOffloadSetting>&
|
||||
le_audio_offload_setting);
|
||||
static void UpdateConfigurationsToMap(
|
||||
const std::optional<setting::LeAudioOffloadSetting>&
|
||||
le_audio_offload_setting);
|
||||
static void UpdateCodecConfigurationsToMap(
|
||||
const std::optional<setting::LeAudioOffloadSetting>&
|
||||
le_audio_offload_setting);
|
||||
static void UpdateStrategyConfigurationsToMap(
|
||||
const std::optional<setting::LeAudioOffloadSetting>&
|
||||
le_audio_offload_setting);
|
||||
|
||||
static std::vector<LeAudioCodecCapabilitiesSetting>
|
||||
ComposeLeAudioCodecCapabilities(
|
||||
const std::vector<setting::Scenario>& supported_scenarios);
|
||||
|
||||
static UnicastCapability GetUnicastCapability(
|
||||
const std::string& coding_direction);
|
||||
template <class T>
|
||||
static inline UnicastCapability ComposeUnicastCapability(
|
||||
const CodecType& codec_type, const AudioLocation& audio_location,
|
||||
const uint8_t& device_cnt, const uint8_t& channel_count,
|
||||
const T& capability);
|
||||
|
||||
static inline Lc3Capabilities ComposeLc3Capability(
|
||||
const setting::CodecConfiguration& codec_configuration);
|
||||
|
||||
static inline AudioLocation GetAudioLocation(
|
||||
const setting::AudioLocation& audio_location);
|
||||
static inline CodecType GetCodecType(const setting::CodecType& codec_type);
|
||||
|
||||
static inline bool IsValidCodecConfiguration(
|
||||
const setting::CodecConfiguration& codec_configuration);
|
||||
static inline bool IsValidStrategyConfiguration(
|
||||
const setting::StrategyConfiguration& strategy_configuration);
|
||||
};
|
||||
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
|
@ -0,0 +1,61 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!---
|
||||
This is an example to configure LE Audio hardware offload supported capability settings
|
||||
In the follow list, there would be only one list in this file. Add element into each list as needed.
|
||||
|
||||
codecConfigurationList:
|
||||
Supported codec capability along with its parameter setting
|
||||
|
||||
strategyConfigurationList:
|
||||
ASE Configuration strategies
|
||||
|
||||
configurationList:
|
||||
For each configuration , there are two attributes
|
||||
- codecConfiguration
|
||||
- strategyConfiguration
|
||||
|
||||
scenarioList:
|
||||
There would be only one `scenarios` group
|
||||
For each scenario, the are two attributes
|
||||
- encode
|
||||
- decode
|
||||
If a scenario is unidirectional, mark another direction as `invalid`
|
||||
The configuration should be chosen from `configurationList`
|
||||
-->
|
||||
<leAudioOffloadSetting>
|
||||
<scenarioList>
|
||||
<!-- encode only -->
|
||||
<scenario encode="OneChanMono_16_1" decode="invalid"/>
|
||||
<scenario encode="TwoChanStereo_16_1" decode="invalid"/>
|
||||
<scenario encode="OneChanStereo_16_1" decode="invalid"/>
|
||||
<scenario encode="OneChanMono_16_2" decode="invalid"/>
|
||||
<scenario encode="TwoChanStereo_16_2" decode="invalid"/>
|
||||
<scenario encode="OneChanStereo_16_2" decode="invalid"/>
|
||||
<!-- encode and decode -->
|
||||
<scenario encode="OneChanStereo_16_1" decode="OneChanStereo_16_1"/>
|
||||
<scenario encode="OneChanStereo_16_1" decode="OneChanMono_16_1"/>
|
||||
<scenario encode="TwoChanStereo_16_1" decode="OneChanMono_16_1"/>
|
||||
<scenario encode="OneChanMono_16_1" decode="OneChanMono_16_1"/>
|
||||
<scenario encode="OneChanStereo_16_2" decode="OneChanStereo_16_2"/>
|
||||
<scenario encode="OneChanStereo_16_2" decode="OneChanMono_16_2"/>
|
||||
<scenario encode="TwoChanStereo_16_2" decode="OneChanMono_16_2"/>
|
||||
<scenario encode="OneChanMono_16_2" decode="OneChanMono_16_2"/>
|
||||
</scenarioList>
|
||||
<configurationList>
|
||||
<configuration name="OneChanMono_16_1" codecConfiguration="LC3_16k_1" strategyConfiguration="MONO_ONE_CIS_PER_DEVICE"/>
|
||||
<configuration name="TwoChanStereo_16_1" codecConfiguration="LC3_16k_1" strategyConfiguration="STEREO_TWO_CISES_PER_DEVICE"/>
|
||||
<configuration name="OneChanStereo_16_1" codecConfiguration="LC3_16k_1" strategyConfiguration="STEREO_ONE_CIS_PER_DEVICE"/>
|
||||
<configuration name="OneChanMono_16_2" codecConfiguration="LC3_16k_2" strategyConfiguration="MONO_ONE_CIS_PER_DEVICE"/>
|
||||
<configuration name="TwoChanStereo_16_2" codecConfiguration="LC3_16k_2" strategyConfiguration="STEREO_TWO_CISES_PER_DEVICE"/>
|
||||
<configuration name="OneChanStereo_16_2" codecConfiguration="LC3_16k_2" strategyConfiguration="STEREO_ONE_CIS_PER_DEVICE"/>
|
||||
</configurationList>
|
||||
<codecConfigurationList>
|
||||
<codecConfiguration name="LC3_16k_1" codec="LC3" samplingFrequency="16000" frameDurationUs="7500" octetsPerCodecFrame="30"/>
|
||||
<codecConfiguration name="LC3_16k_2" codec="LC3" samplingFrequency="16000" frameDurationUs="10000" octetsPerCodecFrame="40"/>
|
||||
</codecConfigurationList>
|
||||
<strategyConfigurationList>
|
||||
<strategyConfiguration name="STEREO_ONE_CIS_PER_DEVICE" audioLocation="STEREO" connectedDevice="2" channelCount="1"/>
|
||||
<strategyConfiguration name="STEREO_TWO_CISES_PER_DEVICE" audioLocation="STEREO" connectedDevice="1" channelCount="2"/>
|
||||
<strategyConfiguration name="MONO_ONE_CIS_PER_DEVICE" audioLocation="MONO" connectedDevice="1" channelCount="1"/>
|
||||
</strategyConfigurationList>
|
||||
</leAudioOffloadSetting>
|
|
@ -0,0 +1,74 @@
|
|||
<!-- LE Audio Offload Codec Capability Schema -->
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:element name="leAudioOffloadSetting">
|
||||
<xs:complexType>
|
||||
<xs:element ref="scenarioList" minOccurs="1" maxOccurs="1"/>
|
||||
<xs:element ref="configurationList" minOccurs="1" maxOccurs="1"/>
|
||||
<xs:element ref="codecConfigurationList" minOccurs="1" maxOccurs="1"/>
|
||||
<xs:element ref="strategyConfigurationList" minOccurs="1" maxOccurs="1"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="scenarioList">
|
||||
<xs:complexType>
|
||||
<xs:element ref="scenario" minOccurs="1" maxOccurs="unbounded"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="configurationList">
|
||||
<xs:complexType>
|
||||
<xs:element ref="configuration" minOccurs="1" maxOccurs="unbounded"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="codecConfigurationList">
|
||||
<xs:complexType>
|
||||
<xs:element ref="codecConfiguration" minOccurs="1" maxOccurs="unbounded"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="strategyConfigurationList">
|
||||
<xs:complexType>
|
||||
<xs:element ref="strategyConfiguration" minOccurs="1" maxOccurs="unbounded"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="scenario">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="encode" type="xs:string"/>
|
||||
<xs:attribute name="decode" type="xs:string"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="configuration">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="name" type="xs:string"/>
|
||||
<xs:attribute name="codecConfiguration" type="xs:string"/>
|
||||
<xs:attribute name="strategyConfiguration" type="xs:string"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="codecConfiguration">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="name" type="xs:string"/>
|
||||
<xs:attribute name="codec" type="codecType"/>
|
||||
<xs:attribute name="pcmBitDepth" type="xs:unsignedByte"/>
|
||||
<xs:attribute name="samplingFrequency" type="xs:int"/>
|
||||
<xs:attribute name="frameDurationUs" type="xs:int"/>
|
||||
<xs:attribute name="octetsPerCodecFrame" type="xs:int"/>
|
||||
<xs:attribute name="codecFrameBlocksPerSdu" type="xs:unsignedByte"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="strategyConfiguration">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="name" type="xs:string"/>
|
||||
<xs:attribute name="audioLocation" type="audioLocation"/>
|
||||
<xs:attribute name="connectedDevice" type="xs:unsignedByte"/>
|
||||
<xs:attribute name="channelCount" type="xs:unsignedByte"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:simpleType name="audioLocation">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="MONO"/>
|
||||
<xs:enumeration value="STEREO"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="codecType">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="LC3"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:schema>
|
|
@ -0,0 +1,111 @@
|
|||
// Signature format: 2.0
|
||||
package aidl.android.hardware.bluetooth.audio.setting {
|
||||
|
||||
public enum AudioLocation {
|
||||
method public String getRawName();
|
||||
enum_constant public static final aidl.android.hardware.bluetooth.audio.setting.AudioLocation MONO;
|
||||
enum_constant public static final aidl.android.hardware.bluetooth.audio.setting.AudioLocation STEREO;
|
||||
}
|
||||
|
||||
public class CodecConfiguration {
|
||||
ctor public CodecConfiguration();
|
||||
method public aidl.android.hardware.bluetooth.audio.setting.CodecType getCodec();
|
||||
method public short getCodecFrameBlocksPerSdu();
|
||||
method public int getFrameDurationUs();
|
||||
method public String getName();
|
||||
method public int getOctetsPerCodecFrame();
|
||||
method public short getPcmBitDepth();
|
||||
method public int getSamplingFrequency();
|
||||
method public void setCodec(aidl.android.hardware.bluetooth.audio.setting.CodecType);
|
||||
method public void setCodecFrameBlocksPerSdu(short);
|
||||
method public void setFrameDurationUs(int);
|
||||
method public void setName(String);
|
||||
method public void setOctetsPerCodecFrame(int);
|
||||
method public void setPcmBitDepth(short);
|
||||
method public void setSamplingFrequency(int);
|
||||
}
|
||||
|
||||
public class CodecConfigurationList {
|
||||
ctor public CodecConfigurationList();
|
||||
method public java.util.List<aidl.android.hardware.bluetooth.audio.setting.CodecConfiguration> getCodecConfiguration();
|
||||
}
|
||||
|
||||
public enum CodecType {
|
||||
method public String getRawName();
|
||||
enum_constant public static final aidl.android.hardware.bluetooth.audio.setting.CodecType LC3;
|
||||
}
|
||||
|
||||
public class Configuration {
|
||||
ctor public Configuration();
|
||||
method public String getCodecConfiguration();
|
||||
method public String getName();
|
||||
method public String getStrategyConfiguration();
|
||||
method public void setCodecConfiguration(String);
|
||||
method public void setName(String);
|
||||
method public void setStrategyConfiguration(String);
|
||||
}
|
||||
|
||||
public class ConfigurationList {
|
||||
ctor public ConfigurationList();
|
||||
method public java.util.List<aidl.android.hardware.bluetooth.audio.setting.Configuration> getConfiguration();
|
||||
}
|
||||
|
||||
public class LeAudioOffloadSetting {
|
||||
ctor public LeAudioOffloadSetting();
|
||||
method public aidl.android.hardware.bluetooth.audio.setting.CodecConfigurationList getCodecConfigurationList();
|
||||
method public aidl.android.hardware.bluetooth.audio.setting.ConfigurationList getConfigurationList();
|
||||
method public aidl.android.hardware.bluetooth.audio.setting.ScenarioList getScenarioList();
|
||||
method public aidl.android.hardware.bluetooth.audio.setting.StrategyConfigurationList getStrategyConfigurationList();
|
||||
method public void setCodecConfigurationList(aidl.android.hardware.bluetooth.audio.setting.CodecConfigurationList);
|
||||
method public void setConfigurationList(aidl.android.hardware.bluetooth.audio.setting.ConfigurationList);
|
||||
method public void setScenarioList(aidl.android.hardware.bluetooth.audio.setting.ScenarioList);
|
||||
method public void setStrategyConfigurationList(aidl.android.hardware.bluetooth.audio.setting.StrategyConfigurationList);
|
||||
}
|
||||
|
||||
public class Scenario {
|
||||
ctor public Scenario();
|
||||
method public String getDecode();
|
||||
method public String getEncode();
|
||||
method public void setDecode(String);
|
||||
method public void setEncode(String);
|
||||
}
|
||||
|
||||
public class ScenarioList {
|
||||
ctor public ScenarioList();
|
||||
method public java.util.List<aidl.android.hardware.bluetooth.audio.setting.Scenario> getScenario();
|
||||
}
|
||||
|
||||
public class StrategyConfiguration {
|
||||
ctor public StrategyConfiguration();
|
||||
method public aidl.android.hardware.bluetooth.audio.setting.AudioLocation getAudioLocation();
|
||||
method public short getChannelCount();
|
||||
method public short getConnectedDevice();
|
||||
method public String getName();
|
||||
method public void setAudioLocation(aidl.android.hardware.bluetooth.audio.setting.AudioLocation);
|
||||
method public void setChannelCount(short);
|
||||
method public void setConnectedDevice(short);
|
||||
method public void setName(String);
|
||||
}
|
||||
|
||||
public class StrategyConfigurationList {
|
||||
ctor public StrategyConfigurationList();
|
||||
method public java.util.List<aidl.android.hardware.bluetooth.audio.setting.StrategyConfiguration> getStrategyConfiguration();
|
||||
}
|
||||
|
||||
public class XmlParser {
|
||||
ctor public XmlParser();
|
||||
method public static aidl.android.hardware.bluetooth.audio.setting.CodecConfiguration readCodecConfiguration(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
|
||||
method public static aidl.android.hardware.bluetooth.audio.setting.CodecConfigurationList readCodecConfigurationList(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
|
||||
method public static aidl.android.hardware.bluetooth.audio.setting.Configuration readConfiguration(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
|
||||
method public static aidl.android.hardware.bluetooth.audio.setting.ConfigurationList readConfigurationList(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
|
||||
method public static aidl.android.hardware.bluetooth.audio.setting.LeAudioOffloadSetting readLeAudioOffloadSetting(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
|
||||
method public static aidl.android.hardware.bluetooth.audio.setting.Scenario readScenario(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
|
||||
method public static aidl.android.hardware.bluetooth.audio.setting.ScenarioList readScenarioList(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
|
||||
method public static aidl.android.hardware.bluetooth.audio.setting.StrategyConfiguration readStrategyConfiguration(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
|
||||
method public static aidl.android.hardware.bluetooth.audio.setting.StrategyConfigurationList readStrategyConfigurationList(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
|
||||
method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
|
||||
method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
// Signature format: 2.0
|
Loading…
Reference in a new issue