mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 11:36:00 +00:00
Merge changes from topic "HFP-SCO-management" into main
* changes: Add VTS for HFP sessions Add HFP to BluetoothAudioSession Add HFP default implementation Add HFP AIDL design
This commit is contained in:
@@ -38,4 +38,5 @@ union AudioConfiguration {
|
||||
android.hardware.bluetooth.audio.CodecConfiguration a2dpConfig;
|
||||
android.hardware.bluetooth.audio.LeAudioConfiguration leAudioConfig;
|
||||
android.hardware.bluetooth.audio.LeAudioBroadcastConfiguration leAudioBroadcastConfig;
|
||||
android.hardware.bluetooth.audio.HfpConfiguration hfpConfig;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// 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 HfpConfiguration {
|
||||
android.hardware.bluetooth.audio.CodecId codecId;
|
||||
int connectionHandle;
|
||||
boolean nrec;
|
||||
boolean controllerCodec;
|
||||
}
|
||||
@@ -46,4 +46,7 @@ enum SessionType {
|
||||
LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
|
||||
A2DP_SOFTWARE_DECODING_DATAPATH,
|
||||
A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH,
|
||||
HFP_SOFTWARE_ENCODING_DATAPATH,
|
||||
HFP_SOFTWARE_DECODING_DATAPATH,
|
||||
HFP_HARDWARE_OFFLOAD_DATAPATH,
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package android.hardware.bluetooth.audio;
|
||||
|
||||
import android.hardware.bluetooth.audio.CodecConfiguration;
|
||||
import android.hardware.bluetooth.audio.HfpConfiguration;
|
||||
import android.hardware.bluetooth.audio.LeAudioBroadcastConfiguration;
|
||||
import android.hardware.bluetooth.audio.LeAudioConfiguration;
|
||||
import android.hardware.bluetooth.audio.PcmConfiguration;
|
||||
@@ -30,4 +31,5 @@ union AudioConfiguration {
|
||||
CodecConfiguration a2dpConfig;
|
||||
LeAudioConfiguration leAudioConfig;
|
||||
LeAudioBroadcastConfiguration leAudioBroadcastConfig;
|
||||
HfpConfiguration hfpConfig;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.hardware.bluetooth.audio;
|
||||
|
||||
import android.hardware.bluetooth.audio.CodecId;
|
||||
|
||||
@VintfStability
|
||||
parcelable HfpConfiguration {
|
||||
/**
|
||||
* Codec identifier.
|
||||
*/
|
||||
CodecId codecId;
|
||||
|
||||
/**
|
||||
* The connection handle used for SCO connection.
|
||||
* Range: 0x0000 to 0x0EFF.
|
||||
*/
|
||||
int connectionHandle;
|
||||
|
||||
/**
|
||||
* Echo canceling and noise reduction functions resident in the AG.
|
||||
*/
|
||||
boolean nrec;
|
||||
|
||||
/**
|
||||
* Indicate whether the codec is encoded and decoded in the controller.
|
||||
* If the codec is inside the DSP, then it would be transparent mode.
|
||||
*/
|
||||
boolean controllerCodec;
|
||||
}
|
||||
@@ -70,4 +70,17 @@ enum SessionType {
|
||||
* The decoding of AVDTP media is done by HW and there is control only
|
||||
*/
|
||||
A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH,
|
||||
/**
|
||||
* Used when audio is encoded by Bluetooth Stack and is streaming to HFP device.
|
||||
*/
|
||||
HFP_SOFTWARE_ENCODING_DATAPATH,
|
||||
/**
|
||||
* Used when audio is decoded by Bluetooth Stack and is streaming to HFP device.
|
||||
*/
|
||||
HFP_SOFTWARE_DECODING_DATAPATH,
|
||||
/**
|
||||
* Used when encoded and decoded by hardware offload and is streamed to HFP device.
|
||||
* This is a control path only.
|
||||
*/
|
||||
HFP_HARDWARE_OFFLOAD_DATAPATH,
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ cc_library_shared {
|
||||
"A2dpOffloadAudioProvider.cpp",
|
||||
"A2dpSoftwareAudioProvider.cpp",
|
||||
"HearingAidAudioProvider.cpp",
|
||||
"HfpOffloadAudioProvider.cpp",
|
||||
"HfpSoftwareAudioProvider.cpp",
|
||||
"LeAudioOffloadAudioProvider.cpp",
|
||||
"LeAudioSoftwareAudioProvider.cpp",
|
||||
"service.cpp",
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include "A2dpSoftwareAudioProvider.h"
|
||||
#include "BluetoothAudioProvider.h"
|
||||
#include "HearingAidAudioProvider.h"
|
||||
#include "HfpOffloadAudioProvider.h"
|
||||
#include "HfpSoftwareAudioProvider.h"
|
||||
#include "LeAudioOffloadAudioProvider.h"
|
||||
#include "LeAudioSoftwareAudioProvider.h"
|
||||
|
||||
@@ -78,6 +80,15 @@ ndk::ScopedAStatus BluetoothAudioProviderFactory::openProvider(
|
||||
case SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH:
|
||||
provider = ndk::SharedRefBase::make<A2dpOffloadDecodingAudioProvider>();
|
||||
break;
|
||||
case SessionType::HFP_SOFTWARE_ENCODING_DATAPATH:
|
||||
provider = ndk::SharedRefBase::make<HfpSoftwareOutputAudioProvider>();
|
||||
break;
|
||||
case SessionType::HFP_SOFTWARE_DECODING_DATAPATH:
|
||||
provider = ndk::SharedRefBase::make<HfpSoftwareInputAudioProvider>();
|
||||
break;
|
||||
case SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH:
|
||||
provider = ndk::SharedRefBase::make<HfpOffloadAudioProvider>();
|
||||
break;
|
||||
default:
|
||||
provider = nullptr;
|
||||
break;
|
||||
|
||||
65
bluetooth/audio/aidl/default/HfpOffloadAudioProvider.cpp
Normal file
65
bluetooth/audio/aidl/default/HfpOffloadAudioProvider.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "BTAudioProviderHfpHW"
|
||||
|
||||
#include "HfpOffloadAudioProvider.h"
|
||||
|
||||
#include <BluetoothAudioCodecs.h>
|
||||
#include <BluetoothAudioSessionReport.h>
|
||||
#include <android-base/logging.h>
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
|
||||
HfpOffloadAudioProvider::HfpOffloadAudioProvider() {
|
||||
session_type_ = SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH;
|
||||
}
|
||||
|
||||
bool HfpOffloadAudioProvider::isValid(const SessionType& session_type) {
|
||||
return (session_type == session_type_);
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus HfpOffloadAudioProvider::startSession(
|
||||
const std::shared_ptr<IBluetoothAudioPort>& host_if,
|
||||
const AudioConfiguration& audio_config,
|
||||
const std::vector<LatencyMode>& latency_modes, DataMQDesc* _aidl_return) {
|
||||
if (audio_config.getTag() != AudioConfiguration::hfpConfig) {
|
||||
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,
|
||||
latency_modes, _aidl_return);
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus HfpOffloadAudioProvider::onSessionReady(
|
||||
DataMQDesc* _aidl_return) {
|
||||
*_aidl_return = DataMQDesc();
|
||||
BluetoothAudioSessionReport::OnSessionStarted(
|
||||
session_type_, stack_iface_, nullptr, *audio_config_, latency_modes_);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
46
bluetooth/audio/aidl/default/HfpOffloadAudioProvider.h
Normal file
46
bluetooth/audio/aidl/default/HfpOffloadAudioProvider.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BluetoothAudioProvider.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
|
||||
class HfpOffloadAudioProvider : public BluetoothAudioProvider {
|
||||
public:
|
||||
HfpOffloadAudioProvider();
|
||||
|
||||
bool isValid(const SessionType& sessionType) override;
|
||||
|
||||
ndk::ScopedAStatus startSession(
|
||||
const std::shared_ptr<IBluetoothAudioPort>& host_if,
|
||||
const AudioConfiguration& audio_config,
|
||||
const std::vector<LatencyMode>& latency_modes, DataMQDesc* _aidl_return);
|
||||
|
||||
private:
|
||||
ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
|
||||
};
|
||||
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
140
bluetooth/audio/aidl/default/HfpSoftwareAudioProvider.cpp
Normal file
140
bluetooth/audio/aidl/default/HfpSoftwareAudioProvider.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "BTAudioProviderHfpSW"
|
||||
|
||||
#include "HfpSoftwareAudioProvider.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 kBufferCount = 2; // two frame buffer
|
||||
|
||||
HfpSoftwareOutputAudioProvider::HfpSoftwareOutputAudioProvider()
|
||||
: HfpSoftwareAudioProvider() {
|
||||
session_type_ = SessionType::HFP_SOFTWARE_ENCODING_DATAPATH;
|
||||
}
|
||||
|
||||
HfpSoftwareInputAudioProvider::HfpSoftwareInputAudioProvider()
|
||||
: HfpSoftwareAudioProvider() {
|
||||
session_type_ = SessionType::HFP_SOFTWARE_DECODING_DATAPATH;
|
||||
}
|
||||
|
||||
HfpSoftwareAudioProvider::HfpSoftwareAudioProvider()
|
||||
: BluetoothAudioProvider(), data_mq_(nullptr) {
|
||||
}
|
||||
|
||||
bool HfpSoftwareAudioProvider::isValid(const SessionType& sessionType) {
|
||||
return (sessionType == session_type_);
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus HfpSoftwareAudioProvider::startSession(
|
||||
const std::shared_ptr<IBluetoothAudioPort>& host_if,
|
||||
const AudioConfiguration& audio_config,
|
||||
const std::vector<LatencyMode>& latency_modes, 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);
|
||||
}
|
||||
|
||||
bool isValidConfig = true;
|
||||
|
||||
if (pcm_config.bitsPerSample != 16) {
|
||||
isValidConfig = false;
|
||||
}
|
||||
|
||||
if (pcm_config.sampleRateHz != 8000 && pcm_config.sampleRateHz != 16000 &&
|
||||
pcm_config.sampleRateHz != 32000) {
|
||||
isValidConfig = false;
|
||||
}
|
||||
|
||||
if (pcm_config.channelMode != ChannelMode::MONO) {
|
||||
isValidConfig = false;
|
||||
}
|
||||
|
||||
if (pcm_config.dataIntervalUs != 7500) {
|
||||
isValidConfig = false;
|
||||
}
|
||||
|
||||
int bytes_per_sample = pcm_config.bitsPerSample / 8;
|
||||
|
||||
uint32_t data_mq_size = kBufferCount * bytes_per_sample *
|
||||
(pcm_config.sampleRateHz / 1000) *
|
||||
pcm_config.dataIntervalUs / 1000;
|
||||
if (!isValidConfig) {
|
||||
LOG(ERROR) << __func__ << "Unexpected audio buffer size: " << data_mq_size
|
||||
<< ", SampleRateHz: " << pcm_config.sampleRateHz
|
||||
<< ", ChannelMode: " << toString(pcm_config.channelMode)
|
||||
<< ", BitsPerSample: "
|
||||
<< static_cast<int>(pcm_config.bitsPerSample)
|
||||
<< ", BytesPerSample: " << bytes_per_sample
|
||||
<< ", DataIntervalUs: " << pcm_config.dataIntervalUs
|
||||
<< ", SessionType: " << toString(session_type_);
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
|
||||
}
|
||||
|
||||
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,
|
||||
latency_modes, _aidl_return);
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus HfpSoftwareAudioProvider::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();
|
||||
auto desc = data_mq_->dupeDesc();
|
||||
BluetoothAudioSessionReport::OnSessionStarted(
|
||||
session_type_, stack_iface_, &desc, *audio_config_, latency_modes_);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
59
bluetooth/audio/aidl/default/HfpSoftwareAudioProvider.h
Normal file
59
bluetooth/audio/aidl/default/HfpSoftwareAudioProvider.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BluetoothAudioProvider.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
|
||||
class HfpSoftwareAudioProvider : public BluetoothAudioProvider {
|
||||
public:
|
||||
HfpSoftwareAudioProvider();
|
||||
|
||||
bool isValid(const SessionType& sessionType) override;
|
||||
|
||||
ndk::ScopedAStatus startSession(
|
||||
const std::shared_ptr<IBluetoothAudioPort>& host_if,
|
||||
const AudioConfiguration& audio_config,
|
||||
const std::vector<LatencyMode>& latency_modes, DataMQDesc* _aidl_return);
|
||||
|
||||
private:
|
||||
// audio data queue for software encoding
|
||||
std::unique_ptr<DataMQ> data_mq_;
|
||||
|
||||
ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
|
||||
};
|
||||
|
||||
class HfpSoftwareOutputAudioProvider : public HfpSoftwareAudioProvider {
|
||||
public:
|
||||
HfpSoftwareOutputAudioProvider();
|
||||
};
|
||||
|
||||
class HfpSoftwareInputAudioProvider : public HfpSoftwareAudioProvider {
|
||||
public:
|
||||
HfpSoftwareInputAudioProvider();
|
||||
};
|
||||
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
@@ -49,6 +49,7 @@ using aidl::android::hardware::bluetooth::audio::CodecConfiguration;
|
||||
using aidl::android::hardware::bluetooth::audio::CodecId;
|
||||
using aidl::android::hardware::bluetooth::audio::CodecInfo;
|
||||
using aidl::android::hardware::bluetooth::audio::CodecType;
|
||||
using aidl::android::hardware::bluetooth::audio::HfpConfiguration;
|
||||
using aidl::android::hardware::bluetooth::audio::IBluetoothAudioPort;
|
||||
using aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider;
|
||||
using aidl::android::hardware::bluetooth::audio::IBluetoothAudioProviderFactory;
|
||||
@@ -92,6 +93,13 @@ static constexpr int8_t a2dp_bits_per_samples[] = {0, 16, 24, 32};
|
||||
static constexpr ChannelMode a2dp_channel_modes[] = {
|
||||
ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
|
||||
static std::vector<LatencyMode> latency_modes = {LatencyMode::FREE};
|
||||
|
||||
// Some valid configs for HFP PCM configuration (software sessions)
|
||||
static constexpr int32_t hfp_sample_rates_[] = {8000, 16000, 32000};
|
||||
static constexpr int8_t hfp_bits_per_samples_[] = {16};
|
||||
static constexpr ChannelMode hfp_channel_modes_[] = {ChannelMode::MONO};
|
||||
static constexpr int32_t hfp_data_interval_us_[] = {7500};
|
||||
|
||||
// Helpers
|
||||
|
||||
template <typename T>
|
||||
@@ -197,7 +205,8 @@ class BluetoothAudioProviderFactoryAidl
|
||||
case SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH:
|
||||
case SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH:
|
||||
case SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH:
|
||||
case SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH: {
|
||||
case SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH:
|
||||
case SessionType::HFP_SOFTWARE_ENCODING_DATAPATH: {
|
||||
// All software paths are mandatory and must have exact 1
|
||||
// "PcmParameters"
|
||||
ASSERT_EQ(temp_provider_capabilities_.size(), 1);
|
||||
@@ -258,7 +267,8 @@ class BluetoothAudioProviderFactoryAidl
|
||||
AudioCapabilities::leAudioCapabilities);
|
||||
}
|
||||
} break;
|
||||
case SessionType::A2DP_SOFTWARE_DECODING_DATAPATH: {
|
||||
case SessionType::A2DP_SOFTWARE_DECODING_DATAPATH:
|
||||
case SessionType::HFP_SOFTWARE_DECODING_DATAPATH: {
|
||||
if (!temp_provider_capabilities_.empty()) {
|
||||
ASSERT_EQ(temp_provider_capabilities_.size(), 1);
|
||||
ASSERT_EQ(temp_provider_capabilities_[0].getTag(),
|
||||
@@ -298,7 +308,10 @@ class BluetoothAudioProviderFactoryAidl
|
||||
LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
|
||||
session_type ==
|
||||
SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
|
||||
session_type == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH);
|
||||
session_type == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
|
||||
session_type == SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH ||
|
||||
session_type == SessionType::HFP_SOFTWARE_DECODING_DATAPATH ||
|
||||
session_type == SessionType::HFP_SOFTWARE_ENCODING_DATAPATH);
|
||||
ASSERT_EQ(audio_provider_, nullptr);
|
||||
}
|
||||
}
|
||||
@@ -575,6 +588,8 @@ class BluetoothAudioProviderFactoryAidl
|
||||
SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
|
||||
SessionType::A2DP_SOFTWARE_DECODING_DATAPATH,
|
||||
SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH,
|
||||
SessionType::HFP_SOFTWARE_ENCODING_DATAPATH,
|
||||
SessionType::HFP_SOFTWARE_DECODING_DATAPATH,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -750,6 +765,137 @@ TEST_P(BluetoothAudioProviderA2dpEncodingSoftwareAidl,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* openProvider HFP_SOFTWARE_ENCODING_DATAPATH
|
||||
*/
|
||||
class BluetoothAudioProviderHfpSoftwareEncodingAidl
|
||||
: public BluetoothAudioProviderFactoryAidl {
|
||||
public:
|
||||
virtual void SetUp() override {
|
||||
BluetoothAudioProviderFactoryAidl::SetUp();
|
||||
GetProviderCapabilitiesHelper(SessionType::HFP_SOFTWARE_ENCODING_DATAPATH);
|
||||
OpenProviderHelper(SessionType::HFP_SOFTWARE_ENCODING_DATAPATH);
|
||||
ASSERT_NE(audio_provider_, nullptr);
|
||||
}
|
||||
|
||||
virtual void TearDown() override {
|
||||
audio_port_ = nullptr;
|
||||
audio_provider_ = nullptr;
|
||||
BluetoothAudioProviderFactoryAidl::TearDown();
|
||||
}
|
||||
|
||||
bool OpenSession(int32_t sample_rate, int8_t bits_per_sample,
|
||||
ChannelMode channel_mode, int32_t data_interval_us) {
|
||||
PcmConfiguration pcm_config{
|
||||
.sampleRateHz = sample_rate,
|
||||
.channelMode = channel_mode,
|
||||
.bitsPerSample = bits_per_sample,
|
||||
.dataIntervalUs = data_interval_us,
|
||||
};
|
||||
// Checking against provider capability from getProviderCapabilities
|
||||
// For HFP software, it's
|
||||
// BluetoothAudioCodecs::GetSoftwarePcmCapabilities();
|
||||
DataMQDesc mq_desc;
|
||||
auto aidl_retval = audio_provider_->startSession(
|
||||
audio_port_, AudioConfiguration(pcm_config), latency_modes, &mq_desc);
|
||||
DataMQ data_mq(mq_desc);
|
||||
|
||||
if (!aidl_retval.isOk()) return false;
|
||||
if (!data_mq.isValid()) return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether we can open a provider of type
|
||||
*/
|
||||
TEST_P(BluetoothAudioProviderHfpSoftwareEncodingAidl,
|
||||
OpenHfpSoftwareEncodingProvider) {}
|
||||
|
||||
/**
|
||||
* Test whether each provider of type
|
||||
* SessionType::HFP_SOFTWARE_ENCODING_DATAPATH can be started and stopped with
|
||||
* different PCM config
|
||||
*/
|
||||
TEST_P(BluetoothAudioProviderHfpSoftwareEncodingAidl,
|
||||
StartAndEndHfpEncodingSoftwareSessionWithPossiblePcmConfig) {
|
||||
for (auto sample_rate : hfp_sample_rates_) {
|
||||
for (auto bits_per_sample : hfp_bits_per_samples_) {
|
||||
for (auto channel_mode : hfp_channel_modes_) {
|
||||
for (auto data_interval_us: hfp_data_interval_us_) {
|
||||
EXPECT_TRUE(OpenSession(sample_rate, bits_per_sample,
|
||||
channel_mode, data_interval_us));
|
||||
EXPECT_TRUE(audio_provider_->endSession().isOk());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* openProvider HFP_SOFTWARE_DECODING_DATAPATH
|
||||
*/
|
||||
class BluetoothAudioProviderHfpSoftwareDecodingAidl
|
||||
: public BluetoothAudioProviderFactoryAidl {
|
||||
public:
|
||||
virtual void SetUp() override {
|
||||
BluetoothAudioProviderFactoryAidl::SetUp();
|
||||
GetProviderCapabilitiesHelper(SessionType::HFP_SOFTWARE_DECODING_DATAPATH);
|
||||
OpenProviderHelper(SessionType::HFP_SOFTWARE_DECODING_DATAPATH);
|
||||
ASSERT_NE(audio_provider_, nullptr);
|
||||
}
|
||||
|
||||
virtual void TearDown() override {
|
||||
audio_port_ = nullptr;
|
||||
audio_provider_ = nullptr;
|
||||
BluetoothAudioProviderFactoryAidl::TearDown();
|
||||
}
|
||||
|
||||
bool OpenSession(int32_t sample_rate, int8_t bits_per_sample,
|
||||
ChannelMode channel_mode, int32_t data_interval_us) {
|
||||
PcmConfiguration pcm_config{
|
||||
.sampleRateHz = sample_rate,
|
||||
.channelMode = channel_mode,
|
||||
.bitsPerSample = bits_per_sample,
|
||||
.dataIntervalUs = data_interval_us,
|
||||
};
|
||||
DataMQDesc mq_desc;
|
||||
auto aidl_retval = audio_provider_->startSession(
|
||||
audio_port_, AudioConfiguration(pcm_config), latency_modes, &mq_desc);
|
||||
DataMQ data_mq(mq_desc);
|
||||
|
||||
if (!aidl_retval.isOk()) return false;
|
||||
if (!data_mq.isValid()) return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether we can open a provider of type
|
||||
*/
|
||||
TEST_P(BluetoothAudioProviderHfpSoftwareDecodingAidl,
|
||||
OpenHfpSoftwareDecodingProvider) {}
|
||||
|
||||
/**
|
||||
* Test whether each provider of type
|
||||
* SessionType::HFP_SOFTWARE_DECODING_DATAPATH can be started and stopped with
|
||||
* different PCM config
|
||||
*/
|
||||
TEST_P(BluetoothAudioProviderHfpSoftwareDecodingAidl,
|
||||
StartAndEndHfpDecodingSoftwareSessionWithPossiblePcmConfig) {
|
||||
for (auto sample_rate : hfp_sample_rates_) {
|
||||
for (auto bits_per_sample : hfp_bits_per_samples_) {
|
||||
for (auto channel_mode : hfp_channel_modes_) {
|
||||
for (auto data_interval_us: hfp_data_interval_us_) {
|
||||
EXPECT_TRUE(OpenSession(sample_rate, bits_per_sample,
|
||||
channel_mode, data_interval_us));
|
||||
EXPECT_TRUE(audio_provider_->endSession().isOk());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* openProvider A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH
|
||||
*/
|
||||
@@ -1002,6 +1148,62 @@ TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* openProvider HFP_HARDWARE_OFFLOAD_DATAPATH
|
||||
*/
|
||||
class BluetoothAudioProviderHfpHardwareAidl
|
||||
: public BluetoothAudioProviderFactoryAidl {
|
||||
public:
|
||||
virtual void SetUp() override {
|
||||
BluetoothAudioProviderFactoryAidl::SetUp();
|
||||
OpenProviderHelper(SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH);
|
||||
// Can open or empty capability
|
||||
ASSERT_TRUE(temp_provider_capabilities_.empty() ||
|
||||
audio_provider_ != nullptr);
|
||||
}
|
||||
|
||||
virtual void TearDown() override {
|
||||
audio_port_ = nullptr;
|
||||
audio_provider_ = nullptr;
|
||||
BluetoothAudioProviderFactoryAidl::TearDown();
|
||||
}
|
||||
|
||||
bool OpenSession(CodecId codec_id, int connection_handle, bool nrec,
|
||||
bool controller_codec) {
|
||||
// Check if can open session with a Hfp configuration
|
||||
HfpConfiguration hfp_configuration{
|
||||
.codecId = codec_id,
|
||||
.connectionHandle = connection_handle,
|
||||
.nrec = nrec,
|
||||
.controllerCodec = controller_codec,
|
||||
};
|
||||
DataMQDesc mq_desc;
|
||||
auto aidl_retval = audio_provider_->startSession(
|
||||
audio_port_, AudioConfiguration(hfp_configuration), latency_modes,
|
||||
&mq_desc);
|
||||
|
||||
// Only check if aidl is ok to start session.
|
||||
return aidl_retval.isOk();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether we can open a provider of type
|
||||
*/
|
||||
TEST_P(BluetoothAudioProviderHfpHardwareAidl, OpenHfpHardwareProvider) {}
|
||||
|
||||
/**
|
||||
* Test whether each provider of type
|
||||
* SessionType::HFP_SOFTWARE_DECODING_DATAPATH can be started and stopped with
|
||||
* different HFP config
|
||||
*/
|
||||
TEST_P(BluetoothAudioProviderHfpHardwareAidl,
|
||||
StartAndEndHfpHardwareSessionWithPossiblePcmConfig) {
|
||||
// Try to open with a sample configuration
|
||||
EXPECT_TRUE(OpenSession(CodecId::Core::CVSD, 6, false, true));
|
||||
EXPECT_TRUE(audio_provider_->endSession().isOk());
|
||||
}
|
||||
|
||||
/**
|
||||
* openProvider HEARING_AID_SOFTWARE_ENCODING_DATAPATH
|
||||
*/
|
||||
@@ -2279,6 +2481,29 @@ INSTANTIATE_TEST_SUITE_P(PerInstance,
|
||||
IBluetoothAudioProviderFactory::descriptor)),
|
||||
android::PrintInstanceNameToString);
|
||||
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
|
||||
BluetoothAudioProviderHfpHardwareAidl);
|
||||
INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderHfpHardwareAidl,
|
||||
testing::ValuesIn(android::getAidlHalInstanceNames(
|
||||
IBluetoothAudioProviderFactory::descriptor)),
|
||||
android::PrintInstanceNameToString);
|
||||
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
|
||||
BluetoothAudioProviderHfpSoftwareDecodingAidl);
|
||||
INSTANTIATE_TEST_SUITE_P(PerInstance,
|
||||
BluetoothAudioProviderHfpSoftwareDecodingAidl,
|
||||
testing::ValuesIn(android::getAidlHalInstanceNames(
|
||||
IBluetoothAudioProviderFactory::descriptor)),
|
||||
android::PrintInstanceNameToString);
|
||||
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
|
||||
BluetoothAudioProviderHfpSoftwareEncodingAidl);
|
||||
INSTANTIATE_TEST_SUITE_P(PerInstance,
|
||||
BluetoothAudioProviderHfpSoftwareEncodingAidl,
|
||||
testing::ValuesIn(android::getAidlHalInstanceNames(
|
||||
IBluetoothAudioProviderFactory::descriptor)),
|
||||
android::PrintInstanceNameToString);
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
ABinderProcess_setThreadPoolMaxThreadCount(1);
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace bluetooth {
|
||||
namespace audio {
|
||||
|
||||
static const PcmCapabilities kDefaultSoftwarePcmCapabilities = {
|
||||
.sampleRateHz = {16000, 24000, 32000, 44100, 48000, 88200, 96000},
|
||||
.sampleRateHz = {8000, 16000, 24000, 32000, 44100, 48000, 88200, 96000},
|
||||
.channelMode = {ChannelMode::MONO, ChannelMode::STEREO},
|
||||
.bitsPerSample = {16, 24, 32},
|
||||
.dataIntervalUs = {},
|
||||
|
||||
@@ -95,6 +95,8 @@ const AudioConfiguration BluetoothAudioSession::GetAudioConfig() {
|
||||
case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
|
||||
case SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH:
|
||||
return AudioConfiguration(CodecConfiguration{});
|
||||
case SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH:
|
||||
return AudioConfiguration(HfpConfiguration{});
|
||||
case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
|
||||
case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
|
||||
return AudioConfiguration(LeAudioConfiguration{});
|
||||
@@ -154,6 +156,7 @@ bool BluetoothAudioSession::IsSessionReady() {
|
||||
session_type_ ==
|
||||
SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
|
||||
session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
|
||||
session_type_ == SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH ||
|
||||
(data_mq_ != nullptr && data_mq_->isValid()));
|
||||
return stack_iface_ != nullptr && is_mq_valid && audio_config_ != nullptr;
|
||||
}
|
||||
@@ -275,6 +278,8 @@ bool BluetoothAudioSession::UpdateAudioConfig(
|
||||
bool is_software_session =
|
||||
(session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
|
||||
session_type_ == SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH ||
|
||||
session_type_ == SessionType::HFP_SOFTWARE_ENCODING_DATAPATH ||
|
||||
session_type_ == SessionType::HFP_SOFTWARE_DECODING_DATAPATH ||
|
||||
session_type_ == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH ||
|
||||
session_type_ == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH ||
|
||||
session_type_ ==
|
||||
@@ -283,6 +288,8 @@ bool BluetoothAudioSession::UpdateAudioConfig(
|
||||
bool is_offload_a2dp_session =
|
||||
(session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
|
||||
session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH);
|
||||
bool is_offload_hfp_session =
|
||||
session_type_ == SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH;
|
||||
bool is_offload_le_audio_unicast_session =
|
||||
(session_type_ ==
|
||||
SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
|
||||
@@ -298,6 +305,9 @@ bool BluetoothAudioSession::UpdateAudioConfig(
|
||||
bool is_a2dp_offload_audio_config =
|
||||
(is_offload_a2dp_session &&
|
||||
audio_config_tag == AudioConfiguration::a2dpConfig);
|
||||
bool is_hfp_offload_audio_config =
|
||||
(is_offload_hfp_session &&
|
||||
audio_config_tag == AudioConfiguration::hfpConfig);
|
||||
bool is_le_audio_offload_unicast_audio_config =
|
||||
(is_offload_le_audio_unicast_session &&
|
||||
audio_config_tag == AudioConfiguration::leAudioConfig);
|
||||
@@ -305,6 +315,7 @@ bool BluetoothAudioSession::UpdateAudioConfig(
|
||||
(is_offload_le_audio_broadcast_session &&
|
||||
audio_config_tag == AudioConfiguration::leAudioBroadcastConfig);
|
||||
if (!is_software_audio_config && !is_a2dp_offload_audio_config &&
|
||||
!is_hfp_offload_audio_config &&
|
||||
!is_le_audio_offload_unicast_audio_config &&
|
||||
!is_le_audio_offload_broadcast_audio_config) {
|
||||
return false;
|
||||
|
||||
@@ -84,6 +84,8 @@ class BluetoothAudioSessionControl {
|
||||
case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
|
||||
case SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH:
|
||||
return AudioConfiguration(CodecConfiguration{});
|
||||
case SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH:
|
||||
return AudioConfiguration(HfpConfiguration{});
|
||||
case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
|
||||
case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
|
||||
return AudioConfiguration(LeAudioConfiguration{});
|
||||
|
||||
@@ -475,6 +475,8 @@ inline AudioConfig_2_1 to_hidl_audio_config_2_1(
|
||||
hidl_audio_config.leAudioCodecConfig(to_hidl_leaudio_broadcast_config_2_1(
|
||||
audio_config.get<AudioConfiguration::leAudioBroadcastConfig>()));
|
||||
break;
|
||||
default:
|
||||
LOG(FATAL) << __func__ << ": unexpected AudioConfiguration";
|
||||
}
|
||||
return hidl_audio_config;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user