Remove bluetooth.audio@2.2 default implementation and utils handles am: 921760d9a7
Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/1959014 Change-Id: I38f8e9a73d41727909a88d5bbe4f95bef560bcc6
This commit is contained in:
commit
d3f8b39e76
27 changed files with 48 additions and 3340 deletions
|
@ -1,3 +0,0 @@
|
|||
aliceypkuo@google.com
|
||||
ugoyu@google.com
|
||||
sattiraju@google.com
|
|
@ -1,95 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021 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 "BTAudioProviderA2dpOffload"
|
||||
|
||||
#include "A2dpOffloadAudioProvider.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <fmq/MessageQueue.h>
|
||||
#include <hidl/MQDescriptor.h>
|
||||
|
||||
#include "BluetoothAudioSessionReport_2_2.h"
|
||||
#include "BluetoothAudioSupportedCodecsDB_2_1.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
namespace V2_2 {
|
||||
namespace implementation {
|
||||
|
||||
using ::android::bluetooth::audio::BluetoothAudioSessionReport_2_2;
|
||||
using ::android::hardware::kSynchronizedReadWrite;
|
||||
using ::android::hardware::MessageQueue;
|
||||
using ::android::hardware::Void;
|
||||
using ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration;
|
||||
|
||||
using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
|
||||
|
||||
A2dpOffloadAudioProvider::A2dpOffloadAudioProvider()
|
||||
: BluetoothAudioProvider() {
|
||||
session_type_ = V2_1::SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH;
|
||||
}
|
||||
|
||||
bool A2dpOffloadAudioProvider::isValid(const V2_0::SessionType& sessionType) {
|
||||
return isValid(static_cast<V2_1::SessionType>(sessionType));
|
||||
}
|
||||
|
||||
bool A2dpOffloadAudioProvider::isValid(const V2_1::SessionType& sessionType) {
|
||||
return (sessionType == session_type_);
|
||||
}
|
||||
|
||||
Return<void> A2dpOffloadAudioProvider::startSession(
|
||||
const sp<V2_0::IBluetoothAudioPort>& hostIf,
|
||||
const AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
|
||||
/**
|
||||
* Initialize the audio platform if audioConfiguration is supported.
|
||||
* Save the IBluetoothAudioPort interface, so that it can be used
|
||||
* later to send stream control commands to the HAL client, based on
|
||||
* interaction with Audio framework.
|
||||
*/
|
||||
if (audioConfig.getDiscriminator() !=
|
||||
AudioConfiguration::hidl_discriminator::codecConfig) {
|
||||
LOG(WARNING) << __func__
|
||||
<< " - Invalid Audio Configuration=" << toString(audioConfig);
|
||||
_hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
|
||||
DataMQ::Descriptor());
|
||||
return Void();
|
||||
} else if (!android::bluetooth::audio::IsOffloadCodecConfigurationValid(
|
||||
session_type_, audioConfig.codecConfig())) {
|
||||
_hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
|
||||
DataMQ::Descriptor());
|
||||
return Void();
|
||||
}
|
||||
|
||||
return BluetoothAudioProvider::startSession(hostIf, audioConfig, _hidl_cb);
|
||||
}
|
||||
|
||||
Return<void> A2dpOffloadAudioProvider::onSessionReady(
|
||||
startSession_cb _hidl_cb) {
|
||||
BluetoothAudioSessionReport_2_2::OnSessionStarted(session_type_, stack_iface_,
|
||||
nullptr, audio_config_);
|
||||
_hidl_cb(BluetoothAudioStatus::SUCCESS, DataMQ::Descriptor());
|
||||
return Void();
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_2
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace hardware
|
||||
} // namespace android
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021 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 android {
|
||||
namespace hardware {
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
namespace V2_2 {
|
||||
namespace implementation {
|
||||
|
||||
class A2dpOffloadAudioProvider : public BluetoothAudioProvider {
|
||||
public:
|
||||
A2dpOffloadAudioProvider();
|
||||
|
||||
bool isValid(const V2_1::SessionType& sessionType) override;
|
||||
bool isValid(const V2_0::SessionType& sessionType) override;
|
||||
|
||||
Return<void> startSession(const sp<V2_0::IBluetoothAudioPort>& hostIf,
|
||||
const V2_0::AudioConfiguration& audioConfig,
|
||||
startSession_cb _hidl_cb) override;
|
||||
|
||||
private:
|
||||
Return<void> onSessionReady(startSession_cb _hidl_cb) override;
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_2
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace hardware
|
||||
} // namespace android
|
|
@ -1,117 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021 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 "BTAudioProviderA2dpSoftware"
|
||||
|
||||
#include "A2dpSoftwareAudioProvider.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include "BluetoothAudioSessionReport_2_2.h"
|
||||
#include "BluetoothAudioSupportedCodecsDB_2_2.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
namespace V2_2 {
|
||||
namespace implementation {
|
||||
|
||||
using ::android::bluetooth::audio::BluetoothAudioSessionReport_2_2;
|
||||
using ::android::hardware::Void;
|
||||
using ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration;
|
||||
|
||||
// Here the buffer size is based on SBC
|
||||
static constexpr uint32_t kPcmFrameSize = 4; // 16 bits per sample / stereo
|
||||
// SBC is 128, and here we choose the LCM of 16, 24, and 32
|
||||
static constexpr uint32_t kPcmFrameCount = 96;
|
||||
static constexpr uint32_t kRtpFrameSize = kPcmFrameSize * kPcmFrameCount;
|
||||
// The max counts by 1 tick (20ms) for SBC is about 7. Since using 96 for the
|
||||
// PCM counts, here we just choose a greater number
|
||||
static constexpr uint32_t kRtpFrameCount = 10;
|
||||
static constexpr uint32_t kBufferSize = kRtpFrameSize * kRtpFrameCount;
|
||||
static constexpr uint32_t kBufferCount = 2; // double buffer
|
||||
static constexpr uint32_t kDataMqSize = kBufferSize * kBufferCount;
|
||||
|
||||
A2dpSoftwareAudioProvider::A2dpSoftwareAudioProvider()
|
||||
: BluetoothAudioProvider(), mDataMQ(nullptr) {
|
||||
LOG(INFO) << __func__ << " - size of audio buffer " << kDataMqSize
|
||||
<< " byte(s)";
|
||||
std::unique_ptr<DataMQ> tempDataMQ(
|
||||
new DataMQ(kDataMqSize, /* EventFlag */ true));
|
||||
if (tempDataMQ && tempDataMQ->isValid()) {
|
||||
mDataMQ = std::move(tempDataMQ);
|
||||
session_type_ = V2_1::SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH;
|
||||
} else {
|
||||
ALOGE_IF(!tempDataMQ, "failed to allocate data MQ");
|
||||
ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(), "data MQ is invalid");
|
||||
}
|
||||
}
|
||||
|
||||
bool A2dpSoftwareAudioProvider::isValid(const V2_0::SessionType& sessionType) {
|
||||
return isValid(static_cast<V2_1::SessionType>(sessionType));
|
||||
}
|
||||
|
||||
bool A2dpSoftwareAudioProvider::isValid(const V2_1::SessionType& sessionType) {
|
||||
return (sessionType == session_type_ && mDataMQ && mDataMQ->isValid());
|
||||
}
|
||||
|
||||
Return<void> A2dpSoftwareAudioProvider::startSession(
|
||||
const sp<V2_0::IBluetoothAudioPort>& hostIf,
|
||||
const AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
|
||||
/**
|
||||
* Initialize the audio platform if audioConfiguration is supported.
|
||||
* Save the IBluetoothAudioPort interface, so that it can be used
|
||||
* later to send stream control commands to the HAL client, based on
|
||||
* interaction with Audio framework.
|
||||
*/
|
||||
if (audioConfig.getDiscriminator() !=
|
||||
AudioConfiguration::hidl_discriminator::pcmConfig) {
|
||||
LOG(WARNING) << __func__
|
||||
<< " - Invalid Audio Configuration=" << toString(audioConfig);
|
||||
_hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
|
||||
DataMQ::Descriptor());
|
||||
return Void();
|
||||
} else if (!android::bluetooth::audio::IsSoftwarePcmConfigurationValid(
|
||||
audioConfig.pcmConfig())) {
|
||||
LOG(WARNING) << __func__ << " - Unsupported PCM Configuration="
|
||||
<< toString(audioConfig.pcmConfig());
|
||||
_hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
|
||||
DataMQ::Descriptor());
|
||||
return Void();
|
||||
}
|
||||
|
||||
return BluetoothAudioProvider::startSession(hostIf, audioConfig, _hidl_cb);
|
||||
}
|
||||
|
||||
Return<void> A2dpSoftwareAudioProvider::onSessionReady(
|
||||
startSession_cb _hidl_cb) {
|
||||
if (mDataMQ && mDataMQ->isValid()) {
|
||||
BluetoothAudioSessionReport_2_2::OnSessionStarted(
|
||||
session_type_, stack_iface_, mDataMQ->getDesc(), audio_config_);
|
||||
_hidl_cb(BluetoothAudioStatus::SUCCESS, *mDataMQ->getDesc());
|
||||
} else {
|
||||
_hidl_cb(BluetoothAudioStatus::FAILURE, DataMQ::Descriptor());
|
||||
}
|
||||
return Void();
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_2
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace hardware
|
||||
} // namespace android
|
|
@ -1,59 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021 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 <fmq/MessageQueue.h>
|
||||
#include <hidl/MQDescriptor.h>
|
||||
|
||||
#include "BluetoothAudioProvider.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
namespace V2_2 {
|
||||
namespace implementation {
|
||||
|
||||
using ::android::hardware::kSynchronizedReadWrite;
|
||||
using ::android::hardware::MessageQueue;
|
||||
|
||||
using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
|
||||
|
||||
class A2dpSoftwareAudioProvider : public BluetoothAudioProvider {
|
||||
public:
|
||||
A2dpSoftwareAudioProvider();
|
||||
|
||||
bool isValid(const V2_1::SessionType& sessionType) override;
|
||||
bool isValid(const V2_0::SessionType& sessionType) override;
|
||||
|
||||
Return<void> startSession(const sp<V2_0::IBluetoothAudioPort>& hostIf,
|
||||
const V2_0::AudioConfiguration& audioConfig,
|
||||
startSession_cb _hidl_cb) override;
|
||||
|
||||
private:
|
||||
// audio data queue for software encoding
|
||||
std::unique_ptr<DataMQ> mDataMQ;
|
||||
|
||||
Return<void> onSessionReady(startSession_cb _hidl_cb) override;
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_2
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace hardware
|
||||
} // namespace android
|
|
@ -1,37 +0,0 @@
|
|||
package {
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "hardware_interfaces_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["hardware_interfaces_license"],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "android.hardware.bluetooth.audio@2.2-impl",
|
||||
defaults: ["hidl_defaults"],
|
||||
vendor: true,
|
||||
relative_install_path: "hw",
|
||||
srcs: [
|
||||
"BluetoothAudioProvidersFactory.cpp",
|
||||
"BluetoothAudioProvider.cpp",
|
||||
"A2dpOffloadAudioProvider.cpp",
|
||||
"A2dpSoftwareAudioProvider.cpp",
|
||||
"HearingAidAudioProvider.cpp",
|
||||
"LeAudioAudioProvider.cpp",
|
||||
"LeAudioOffloadAudioProvider.cpp",
|
||||
],
|
||||
header_libs: ["libhardware_headers"],
|
||||
shared_libs: [
|
||||
"android.hardware.bluetooth.audio@2.0",
|
||||
"android.hardware.bluetooth.audio@2.1",
|
||||
"android.hardware.bluetooth.audio@2.2",
|
||||
"libbase",
|
||||
"libbluetooth_audio_session",
|
||||
"libcutils",
|
||||
"libfmq",
|
||||
"libhidlbase",
|
||||
"liblog",
|
||||
"libutils",
|
||||
],
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021 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 <android/hardware/bluetooth/audio/2.2/types.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
namespace V2_2 {
|
||||
namespace implementation {
|
||||
|
||||
using ::android::sp;
|
||||
using ::android::hardware::Return;
|
||||
using ::android::hardware::Void;
|
||||
using ::android::hardware::audio::common::V5_0::SinkMetadata;
|
||||
using ::android::hardware::audio::common::V5_0::SourceMetadata;
|
||||
using ::android::hardware::bluetooth::audio::V2_2::IBluetoothAudioPort;
|
||||
|
||||
class AudioPort_2_0_to_2_2_Wrapper : public V2_2::IBluetoothAudioPort {
|
||||
public:
|
||||
AudioPort_2_0_to_2_2_Wrapper(const sp<V2_0::IBluetoothAudioPort>& port) {
|
||||
this->port = port;
|
||||
}
|
||||
|
||||
Return<void> startStream() override { return port->startStream(); }
|
||||
Return<void> suspendStream() override { return port->suspendStream(); }
|
||||
Return<void> stopStream() override { return port->stopStream(); }
|
||||
Return<void> getPresentationPosition(
|
||||
getPresentationPosition_cb _hidl_cb) override {
|
||||
return port->getPresentationPosition(_hidl_cb);
|
||||
}
|
||||
Return<void> updateMetadata(const SourceMetadata& sourceMetadata) override {
|
||||
return port->updateMetadata(sourceMetadata);
|
||||
}
|
||||
Return<void> updateSinkMetadata(const SinkMetadata&) override {
|
||||
// DO NOTHING, 2.0 AudioPort doesn't support sink metadata updates
|
||||
return Void();
|
||||
}
|
||||
|
||||
sp<V2_0::IBluetoothAudioPort> port;
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_2
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace hardware
|
||||
} // namespace android
|
|
@ -1,229 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "BTAudioProviderStub"
|
||||
|
||||
#include "BluetoothAudioProvider.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include "AudioPort_2_0_to_2_2_Wrapper.h"
|
||||
#include "BluetoothAudioSessionReport_2_2.h"
|
||||
#include "BluetoothAudioSupportedCodecsDB_2_2.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
namespace V2_2 {
|
||||
namespace implementation {
|
||||
|
||||
using ::android::bluetooth::audio::BluetoothAudioSessionReport_2_2;
|
||||
using ::android::hardware::kSynchronizedReadWrite;
|
||||
using ::android::hardware::MessageQueue;
|
||||
using ::android::hardware::Void;
|
||||
|
||||
using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
|
||||
|
||||
void BluetoothAudioDeathRecipient::serviceDied(
|
||||
uint64_t cookie __unused,
|
||||
const wp<::android::hidl::base::V1_0::IBase>& who __unused) {
|
||||
LOG(ERROR) << "BluetoothAudioDeathRecipient::" << __func__
|
||||
<< " - BluetoothAudio Service died";
|
||||
provider_->endSession();
|
||||
}
|
||||
|
||||
BluetoothAudioProvider::BluetoothAudioProvider()
|
||||
: death_recipient_(new BluetoothAudioDeathRecipient(this)),
|
||||
session_type_(V2_1::SessionType::UNKNOWN),
|
||||
audio_config_({}) {}
|
||||
|
||||
Return<void> BluetoothAudioProvider::startSession(
|
||||
const sp<V2_0::IBluetoothAudioPort>& hostIf,
|
||||
const V2_0::AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
|
||||
AudioConfiguration audioConfig_2_2;
|
||||
|
||||
if (audioConfig.getDiscriminator() ==
|
||||
V2_0::AudioConfiguration::hidl_discriminator::pcmConfig) {
|
||||
audioConfig_2_2.pcmConfig(
|
||||
{.sampleRate =
|
||||
static_cast<V2_1::SampleRate>(audioConfig.pcmConfig().sampleRate),
|
||||
.channelMode = audioConfig.pcmConfig().channelMode,
|
||||
.bitsPerSample = audioConfig.pcmConfig().bitsPerSample,
|
||||
.dataIntervalUs = 0});
|
||||
} else {
|
||||
audioConfig_2_2.codecConfig(audioConfig.codecConfig());
|
||||
}
|
||||
|
||||
sp<V2_2::IBluetoothAudioPort> hostIf_2_2 =
|
||||
new AudioPort_2_0_to_2_2_Wrapper(hostIf);
|
||||
return startSession_2_2(hostIf_2_2, audioConfig_2_2, _hidl_cb);
|
||||
}
|
||||
|
||||
Return<void> BluetoothAudioProvider::startSession_2_1(
|
||||
const sp<V2_0::IBluetoothAudioPort>& hostIf,
|
||||
const V2_1::AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
|
||||
AudioConfiguration audioConfig_2_2;
|
||||
if (audioConfig.getDiscriminator() ==
|
||||
V2_1::AudioConfiguration::hidl_discriminator::leAudioCodecConfig) {
|
||||
audioConfig_2_2.leAudioConfig().mode = LeAudioMode::UNKNOWN;
|
||||
audioConfig_2_2.leAudioConfig().config.unicastConfig() = {
|
||||
.streamMap = {{
|
||||
.streamHandle = 0xFFFF,
|
||||
.audioChannelAllocation =
|
||||
audioConfig.leAudioCodecConfig().audioChannelAllocation,
|
||||
}},
|
||||
.peerDelay = 0,
|
||||
.lc3Config = audioConfig.leAudioCodecConfig().lc3Config};
|
||||
} else if (audioConfig.getDiscriminator() ==
|
||||
V2_1::AudioConfiguration::hidl_discriminator::pcmConfig) {
|
||||
audioConfig_2_2.pcmConfig(audioConfig.pcmConfig());
|
||||
} else {
|
||||
audioConfig_2_2.codecConfig(audioConfig.codecConfig());
|
||||
}
|
||||
|
||||
sp<V2_2::IBluetoothAudioPort> hostIf_2_2 =
|
||||
new AudioPort_2_0_to_2_2_Wrapper(hostIf);
|
||||
return startSession_2_2(hostIf_2_2, audioConfig_2_2, _hidl_cb);
|
||||
}
|
||||
|
||||
Return<void> BluetoothAudioProvider::startSession_2_2(
|
||||
const sp<V2_2::IBluetoothAudioPort>& hostIf,
|
||||
const AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
|
||||
if (hostIf == nullptr) {
|
||||
_hidl_cb(BluetoothAudioStatus::FAILURE, DataMQ::Descriptor());
|
||||
return Void();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the audio platform if audioConfiguration is supported.
|
||||
* Save the IBluetoothAudioPort interface, so that it can be used
|
||||
* later to send stream control commands to the HAL client, based on
|
||||
* interaction with Audio framework.
|
||||
*/
|
||||
audio_config_ = audioConfig;
|
||||
stack_iface_ = hostIf;
|
||||
stack_iface_->linkToDeath(death_recipient_, 0);
|
||||
|
||||
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
|
||||
<< ", AudioConfiguration=[" << toString(audio_config_) << "]";
|
||||
|
||||
onSessionReady(_hidl_cb);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> BluetoothAudioProvider::streamStarted(
|
||||
BluetoothAudioStatus status) {
|
||||
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
|
||||
<< ", status=" << toString(status);
|
||||
|
||||
/**
|
||||
* Streaming on control path has started,
|
||||
* HAL server should start the streaming on data path.
|
||||
*/
|
||||
if (stack_iface_) {
|
||||
BluetoothAudioSessionReport_2_2::ReportControlStatus(session_type_, true,
|
||||
status);
|
||||
} else {
|
||||
LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
|
||||
<< ", status=" << toString(status) << " has NO session";
|
||||
}
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> BluetoothAudioProvider::streamSuspended(
|
||||
BluetoothAudioStatus status) {
|
||||
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
|
||||
<< ", status=" << toString(status);
|
||||
|
||||
/**
|
||||
* Streaming on control path has suspend,
|
||||
* HAL server should suspend the streaming on data path.
|
||||
*/
|
||||
if (stack_iface_) {
|
||||
BluetoothAudioSessionReport_2_2::ReportControlStatus(session_type_, false,
|
||||
status);
|
||||
} else {
|
||||
LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
|
||||
<< ", status=" << toString(status) << " has NO session";
|
||||
}
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> BluetoothAudioProvider::endSession() {
|
||||
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
|
||||
|
||||
if (stack_iface_) {
|
||||
BluetoothAudioSessionReport_2_2::OnSessionEnded(session_type_);
|
||||
stack_iface_->unlinkToDeath(death_recipient_);
|
||||
} else {
|
||||
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
|
||||
<< " has NO session";
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up the audio platform as remote audio device is no
|
||||
* longer active
|
||||
*/
|
||||
stack_iface_ = nullptr;
|
||||
audio_config_ = {};
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> BluetoothAudioProvider::updateAudioConfiguration(
|
||||
const AudioConfiguration& audioConfig) {
|
||||
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
|
||||
|
||||
if (stack_iface_ == nullptr) {
|
||||
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
|
||||
<< " has NO session";
|
||||
return Void();
|
||||
}
|
||||
|
||||
if (audioConfig.getDiscriminator() != audio_config_.getDiscriminator()) {
|
||||
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
|
||||
<< " audio config type is not match";
|
||||
return Void();
|
||||
}
|
||||
|
||||
audio_config_ = audioConfig;
|
||||
BluetoothAudioSessionReport_2_2::ReportAudioConfigChanged(session_type_,
|
||||
audio_config_);
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> BluetoothAudioProvider::setLowLatencyModeAllowed(bool allowed) {
|
||||
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
|
||||
|
||||
if (stack_iface_ == nullptr) {
|
||||
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
|
||||
<< " has NO session";
|
||||
return Void();
|
||||
}
|
||||
LOG(INFO) << __func__ << " allowed: " << allowed;
|
||||
return Void();
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_2
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace hardware
|
||||
} // namespace android
|
|
@ -1,89 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021 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 <android/hardware/bluetooth/audio/2.2/IBluetoothAudioProvider.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
namespace V2_2 {
|
||||
namespace implementation {
|
||||
|
||||
using ::android::sp;
|
||||
using ::android::hardware::bluetooth::audio::V2_2::IBluetoothAudioPort;
|
||||
|
||||
using BluetoothAudioStatus =
|
||||
::android::hardware::bluetooth::audio::V2_0::Status;
|
||||
|
||||
class BluetoothAudioDeathRecipient;
|
||||
|
||||
class BluetoothAudioProvider : public IBluetoothAudioProvider {
|
||||
public:
|
||||
BluetoothAudioProvider();
|
||||
~BluetoothAudioProvider() = default;
|
||||
|
||||
virtual bool isValid(const V2_1::SessionType& sessionType) = 0;
|
||||
virtual bool isValid(const V2_0::SessionType& sessionType) = 0;
|
||||
|
||||
Return<void> startSession(const sp<V2_0::IBluetoothAudioPort>& hostIf,
|
||||
const V2_0::AudioConfiguration& audioConfig,
|
||||
startSession_cb _hidl_cb) override;
|
||||
Return<void> startSession_2_1(const sp<V2_0::IBluetoothAudioPort>& hostIf,
|
||||
const V2_1::AudioConfiguration& audioConfig,
|
||||
startSession_cb _hidl_cb) override;
|
||||
Return<void> startSession_2_2(const sp<V2_2::IBluetoothAudioPort>& hostIf,
|
||||
const AudioConfiguration& audioConfig,
|
||||
startSession_cb _hidl_cb) override;
|
||||
Return<void> streamStarted(BluetoothAudioStatus status) override;
|
||||
Return<void> streamSuspended(BluetoothAudioStatus status) override;
|
||||
Return<void> endSession() override;
|
||||
Return<void> updateAudioConfiguration(
|
||||
const AudioConfiguration& audioConfig) override;
|
||||
|
||||
Return<void> setLowLatencyModeAllowed(bool allowed) override;
|
||||
|
||||
protected:
|
||||
sp<BluetoothAudioDeathRecipient> death_recipient_;
|
||||
|
||||
V2_1::SessionType session_type_;
|
||||
AudioConfiguration audio_config_;
|
||||
sp<V2_2::IBluetoothAudioPort> stack_iface_;
|
||||
|
||||
virtual Return<void> onSessionReady(startSession_cb _hidl_cb) = 0;
|
||||
};
|
||||
|
||||
class BluetoothAudioDeathRecipient : public hidl_death_recipient {
|
||||
public:
|
||||
BluetoothAudioDeathRecipient(const sp<BluetoothAudioProvider> provider)
|
||||
: provider_(provider) {}
|
||||
|
||||
virtual void serviceDied(
|
||||
uint64_t cookie,
|
||||
const wp<::android::hidl::base::V1_0::IBase>& who) override;
|
||||
|
||||
private:
|
||||
sp<BluetoothAudioProvider> provider_;
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_2
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace hardware
|
||||
} // namespace android
|
|
@ -1,269 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "BTAudioProvidersFactory"
|
||||
|
||||
#include "BluetoothAudioProvidersFactory.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include "BluetoothAudioSupportedCodecsDB_2_2.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
namespace V2_2 {
|
||||
namespace implementation {
|
||||
|
||||
using ::android::hardware::hidl_vec;
|
||||
using ::android::hardware::Void;
|
||||
using ::android::hardware::bluetooth::audio::V2_0::CodecCapabilities;
|
||||
|
||||
A2dpSoftwareAudioProvider
|
||||
BluetoothAudioProvidersFactory::a2dp_software_provider_instance_;
|
||||
A2dpOffloadAudioProvider
|
||||
BluetoothAudioProvidersFactory::a2dp_offload_provider_instance_;
|
||||
HearingAidAudioProvider
|
||||
BluetoothAudioProvidersFactory::hearing_aid_provider_instance_;
|
||||
LeAudioOutputAudioProvider
|
||||
BluetoothAudioProvidersFactory::leaudio_output_provider_instance_;
|
||||
LeAudioOffloadOutputAudioProvider
|
||||
BluetoothAudioProvidersFactory::leaudio_offload_output_provider_instance_;
|
||||
LeAudioInputAudioProvider
|
||||
BluetoothAudioProvidersFactory::leaudio_input_provider_instance_;
|
||||
LeAudioOffloadInputAudioProvider
|
||||
BluetoothAudioProvidersFactory::leaudio_offload_input_provider_instance_;
|
||||
|
||||
Return<void> BluetoothAudioProvidersFactory::openProvider(
|
||||
const V2_0::SessionType sessionType, openProvider_cb _hidl_cb) {
|
||||
LOG(INFO) << __func__ << " - SessionType=" << toString(sessionType);
|
||||
BluetoothAudioStatus status = BluetoothAudioStatus::SUCCESS;
|
||||
BluetoothAudioProvider* provider = nullptr;
|
||||
|
||||
switch (sessionType) {
|
||||
case V2_0::SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH:
|
||||
provider = &a2dp_software_provider_instance_;
|
||||
break;
|
||||
case V2_0::SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH:
|
||||
provider = &a2dp_offload_provider_instance_;
|
||||
break;
|
||||
case V2_0::SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH:
|
||||
provider = &hearing_aid_provider_instance_;
|
||||
break;
|
||||
default:
|
||||
status = BluetoothAudioStatus::FAILURE;
|
||||
}
|
||||
|
||||
if (provider == nullptr || !provider->isValid(sessionType)) {
|
||||
provider = nullptr;
|
||||
status = BluetoothAudioStatus::FAILURE;
|
||||
LOG(ERROR) << __func__ << " - SessionType=" << toString(sessionType)
|
||||
<< ", status=" << toString(status);
|
||||
}
|
||||
|
||||
_hidl_cb(status, provider);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> BluetoothAudioProvidersFactory::openProvider_2_1(
|
||||
const V2_1::SessionType sessionType, openProvider_2_1_cb _hidl_cb) {
|
||||
LOG(INFO) << __func__ << " - SessionType=" << toString(sessionType);
|
||||
BluetoothAudioStatus status = BluetoothAudioStatus::SUCCESS;
|
||||
BluetoothAudioProvider* provider = nullptr;
|
||||
|
||||
switch (sessionType) {
|
||||
case V2_1::SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH:
|
||||
provider = &a2dp_software_provider_instance_;
|
||||
break;
|
||||
case V2_1::SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH:
|
||||
provider = &a2dp_offload_provider_instance_;
|
||||
break;
|
||||
case V2_1::SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH:
|
||||
provider = &hearing_aid_provider_instance_;
|
||||
break;
|
||||
case V2_1::SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH:
|
||||
provider = &leaudio_output_provider_instance_;
|
||||
break;
|
||||
case V2_1::SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH:
|
||||
provider = &leaudio_input_provider_instance_;
|
||||
break;
|
||||
default:
|
||||
status = BluetoothAudioStatus::FAILURE;
|
||||
}
|
||||
|
||||
if (provider == nullptr || !provider->isValid(sessionType)) {
|
||||
provider = nullptr;
|
||||
status = BluetoothAudioStatus::FAILURE;
|
||||
LOG(ERROR) << __func__ << " - SessionType=" << toString(sessionType)
|
||||
<< ", status=" << toString(status);
|
||||
}
|
||||
|
||||
_hidl_cb(status, provider);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> BluetoothAudioProvidersFactory::openProvider_2_2(
|
||||
const V2_1::SessionType sessionType, openProvider_2_2_cb _hidl_cb) {
|
||||
LOG(INFO) << __func__ << " - SessionType=" << toString(sessionType);
|
||||
BluetoothAudioStatus status = BluetoothAudioStatus::SUCCESS;
|
||||
BluetoothAudioProvider* provider = nullptr;
|
||||
|
||||
switch (sessionType) {
|
||||
case V2_1::SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH:
|
||||
provider = &a2dp_software_provider_instance_;
|
||||
break;
|
||||
case V2_1::SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH:
|
||||
provider = &a2dp_offload_provider_instance_;
|
||||
break;
|
||||
case V2_1::SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH:
|
||||
provider = &hearing_aid_provider_instance_;
|
||||
break;
|
||||
case V2_1::SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH:
|
||||
provider = &leaudio_output_provider_instance_;
|
||||
break;
|
||||
case V2_1::SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
|
||||
provider = &leaudio_offload_output_provider_instance_;
|
||||
break;
|
||||
case V2_1::SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH:
|
||||
provider = &leaudio_input_provider_instance_;
|
||||
break;
|
||||
case V2_1::SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
|
||||
provider = &leaudio_offload_input_provider_instance_;
|
||||
break;
|
||||
default:
|
||||
status = BluetoothAudioStatus::FAILURE;
|
||||
}
|
||||
|
||||
if (provider == nullptr || !provider->isValid(sessionType)) {
|
||||
provider = nullptr;
|
||||
status = BluetoothAudioStatus::FAILURE;
|
||||
LOG(ERROR) << __func__ << " - SessionType=" << toString(sessionType)
|
||||
<< ", status=" << toString(status);
|
||||
}
|
||||
|
||||
_hidl_cb(status, provider);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> BluetoothAudioProvidersFactory::getProviderCapabilities(
|
||||
const V2_0::SessionType sessionType, getProviderCapabilities_cb _hidl_cb) {
|
||||
hidl_vec<V2_0::AudioCapabilities> audio_capabilities =
|
||||
hidl_vec<V2_0::AudioCapabilities>(0);
|
||||
if (sessionType == V2_0::SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
|
||||
std::vector<CodecCapabilities> db_codec_capabilities =
|
||||
android::bluetooth::audio::GetOffloadCodecCapabilities(sessionType);
|
||||
if (db_codec_capabilities.size()) {
|
||||
audio_capabilities.resize(db_codec_capabilities.size());
|
||||
for (int i = 0; i < db_codec_capabilities.size(); ++i) {
|
||||
audio_capabilities[i].codecCapabilities(db_codec_capabilities[i]);
|
||||
}
|
||||
}
|
||||
} else if (sessionType != V2_0::SessionType::UNKNOWN) {
|
||||
std::vector<::android::hardware::bluetooth::audio::V2_0::PcmParameters>
|
||||
db_pcm_capabilities =
|
||||
android::bluetooth::audio::GetSoftwarePcmCapabilities();
|
||||
if (db_pcm_capabilities.size() == 1) {
|
||||
audio_capabilities.resize(1);
|
||||
audio_capabilities[0].pcmCapabilities(db_pcm_capabilities[0]);
|
||||
}
|
||||
}
|
||||
LOG(INFO) << __func__ << " - SessionType=" << toString(sessionType)
|
||||
<< " supports " << audio_capabilities.size() << " codecs";
|
||||
_hidl_cb(audio_capabilities);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> BluetoothAudioProvidersFactory::getProviderCapabilities_2_1(
|
||||
const V2_1::SessionType sessionType,
|
||||
getProviderCapabilities_2_1_cb _hidl_cb) {
|
||||
hidl_vec<V2_1::AudioCapabilities> audio_capabilities =
|
||||
hidl_vec<V2_1::AudioCapabilities>(0);
|
||||
if (sessionType == V2_1::SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
|
||||
std::vector<CodecCapabilities> db_codec_capabilities =
|
||||
android::bluetooth::audio::GetOffloadCodecCapabilities(sessionType);
|
||||
if (db_codec_capabilities.size()) {
|
||||
audio_capabilities.resize(db_codec_capabilities.size());
|
||||
for (int i = 0; i < db_codec_capabilities.size(); ++i) {
|
||||
audio_capabilities[i].codecCapabilities(db_codec_capabilities[i]);
|
||||
}
|
||||
}
|
||||
} else if (sessionType != V2_1::SessionType::UNKNOWN) {
|
||||
std::vector<V2_1::PcmParameters> db_pcm_capabilities =
|
||||
android::bluetooth::audio::GetSoftwarePcmCapabilities_2_1();
|
||||
if (db_pcm_capabilities.size() == 1) {
|
||||
audio_capabilities.resize(1);
|
||||
audio_capabilities[0].pcmCapabilities(db_pcm_capabilities[0]);
|
||||
}
|
||||
}
|
||||
LOG(INFO) << __func__ << " - SessionType=" << toString(sessionType)
|
||||
<< " supports " << audio_capabilities.size() << " codecs";
|
||||
_hidl_cb(audio_capabilities);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> BluetoothAudioProvidersFactory::getProviderCapabilities_2_2(
|
||||
const V2_1::SessionType sessionType,
|
||||
getProviderCapabilities_2_2_cb _hidl_cb) {
|
||||
hidl_vec<V2_2::AudioCapabilities> audio_capabilities =
|
||||
hidl_vec<V2_2::AudioCapabilities>(0);
|
||||
if (sessionType == V2_1::SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
|
||||
std::vector<CodecCapabilities> db_codec_capabilities =
|
||||
android::bluetooth::audio::GetOffloadCodecCapabilities(sessionType);
|
||||
if (db_codec_capabilities.size()) {
|
||||
audio_capabilities.resize(db_codec_capabilities.size());
|
||||
for (int i = 0; i < db_codec_capabilities.size(); ++i) {
|
||||
audio_capabilities[i].codecCapabilities(db_codec_capabilities[i]);
|
||||
}
|
||||
}
|
||||
} else if (sessionType == V2_1::SessionType::
|
||||
LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
|
||||
sessionType == V2_1::SessionType::
|
||||
LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
|
||||
std::vector<LeAudioCodecCapabilitiesSetting> db_codec_capabilities =
|
||||
android::bluetooth::audio::GetLeAudioOffloadCodecCapabilities(
|
||||
sessionType);
|
||||
if (db_codec_capabilities.size()) {
|
||||
audio_capabilities.resize(db_codec_capabilities.size());
|
||||
for (int i = 0; i < db_codec_capabilities.size(); ++i) {
|
||||
audio_capabilities[i].leAudioCapabilities(db_codec_capabilities[i]);
|
||||
}
|
||||
}
|
||||
} else if (sessionType != V2_1::SessionType::UNKNOWN) {
|
||||
std::vector<V2_1::PcmParameters> db_pcm_capabilities =
|
||||
android::bluetooth::audio::GetSoftwarePcmCapabilities_2_1();
|
||||
if (db_pcm_capabilities.size() == 1) {
|
||||
audio_capabilities.resize(1);
|
||||
audio_capabilities[0].pcmCapabilities(db_pcm_capabilities[0]);
|
||||
}
|
||||
}
|
||||
LOG(INFO) << __func__ << " - SessionType=" << toString(sessionType)
|
||||
<< " supports " << audio_capabilities.size() << " codecs";
|
||||
_hidl_cb(audio_capabilities);
|
||||
return Void();
|
||||
}
|
||||
|
||||
IBluetoothAudioProvidersFactory* HIDL_FETCH_IBluetoothAudioProvidersFactory(
|
||||
const char* /* name */) {
|
||||
return new BluetoothAudioProvidersFactory();
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_2
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace hardware
|
||||
} // namespace android
|
|
@ -1,80 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021 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 <android/hardware/bluetooth/audio/2.2/IBluetoothAudioProvidersFactory.h>
|
||||
|
||||
#include "A2dpOffloadAudioProvider.h"
|
||||
#include "A2dpSoftwareAudioProvider.h"
|
||||
#include "BluetoothAudioProvider.h"
|
||||
#include "HearingAidAudioProvider.h"
|
||||
#include "LeAudioAudioProvider.h"
|
||||
#include "LeAudioOffloadAudioProvider.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
namespace V2_2 {
|
||||
namespace implementation {
|
||||
|
||||
class BluetoothAudioProvidersFactory : public IBluetoothAudioProvidersFactory {
|
||||
public:
|
||||
BluetoothAudioProvidersFactory() {}
|
||||
|
||||
Return<void> openProvider(const V2_0::SessionType sessionType,
|
||||
openProvider_cb _hidl_cb) override;
|
||||
|
||||
Return<void> getProviderCapabilities(
|
||||
const V2_0::SessionType sessionType,
|
||||
getProviderCapabilities_cb _hidl_cb) override;
|
||||
|
||||
Return<void> openProvider_2_1(const V2_1::SessionType sessionType,
|
||||
openProvider_2_1_cb _hidl_cb) override;
|
||||
|
||||
Return<void> openProvider_2_2(const V2_1::SessionType sessionType,
|
||||
openProvider_2_2_cb _hidl_cb) override;
|
||||
|
||||
Return<void> getProviderCapabilities_2_1(
|
||||
const V2_1::SessionType sessionType,
|
||||
getProviderCapabilities_2_1_cb _hidl_cb) override;
|
||||
|
||||
Return<void> getProviderCapabilities_2_2(
|
||||
const V2_1::SessionType sessionType,
|
||||
getProviderCapabilities_2_2_cb _hidl_cb) override;
|
||||
|
||||
private:
|
||||
static A2dpSoftwareAudioProvider a2dp_software_provider_instance_;
|
||||
static A2dpOffloadAudioProvider a2dp_offload_provider_instance_;
|
||||
static HearingAidAudioProvider hearing_aid_provider_instance_;
|
||||
static LeAudioOutputAudioProvider leaudio_output_provider_instance_;
|
||||
static LeAudioInputAudioProvider leaudio_input_provider_instance_;
|
||||
static LeAudioOffloadOutputAudioProvider
|
||||
leaudio_offload_output_provider_instance_;
|
||||
static LeAudioOffloadInputAudioProvider
|
||||
leaudio_offload_input_provider_instance_;
|
||||
};
|
||||
|
||||
extern "C" IBluetoothAudioProvidersFactory*
|
||||
HIDL_FETCH_IBluetoothAudioProvidersFactory(const char* name);
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_2
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace hardware
|
||||
} // namespace android
|
|
@ -1,112 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "BTAudioProviderHearingAid"
|
||||
|
||||
#include "HearingAidAudioProvider.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include "BluetoothAudioSessionReport_2_2.h"
|
||||
#include "BluetoothAudioSupportedCodecsDB_2_2.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
namespace V2_2 {
|
||||
namespace implementation {
|
||||
|
||||
using ::android::bluetooth::audio::BluetoothAudioSessionReport_2_2;
|
||||
using ::android::hardware::Void;
|
||||
using ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration;
|
||||
|
||||
static constexpr uint32_t kPcmFrameSize = 4; // 16 bits per sample / stereo
|
||||
static constexpr uint32_t kPcmFrameCount = 128;
|
||||
static constexpr uint32_t kRtpFrameSize = kPcmFrameSize * kPcmFrameCount;
|
||||
static constexpr uint32_t kRtpFrameCount = 7; // max counts by 1 tick (20ms)
|
||||
static constexpr uint32_t kBufferSize = kRtpFrameSize * kRtpFrameCount;
|
||||
static constexpr uint32_t kBufferCount = 1; // single buffer
|
||||
static constexpr uint32_t kDataMqSize = kBufferSize * kBufferCount;
|
||||
|
||||
HearingAidAudioProvider::HearingAidAudioProvider()
|
||||
: BluetoothAudioProvider(), mDataMQ(nullptr) {
|
||||
LOG(INFO) << __func__ << " - size of audio buffer " << kDataMqSize
|
||||
<< " byte(s)";
|
||||
std::unique_ptr<DataMQ> tempDataMQ(
|
||||
new DataMQ(kDataMqSize, /* EventFlag */ true));
|
||||
if (tempDataMQ && tempDataMQ->isValid()) {
|
||||
mDataMQ = std::move(tempDataMQ);
|
||||
session_type_ = V2_1::SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH;
|
||||
} else {
|
||||
ALOGE_IF(!tempDataMQ, "failed to allocate data MQ");
|
||||
ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(), "data MQ is invalid");
|
||||
}
|
||||
}
|
||||
|
||||
bool HearingAidAudioProvider::isValid(const V2_0::SessionType& sessionType) {
|
||||
return isValid(static_cast<V2_1::SessionType>(sessionType));
|
||||
}
|
||||
|
||||
bool HearingAidAudioProvider::isValid(const V2_1::SessionType& sessionType) {
|
||||
return (sessionType == session_type_ && mDataMQ && mDataMQ->isValid());
|
||||
}
|
||||
|
||||
Return<void> HearingAidAudioProvider::startSession(
|
||||
const sp<V2_0::IBluetoothAudioPort>& hostIf,
|
||||
const AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
|
||||
/**
|
||||
* Initialize the audio platform if audioConfiguration is supported.
|
||||
* Save the IBluetoothAudioPort interface, so that it can be used
|
||||
* later to send stream control commands to the HAL client, based on
|
||||
* interaction with Audio framework.
|
||||
*/
|
||||
if (audioConfig.getDiscriminator() !=
|
||||
AudioConfiguration::hidl_discriminator::pcmConfig) {
|
||||
LOG(WARNING) << __func__
|
||||
<< " - Invalid Audio Configuration=" << toString(audioConfig);
|
||||
_hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
|
||||
DataMQ::Descriptor());
|
||||
return Void();
|
||||
} else if (!android::bluetooth::audio::IsSoftwarePcmConfigurationValid(
|
||||
audioConfig.pcmConfig())) {
|
||||
LOG(WARNING) << __func__ << " - Unsupported PCM Configuration="
|
||||
<< toString(audioConfig.pcmConfig());
|
||||
_hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
|
||||
DataMQ::Descriptor());
|
||||
return Void();
|
||||
}
|
||||
|
||||
return BluetoothAudioProvider::startSession(hostIf, audioConfig, _hidl_cb);
|
||||
}
|
||||
|
||||
Return<void> HearingAidAudioProvider::onSessionReady(startSession_cb _hidl_cb) {
|
||||
if (mDataMQ && mDataMQ->isValid()) {
|
||||
BluetoothAudioSessionReport_2_2::OnSessionStarted(
|
||||
session_type_, stack_iface_, mDataMQ->getDesc(), audio_config_);
|
||||
_hidl_cb(BluetoothAudioStatus::SUCCESS, *mDataMQ->getDesc());
|
||||
} else {
|
||||
_hidl_cb(BluetoothAudioStatus::FAILURE, DataMQ::Descriptor());
|
||||
}
|
||||
return Void();
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_2
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace hardware
|
||||
} // namespace android
|
|
@ -1,59 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021 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 <fmq/MessageQueue.h>
|
||||
#include <hidl/MQDescriptor.h>
|
||||
|
||||
#include "BluetoothAudioProvider.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
namespace V2_2 {
|
||||
namespace implementation {
|
||||
|
||||
using ::android::hardware::kSynchronizedReadWrite;
|
||||
using ::android::hardware::MessageQueue;
|
||||
|
||||
using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
|
||||
|
||||
class HearingAidAudioProvider : public BluetoothAudioProvider {
|
||||
public:
|
||||
HearingAidAudioProvider();
|
||||
|
||||
bool isValid(const V2_1::SessionType& sessionType) override;
|
||||
bool isValid(const V2_0::SessionType& sessionType) override;
|
||||
|
||||
Return<void> startSession(const sp<V2_0::IBluetoothAudioPort>& hostIf,
|
||||
const V2_0::AudioConfiguration& audioConfig,
|
||||
startSession_cb _hidl_cb) override;
|
||||
|
||||
private:
|
||||
// audio data queue for software encoding
|
||||
std::unique_ptr<DataMQ> mDataMQ;
|
||||
|
||||
Return<void> onSessionReady(startSession_cb _hidl_cb) override;
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_2
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace hardware
|
||||
} // namespace android
|
|
@ -1,222 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021 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 "BTAudioProviderLeAudio"
|
||||
|
||||
#include "LeAudioAudioProvider.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include "AudioPort_2_0_to_2_2_Wrapper.h"
|
||||
#include "BluetoothAudioSessionReport_2_2.h"
|
||||
#include "BluetoothAudioSupportedCodecsDB_2_2.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
namespace V2_2 {
|
||||
namespace implementation {
|
||||
|
||||
using ::android::bluetooth::audio::BluetoothAudioSessionReport_2_2;
|
||||
using ::android::hardware::Void;
|
||||
using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
|
||||
using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
|
||||
using ::android::hardware::bluetooth::audio::V2_1::SampleRate;
|
||||
|
||||
static constexpr uint32_t kBufferOutCount = 2; // two frame buffer
|
||||
static constexpr uint32_t kBufferInCount = 2; // two frame buffer
|
||||
|
||||
LeAudioOutputAudioProvider::LeAudioOutputAudioProvider()
|
||||
: LeAudioAudioProvider() {
|
||||
session_type_ = V2_1::SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
|
||||
}
|
||||
|
||||
LeAudioInputAudioProvider::LeAudioInputAudioProvider()
|
||||
: LeAudioAudioProvider() {
|
||||
session_type_ = V2_1::SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH;
|
||||
}
|
||||
|
||||
LeAudioAudioProvider::LeAudioAudioProvider()
|
||||
: BluetoothAudioProvider(), mDataMQ(nullptr) {}
|
||||
|
||||
bool LeAudioAudioProvider::isValid(const V2_0::SessionType& sessionType) {
|
||||
LOG(ERROR) << __func__ << ", invalid session type for Le Audio provider: "
|
||||
<< toString(sessionType);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LeAudioAudioProvider::isValid(const V2_1::SessionType& sessionType) {
|
||||
return (sessionType == session_type_);
|
||||
}
|
||||
|
||||
Return<void> LeAudioAudioProvider::startSession_2_1(
|
||||
const sp<V2_0::IBluetoothAudioPort>& hostIf,
|
||||
const V2_1::AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
|
||||
if (audioConfig.getDiscriminator() !=
|
||||
V2_1::AudioConfiguration::hidl_discriminator::pcmConfig) {
|
||||
LOG(WARNING) << __func__
|
||||
<< " - Invalid Audio Configuration=" << toString(audioConfig);
|
||||
_hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
|
||||
DataMQ::Descriptor());
|
||||
return Void();
|
||||
}
|
||||
|
||||
AudioConfiguration audioConfig_2_2;
|
||||
audioConfig_2_2.pcmConfig(
|
||||
{.sampleRate =
|
||||
static_cast<V2_1::SampleRate>(audioConfig.pcmConfig().sampleRate),
|
||||
.channelMode = audioConfig.pcmConfig().channelMode,
|
||||
.bitsPerSample = audioConfig.pcmConfig().bitsPerSample,
|
||||
.dataIntervalUs = 0});
|
||||
|
||||
sp<V2_2::IBluetoothAudioPort> hostIf_2_2 =
|
||||
new AudioPort_2_0_to_2_2_Wrapper(hostIf);
|
||||
return startSession_2_2(hostIf_2_2, audioConfig_2_2, _hidl_cb);
|
||||
}
|
||||
|
||||
Return<void> LeAudioAudioProvider::startSession_2_2(
|
||||
const sp<V2_2::IBluetoothAudioPort>& hostIf,
|
||||
const AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
|
||||
/**
|
||||
* Initialize the audio platform if audioConfiguration is supported.
|
||||
* Save the IBluetoothAudioPort interface, so that it can be used
|
||||
* later to send stream control commands to the HAL client, based on
|
||||
* interaction with Audio framework.
|
||||
*/
|
||||
if (audioConfig.getDiscriminator() !=
|
||||
AudioConfiguration::hidl_discriminator::pcmConfig) {
|
||||
LOG(WARNING) << __func__
|
||||
<< " - Invalid Audio Configuration=" << toString(audioConfig);
|
||||
_hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
|
||||
DataMQ::Descriptor());
|
||||
return Void();
|
||||
} else if (!android::bluetooth::audio::IsSoftwarePcmConfigurationValid_2_1(
|
||||
audioConfig.pcmConfig())) {
|
||||
LOG(WARNING) << __func__ << " - Unsupported PCM Configuration="
|
||||
<< toString(audioConfig.pcmConfig());
|
||||
_hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
|
||||
DataMQ::Descriptor());
|
||||
return Void();
|
||||
}
|
||||
|
||||
uint32_t kDataMqSize = 0;
|
||||
switch (audioConfig.pcmConfig().sampleRate) {
|
||||
case SampleRate::RATE_8000:
|
||||
kDataMqSize = 8000;
|
||||
break;
|
||||
case SampleRate::RATE_16000:
|
||||
kDataMqSize = 16000;
|
||||
break;
|
||||
case SampleRate::RATE_24000:
|
||||
kDataMqSize = 24000;
|
||||
break;
|
||||
case SampleRate::RATE_32000:
|
||||
kDataMqSize = 32000;
|
||||
break;
|
||||
case SampleRate::RATE_44100:
|
||||
kDataMqSize = 44100;
|
||||
break;
|
||||
case SampleRate::RATE_48000:
|
||||
kDataMqSize = 48000;
|
||||
break;
|
||||
default:
|
||||
LOG(WARNING) << __func__ << " - Unsupported sampling frequency="
|
||||
<< toString(audioConfig.pcmConfig());
|
||||
_hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
|
||||
DataMQ::Descriptor());
|
||||
return Void();
|
||||
}
|
||||
|
||||
/* Number of samples per millisecond */
|
||||
kDataMqSize = ceil(kDataMqSize / 1000);
|
||||
|
||||
switch (audioConfig.pcmConfig().channelMode) {
|
||||
case ChannelMode::MONO:
|
||||
break;
|
||||
case ChannelMode::STEREO:
|
||||
kDataMqSize *= 2;
|
||||
break;
|
||||
default:
|
||||
/* This should never happen it would be caught while validating
|
||||
* parameters.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
switch (audioConfig.pcmConfig().bitsPerSample) {
|
||||
case BitsPerSample::BITS_16:
|
||||
kDataMqSize *= 2;
|
||||
break;
|
||||
case BitsPerSample::BITS_24:
|
||||
kDataMqSize *= 3;
|
||||
break;
|
||||
case BitsPerSample::BITS_32:
|
||||
kDataMqSize *= 4;
|
||||
break;
|
||||
default:
|
||||
/* This should never happen it would be caught while validating
|
||||
* parameters.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
if (session_type_ == V2_1::SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH)
|
||||
kDataMqSize *= kBufferOutCount;
|
||||
else if (session_type_ ==
|
||||
V2_1::SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH)
|
||||
kDataMqSize *= kBufferInCount;
|
||||
else
|
||||
LOG(WARNING) << __func__ << ", default single buffer used";
|
||||
|
||||
kDataMqSize *= audioConfig.pcmConfig().dataIntervalUs / 1000;
|
||||
|
||||
LOG(INFO) << __func__ << " - size of audio buffer " << kDataMqSize
|
||||
<< " byte(s)";
|
||||
|
||||
std::unique_ptr<DataMQ> tempDataMQ(
|
||||
new DataMQ(kDataMqSize, /* EventFlag */ true));
|
||||
if (tempDataMQ && tempDataMQ->isValid()) {
|
||||
mDataMQ = std::move(tempDataMQ);
|
||||
} else {
|
||||
ALOGE_IF(!tempDataMQ, "failed to allocate data MQ");
|
||||
ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(), "data MQ is invalid");
|
||||
_hidl_cb(BluetoothAudioStatus::FAILURE, DataMQ::Descriptor());
|
||||
return Void();
|
||||
}
|
||||
|
||||
return BluetoothAudioProvider::startSession_2_2(hostIf, audioConfig,
|
||||
_hidl_cb);
|
||||
}
|
||||
|
||||
Return<void> LeAudioAudioProvider::onSessionReady(startSession_cb _hidl_cb) {
|
||||
if (mDataMQ && mDataMQ->isValid()) {
|
||||
BluetoothAudioSessionReport_2_2::OnSessionStarted(
|
||||
session_type_, stack_iface_, mDataMQ->getDesc(), audio_config_);
|
||||
_hidl_cb(BluetoothAudioStatus::SUCCESS, *mDataMQ->getDesc());
|
||||
} else {
|
||||
_hidl_cb(BluetoothAudioStatus::FAILURE, DataMQ::Descriptor());
|
||||
}
|
||||
return Void();
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_2
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace hardware
|
||||
} // namespace android
|
|
@ -1,74 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021 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 <android/hardware/bluetooth/audio/2.2/types.h>
|
||||
#include <fmq/MessageQueue.h>
|
||||
#include <hidl/MQDescriptor.h>
|
||||
|
||||
#include "BluetoothAudioProvider.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
namespace V2_2 {
|
||||
namespace implementation {
|
||||
|
||||
using ::android::hardware::kSynchronizedReadWrite;
|
||||
using ::android::hardware::MessageQueue;
|
||||
|
||||
using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
|
||||
|
||||
class LeAudioAudioProvider : public BluetoothAudioProvider {
|
||||
public:
|
||||
LeAudioAudioProvider();
|
||||
|
||||
bool isValid(const V2_1::SessionType& sessionType) override;
|
||||
bool isValid(const V2_0::SessionType& sessionType) override;
|
||||
|
||||
Return<void> startSession_2_1(const sp<V2_0::IBluetoothAudioPort>& hostIf,
|
||||
const V2_1::AudioConfiguration& audioConfig,
|
||||
startSession_cb _hidl_cb) override;
|
||||
|
||||
Return<void> startSession_2_2(const sp<V2_2::IBluetoothAudioPort>& hostIf,
|
||||
const AudioConfiguration& audioConfig,
|
||||
startSession_cb _hidl_cb) override;
|
||||
|
||||
private:
|
||||
/** queue for software encodec/decoded audio data */
|
||||
std::unique_ptr<DataMQ> mDataMQ;
|
||||
|
||||
Return<void> onSessionReady(startSession_cb _hidl_cb) override;
|
||||
};
|
||||
|
||||
class LeAudioOutputAudioProvider : public LeAudioAudioProvider {
|
||||
public:
|
||||
LeAudioOutputAudioProvider();
|
||||
};
|
||||
|
||||
class LeAudioInputAudioProvider : public LeAudioAudioProvider {
|
||||
public:
|
||||
LeAudioInputAudioProvider();
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_2
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace hardware
|
||||
} // namespace android
|
|
@ -1,143 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021 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 "BTAudioProviderLeAudioOffload"
|
||||
|
||||
#include "LeAudioOffloadAudioProvider.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include "AudioPort_2_0_to_2_2_Wrapper.h"
|
||||
#include "BluetoothAudioSessionReport_2_2.h"
|
||||
#include "BluetoothAudioSupportedCodecsDB_2_2.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
namespace V2_2 {
|
||||
namespace implementation {
|
||||
|
||||
using ::android::bluetooth::audio::BluetoothAudioSessionReport_2_2;
|
||||
using ::android::hardware::Void;
|
||||
using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
|
||||
using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
|
||||
using ::android::hardware::bluetooth::audio::V2_1::SampleRate;
|
||||
|
||||
using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
|
||||
|
||||
LeAudioOffloadOutputAudioProvider::LeAudioOffloadOutputAudioProvider()
|
||||
: LeAudioOffloadAudioProvider() {
|
||||
session_type_ =
|
||||
V2_1::SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
|
||||
}
|
||||
|
||||
LeAudioOffloadInputAudioProvider::LeAudioOffloadInputAudioProvider()
|
||||
: LeAudioOffloadAudioProvider() {
|
||||
session_type_ =
|
||||
V2_1::SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH;
|
||||
}
|
||||
|
||||
LeAudioOffloadAudioProvider::LeAudioOffloadAudioProvider()
|
||||
: BluetoothAudioProvider() {}
|
||||
|
||||
bool LeAudioOffloadAudioProvider::isValid(
|
||||
const V2_0::SessionType& sessionType) {
|
||||
LOG(ERROR) << __func__
|
||||
<< ", invalid session type for Offloaded Le Audio provider: "
|
||||
<< toString(sessionType);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LeAudioOffloadAudioProvider::isValid(
|
||||
const V2_1::SessionType& sessionType) {
|
||||
return (sessionType == session_type_);
|
||||
}
|
||||
|
||||
Return<void> LeAudioOffloadAudioProvider::startSession_2_1(
|
||||
const sp<V2_0::IBluetoothAudioPort>& hostIf,
|
||||
const V2_1::AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
|
||||
if (audioConfig.getDiscriminator() !=
|
||||
V2_1::AudioConfiguration::hidl_discriminator::leAudioCodecConfig) {
|
||||
LOG(WARNING) << __func__
|
||||
<< " - Invalid Audio Configuration=" << toString(audioConfig);
|
||||
_hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
|
||||
DataMQ::Descriptor());
|
||||
return Void();
|
||||
}
|
||||
|
||||
AudioConfiguration audioConfig_2_2;
|
||||
audioConfig_2_2.leAudioConfig().mode = LeAudioMode::UNKNOWN;
|
||||
audioConfig_2_2.leAudioConfig().config.unicastConfig() = {
|
||||
.streamMap = {{
|
||||
.streamHandle = 0xFFFF,
|
||||
.audioChannelAllocation =
|
||||
audioConfig.leAudioCodecConfig().audioChannelAllocation,
|
||||
}},
|
||||
.peerDelay = 0,
|
||||
.lc3Config = audioConfig.leAudioCodecConfig().lc3Config};
|
||||
|
||||
sp<V2_2::IBluetoothAudioPort> hostIf_2_2 =
|
||||
new AudioPort_2_0_to_2_2_Wrapper(hostIf);
|
||||
return startSession_2_2(hostIf_2_2, audioConfig_2_2, _hidl_cb);
|
||||
}
|
||||
|
||||
Return<void> LeAudioOffloadAudioProvider::startSession_2_2(
|
||||
const sp<V2_2::IBluetoothAudioPort>& hostIf,
|
||||
const AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
|
||||
/**
|
||||
* Initialize the audio platform if audioConfiguration is supported.
|
||||
* Save the IBluetoothAudioPort interface, so that it can be used
|
||||
* later to send stream control commands to the HAL client, based on
|
||||
* interaction with Audio framework.
|
||||
*/
|
||||
if (audioConfig.getDiscriminator() !=
|
||||
AudioConfiguration::hidl_discriminator::leAudioConfig) {
|
||||
LOG(WARNING) << __func__
|
||||
<< " - Invalid Audio Configuration=" << toString(audioConfig);
|
||||
_hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
|
||||
DataMQ::Descriptor());
|
||||
return Void();
|
||||
}
|
||||
|
||||
if (!android::bluetooth::audio::IsOffloadLeAudioConfigurationValid(
|
||||
session_type_, audioConfig.leAudioConfig())) {
|
||||
LOG(WARNING) << __func__ << " - Unsupported LC3 Offloaded Configuration="
|
||||
<< toString(audioConfig.leAudioConfig());
|
||||
_hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
|
||||
DataMQ::Descriptor());
|
||||
return Void();
|
||||
}
|
||||
|
||||
return BluetoothAudioProvider::startSession_2_2(hostIf, audioConfig,
|
||||
_hidl_cb);
|
||||
}
|
||||
|
||||
Return<void> LeAudioOffloadAudioProvider::onSessionReady(
|
||||
startSession_cb _hidl_cb) {
|
||||
BluetoothAudioSessionReport_2_2::OnSessionStarted(session_type_, stack_iface_,
|
||||
nullptr, audio_config_);
|
||||
_hidl_cb(BluetoothAudioStatus::SUCCESS, DataMQ::Descriptor());
|
||||
return Void();
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_2
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace hardware
|
||||
} // namespace android
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021 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 <android/hardware/bluetooth/audio/2.2/types.h>
|
||||
|
||||
#include "BluetoothAudioProvider.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
namespace V2_2 {
|
||||
namespace implementation {
|
||||
|
||||
class LeAudioOffloadAudioProvider : public BluetoothAudioProvider {
|
||||
public:
|
||||
LeAudioOffloadAudioProvider();
|
||||
|
||||
bool isValid(const V2_1::SessionType& sessionType) override;
|
||||
bool isValid(const V2_0::SessionType& sessionType) override;
|
||||
|
||||
Return<void> startSession_2_1(const sp<V2_0::IBluetoothAudioPort>& hostIf,
|
||||
const V2_1::AudioConfiguration& audioConfig,
|
||||
startSession_cb _hidl_cb) override;
|
||||
|
||||
Return<void> startSession_2_2(const sp<V2_2::IBluetoothAudioPort>& hostIf,
|
||||
const AudioConfiguration& audioConfig,
|
||||
startSession_cb _hidl_cb) override;
|
||||
|
||||
private:
|
||||
Return<void> onSessionReady(startSession_cb _hidl_cb) override;
|
||||
};
|
||||
|
||||
class LeAudioOffloadOutputAudioProvider : public LeAudioOffloadAudioProvider {
|
||||
public:
|
||||
LeAudioOffloadOutputAudioProvider();
|
||||
};
|
||||
|
||||
class LeAudioOffloadInputAudioProvider : public LeAudioOffloadAudioProvider {
|
||||
public:
|
||||
LeAudioOffloadInputAudioProvider();
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_2
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace hardware
|
||||
} // namespace android
|
|
@ -1,4 +0,0 @@
|
|||
include platform/packages/modules/Bluetooth:/OWNERS
|
||||
|
||||
cheneyni@google.com
|
||||
aliceypkuo@google.com
|
|
@ -14,10 +14,8 @@ cc_library_shared {
|
|||
srcs: [
|
||||
"session/BluetoothAudioSession.cpp",
|
||||
"session/BluetoothAudioSession_2_1.cpp",
|
||||
"session/BluetoothAudioSession_2_2.cpp",
|
||||
"session/BluetoothAudioSupportedCodecsDB.cpp",
|
||||
"session/BluetoothAudioSupportedCodecsDB_2_1.cpp",
|
||||
"session/BluetoothAudioSupportedCodecsDB_2_2.cpp",
|
||||
],
|
||||
export_include_dirs: ["session/"],
|
||||
header_libs: ["libhardware_headers"],
|
||||
|
@ -25,7 +23,6 @@ cc_library_shared {
|
|||
"android.hardware.audio.common@5.0",
|
||||
"android.hardware.bluetooth.audio@2.0",
|
||||
"android.hardware.bluetooth.audio@2.1",
|
||||
"android.hardware.bluetooth.audio@2.2",
|
||||
"libbase",
|
||||
"libcutils",
|
||||
"libfmq",
|
||||
|
@ -49,7 +46,6 @@ cc_library_shared {
|
|||
shared_libs: [
|
||||
"android.hardware.bluetooth.audio@2.0",
|
||||
"android.hardware.bluetooth.audio@2.1",
|
||||
"android.hardware.bluetooth.audio@2.2",
|
||||
"libbase",
|
||||
"libcutils",
|
||||
"libbinder_ndk",
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include "../aidl_session/BluetoothAudioSessionControl.h"
|
||||
#include "HidlToAidlMiddleware_2_0.h"
|
||||
#include "HidlToAidlMiddleware_2_1.h"
|
||||
#include "HidlToAidlMiddleware_2_2.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
|
@ -82,15 +81,10 @@ using Lc3Config_2_1 =
|
|||
using Lc3FrameDuration_2_1 =
|
||||
::android::hardware::bluetooth::audio::V2_1::Lc3FrameDuration;
|
||||
|
||||
using LeAudioConfig_2_2 =
|
||||
::android::hardware::bluetooth::audio::V2_2::LeAudioConfiguration;
|
||||
using LeAudioMode_2_2 =
|
||||
::android::hardware::bluetooth::audio::V2_2::LeAudioMode;
|
||||
|
||||
std::mutex legacy_callback_lock;
|
||||
std::unordered_map<
|
||||
SessionType,
|
||||
std::unordered_map<uint16_t, std::shared_ptr<PortStatusCallbacks_2_2>>>
|
||||
std::unordered_map<uint16_t, std::shared_ptr<PortStatusCallbacks_2_0>>>
|
||||
legacy_callback_table;
|
||||
|
||||
const static std::unordered_map<SessionType_2_1, SessionType>
|
||||
|
@ -461,50 +455,6 @@ inline Lc3CodecConfig_2_1 to_hidl_leaudio_broadcast_config_2_1(
|
|||
return hidl_lc3_codec_config;
|
||||
}
|
||||
|
||||
inline LeAudioConfig_2_2 to_hidl_leaudio_config_2_2(
|
||||
const LeAudioConfiguration& unicast_config) {
|
||||
LeAudioConfig_2_2 hidl_leaudio_config;
|
||||
hidl_leaudio_config.mode = LeAudioMode_2_2::UNICAST;
|
||||
::android::hardware::bluetooth::audio::V2_2::UnicastConfig
|
||||
hidl_unicast_config;
|
||||
hidl_unicast_config.peerDelay =
|
||||
static_cast<uint32_t>(unicast_config.peerDelayUs / 1000);
|
||||
|
||||
auto& lc3_config = unicast_config.leAudioCodecConfig
|
||||
.get<LeAudioCodecConfiguration::lc3Config>();
|
||||
hidl_unicast_config.lc3Config = to_hidl_lc3_config_2_1(lc3_config);
|
||||
|
||||
hidl_unicast_config.streamMap.resize(unicast_config.streamMap.size());
|
||||
for (int i = 0; i < unicast_config.streamMap.size(); i++) {
|
||||
hidl_unicast_config.streamMap[i].audioChannelAllocation =
|
||||
static_cast<uint32_t>(
|
||||
unicast_config.streamMap[i].audioChannelAllocation);
|
||||
hidl_unicast_config.streamMap[i].streamHandle =
|
||||
static_cast<uint16_t>(unicast_config.streamMap[i].streamHandle);
|
||||
}
|
||||
return hidl_leaudio_config;
|
||||
}
|
||||
|
||||
inline LeAudioConfig_2_2 to_hidl_leaudio_broadcast_config_2_2(
|
||||
const LeAudioBroadcastConfiguration& broadcast_config) {
|
||||
LeAudioConfig_2_2 hidl_leaudio_config;
|
||||
hidl_leaudio_config.mode = LeAudioMode_2_2::BROADCAST;
|
||||
::android::hardware::bluetooth::audio::V2_2::BroadcastConfig
|
||||
hidl_bcast_config;
|
||||
hidl_bcast_config.streamMap.resize(broadcast_config.streamMap.size());
|
||||
for (int i = 0; i < broadcast_config.streamMap.size(); i++) {
|
||||
hidl_bcast_config.streamMap[i].audioChannelAllocation =
|
||||
static_cast<uint32_t>(
|
||||
broadcast_config.streamMap[i].audioChannelAllocation);
|
||||
hidl_bcast_config.streamMap[i].streamHandle =
|
||||
static_cast<uint16_t>(broadcast_config.streamMap[i].streamHandle);
|
||||
hidl_bcast_config.streamMap[i].lc3Config = to_hidl_lc3_config_2_1(
|
||||
broadcast_config.streamMap[i]
|
||||
.leAudioCodecConfig.get<LeAudioCodecConfiguration::lc3Config>());
|
||||
}
|
||||
return hidl_leaudio_config;
|
||||
}
|
||||
|
||||
inline AudioConfig_2_1 to_hidl_audio_config_2_1(
|
||||
const AudioConfiguration& audio_config) {
|
||||
AudioConfig_2_1 hidl_audio_config;
|
||||
|
@ -529,30 +479,6 @@ inline AudioConfig_2_1 to_hidl_audio_config_2_1(
|
|||
return hidl_audio_config;
|
||||
}
|
||||
|
||||
inline AudioConfig_2_2 to_hidl_audio_config_2_2(
|
||||
const AudioConfiguration& audio_config) {
|
||||
AudioConfig_2_2 hidl_audio_config;
|
||||
switch (audio_config.getTag()) {
|
||||
case AudioConfiguration::pcmConfig:
|
||||
hidl_audio_config.pcmConfig(to_hidl_pcm_config_2_1(
|
||||
audio_config.get<AudioConfiguration::pcmConfig>()));
|
||||
break;
|
||||
case AudioConfiguration::a2dpConfig:
|
||||
hidl_audio_config.codecConfig(to_hidl_codec_config_2_0(
|
||||
audio_config.get<AudioConfiguration::a2dpConfig>()));
|
||||
break;
|
||||
case AudioConfiguration::leAudioConfig:
|
||||
hidl_audio_config.leAudioConfig(to_hidl_leaudio_config_2_2(
|
||||
audio_config.get<AudioConfiguration::leAudioConfig>()));
|
||||
break;
|
||||
case AudioConfiguration::leAudioBroadcastConfig:
|
||||
hidl_audio_config.leAudioConfig(to_hidl_leaudio_broadcast_config_2_2(
|
||||
audio_config.get<AudioConfiguration::leAudioBroadcastConfig>()));
|
||||
break;
|
||||
}
|
||||
return hidl_audio_config;
|
||||
}
|
||||
|
||||
/***
|
||||
*
|
||||
* 2.0
|
||||
|
@ -568,18 +494,58 @@ bool HidlToAidlMiddleware_2_0::IsSessionReady(
|
|||
uint16_t HidlToAidlMiddleware_2_0::RegisterControlResultCback(
|
||||
const SessionType_2_0& session_type,
|
||||
const PortStatusCallbacks_2_0& cbacks) {
|
||||
PortStatusCallbacks_2_2 callback_2_2{
|
||||
.control_result_cb_ = cbacks.control_result_cb_,
|
||||
.session_changed_cb_ = cbacks.session_changed_cb_,
|
||||
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);
|
||||
};
|
||||
};
|
||||
return HidlToAidlMiddleware_2_2::RegisterControlResultCback(
|
||||
static_cast<SessionType_2_1>(session_type), callback_2_2);
|
||||
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) {
|
||||
HidlToAidlMiddleware_2_2::UnregisterControlResultCback(
|
||||
static_cast<SessionType_2_1>(session_type), 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(
|
||||
|
@ -659,124 +625,6 @@ const AudioConfig_2_1 HidlToAidlMiddleware_2_1::GetAudioConfig(
|
|||
from_session_type_2_1(session_type)));
|
||||
}
|
||||
|
||||
/***
|
||||
*
|
||||
* 2.2
|
||||
*
|
||||
***/
|
||||
|
||||
bool HidlToAidlMiddleware_2_2::IsSessionReady(
|
||||
const SessionType_2_1& session_type) {
|
||||
return BluetoothAudioSessionControl::IsSessionReady(
|
||||
from_session_type_2_1(session_type));
|
||||
}
|
||||
|
||||
uint16_t HidlToAidlMiddleware_2_2::RegisterControlResultCback(
|
||||
const SessionType_2_1& session_type,
|
||||
const PortStatusCallbacks_2_2& cbacks) {
|
||||
LOG(INFO) << __func__ << ": " << toString(session_type);
|
||||
auto aidl_session_type = from_session_type_2_1(session_type);
|
||||
// Pass the exact reference to the lambda
|
||||
auto& session_legacy_callback_table =
|
||||
legacy_callback_table[aidl_session_type];
|
||||
PortStatusCallbacks aidl_callbacks{};
|
||||
if (cbacks.control_result_cb_) {
|
||||
aidl_callbacks.control_result_cb_ =
|
||||
[&session_legacy_callback_table](uint16_t cookie, bool start_resp,
|
||||
const BluetoothAudioStatus& status) {
|
||||
if (session_legacy_callback_table.find(cookie) ==
|
||||
session_legacy_callback_table.end()) {
|
||||
LOG(ERROR) << __func__ << ": Unknown callback invoked!";
|
||||
return;
|
||||
}
|
||||
auto& cback = session_legacy_callback_table[cookie];
|
||||
cback->control_result_cb_(cookie, start_resp, to_hidl_status(status));
|
||||
};
|
||||
}
|
||||
if (cbacks.session_changed_cb_) {
|
||||
aidl_callbacks.session_changed_cb_ =
|
||||
[&session_legacy_callback_table](uint16_t cookie) {
|
||||
if (session_legacy_callback_table.find(cookie) ==
|
||||
session_legacy_callback_table.end()) {
|
||||
LOG(ERROR) << __func__ << ": Unknown callback invoked!";
|
||||
return;
|
||||
}
|
||||
auto& cback = session_legacy_callback_table[cookie];
|
||||
cback->session_changed_cb_(cookie);
|
||||
};
|
||||
};
|
||||
if (cbacks.audio_configuration_changed_cb_) {
|
||||
aidl_callbacks.audio_configuration_changed_cb_ =
|
||||
[&session_legacy_callback_table](uint16_t cookie) {
|
||||
if (session_legacy_callback_table.find(cookie) ==
|
||||
session_legacy_callback_table.end()) {
|
||||
LOG(ERROR) << __func__ << ": Unknown callback invoked!";
|
||||
return;
|
||||
}
|
||||
auto& cback = session_legacy_callback_table[cookie];
|
||||
cback->audio_configuration_changed_cb_(cookie);
|
||||
};
|
||||
};
|
||||
auto cookie = BluetoothAudioSessionControl::RegisterControlResultCback(
|
||||
aidl_session_type, aidl_callbacks);
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(legacy_callback_lock);
|
||||
session_legacy_callback_table[cookie] =
|
||||
std::make_shared<PortStatusCallbacks_2_2>(cbacks);
|
||||
}
|
||||
return cookie;
|
||||
}
|
||||
|
||||
void HidlToAidlMiddleware_2_2::UnregisterControlResultCback(
|
||||
const SessionType_2_1& session_type, uint16_t cookie) {
|
||||
LOG(INFO) << __func__ << ": " << toString(session_type);
|
||||
auto aidl_session_type = from_session_type_2_1(session_type);
|
||||
BluetoothAudioSessionControl::UnregisterControlResultCback(aidl_session_type,
|
||||
cookie);
|
||||
auto& session_callback_table = legacy_callback_table[aidl_session_type];
|
||||
if (session_callback_table.find(cookie) != session_callback_table.end()) {
|
||||
std::lock_guard<std::mutex> guard(legacy_callback_lock);
|
||||
session_callback_table.erase(cookie);
|
||||
}
|
||||
}
|
||||
|
||||
const AudioConfig_2_2 HidlToAidlMiddleware_2_2::GetAudioConfig(
|
||||
const SessionType_2_1& session_type) {
|
||||
return to_hidl_audio_config_2_2(BluetoothAudioSessionControl::GetAudioConfig(
|
||||
from_session_type_2_1(session_type)));
|
||||
}
|
||||
|
||||
bool HidlToAidlMiddleware_2_2::StartStream(
|
||||
const SessionType_2_1& session_type) {
|
||||
return BluetoothAudioSessionControl::StartStream(
|
||||
from_session_type_2_1(session_type));
|
||||
}
|
||||
|
||||
bool HidlToAidlMiddleware_2_2::SuspendStream(
|
||||
const SessionType_2_1& session_type) {
|
||||
return BluetoothAudioSessionControl::SuspendStream(
|
||||
from_session_type_2_1(session_type));
|
||||
}
|
||||
|
||||
void HidlToAidlMiddleware_2_2::StopStream(const SessionType_2_1& session_type) {
|
||||
return BluetoothAudioSessionControl::StopStream(
|
||||
from_session_type_2_1(session_type));
|
||||
}
|
||||
|
||||
void HidlToAidlMiddleware_2_2::UpdateTracksMetadata(
|
||||
const SessionType_2_1& session_type,
|
||||
const struct source_metadata* source_metadata) {
|
||||
return BluetoothAudioSessionControl::UpdateSourceMetadata(
|
||||
from_session_type_2_1(session_type), *source_metadata);
|
||||
}
|
||||
|
||||
void HidlToAidlMiddleware_2_2::UpdateSinkMetadata(
|
||||
const SessionType_2_1& session_type,
|
||||
const struct sink_metadata* sink_metadata) {
|
||||
return BluetoothAudioSessionControl::UpdateSinkMetadata(
|
||||
from_session_type_2_1(session_type), *sink_metadata);
|
||||
}
|
||||
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace hardware
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <android/hardware/bluetooth/audio/2.2/types.h>
|
||||
|
||||
#include "../session/BluetoothAudioSession.h"
|
||||
#include "../session/BluetoothAudioSession_2_2.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
|
||||
using SessionType_2_1 =
|
||||
::android::hardware::bluetooth::audio::V2_1::SessionType;
|
||||
using PortStatusCallbacks_2_0 =
|
||||
::android::bluetooth::audio::PortStatusCallbacks;
|
||||
using PortStatusCallbacks_2_2 =
|
||||
::android::bluetooth::audio::PortStatusCallbacks_2_2;
|
||||
using AudioConfig_2_2 =
|
||||
::android::hardware::bluetooth::audio::V2_2::AudioConfiguration;
|
||||
|
||||
class HidlToAidlMiddleware_2_2 {
|
||||
public:
|
||||
static bool IsSessionReady(const SessionType_2_1& session_type);
|
||||
|
||||
static uint16_t RegisterControlResultCback(
|
||||
const SessionType_2_1& session_type,
|
||||
const PortStatusCallbacks_2_2& cbacks);
|
||||
|
||||
static void UnregisterControlResultCback(const SessionType_2_1& session_type,
|
||||
uint16_t cookie);
|
||||
|
||||
static const AudioConfig_2_2 GetAudioConfig(
|
||||
const SessionType_2_1& session_type);
|
||||
|
||||
static bool StartStream(const SessionType_2_1& session_type);
|
||||
|
||||
static bool SuspendStream(const SessionType_2_1& session_type);
|
||||
|
||||
static void StopStream(const SessionType_2_1& session_type);
|
||||
|
||||
static void UpdateTracksMetadata(
|
||||
const SessionType_2_1& session_type,
|
||||
const struct source_metadata* source_metadata);
|
||||
|
||||
static void UpdateSinkMetadata(const SessionType_2_1& session_type,
|
||||
const struct sink_metadata* sink_metadata);
|
||||
};
|
||||
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
|
@ -1,193 +0,0 @@
|
|||
/*
|
||||
* Copyright 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BluetoothAudioSession_2_2.h"
|
||||
|
||||
namespace android {
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
|
||||
class BluetoothAudioSessionControl_2_2 {
|
||||
using SessionType_2_1 =
|
||||
::android::hardware::bluetooth::audio::V2_1::SessionType;
|
||||
using AudioConfiguration_2_2 =
|
||||
::android::hardware::bluetooth::audio::V2_2::AudioConfiguration;
|
||||
|
||||
public:
|
||||
// The control API helps to check if session is ready or not
|
||||
// @return: true if the Bluetooth stack has started th specified session
|
||||
static bool IsSessionReady(const SessionType_2_1& session_type) {
|
||||
std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
|
||||
BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
|
||||
if (session_ptr != nullptr) {
|
||||
return session_ptr->IsSessionReady();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// The control API helps the bluetooth_audio module to register
|
||||
// PortStatusCallbacks
|
||||
// @return: cookie - the assigned number to this bluetooth_audio output
|
||||
static uint16_t RegisterControlResultCback(
|
||||
const SessionType_2_1& session_type, const PortStatusCallbacks& cbacks) {
|
||||
std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
|
||||
BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
|
||||
if (session_ptr != nullptr) {
|
||||
PortStatusCallbacks_2_2 cb = {
|
||||
.control_result_cb_ = cbacks.control_result_cb_,
|
||||
.session_changed_cb_ = cbacks.session_changed_cb_,
|
||||
.audio_configuration_changed_cb_ = nullptr};
|
||||
return session_ptr->RegisterStatusCback(cb);
|
||||
}
|
||||
return kObserversCookieUndefined;
|
||||
}
|
||||
|
||||
// The control API helps the bluetooth_audio module to register
|
||||
// PortStatusCallbacks_2_2
|
||||
// @return: cookie - the assigned number to this bluetooth_audio output
|
||||
static uint16_t RegisterControlResultCback(
|
||||
const SessionType_2_1& session_type,
|
||||
const PortStatusCallbacks_2_2& cbacks) {
|
||||
std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
|
||||
BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
|
||||
if (session_ptr != nullptr) {
|
||||
return session_ptr->RegisterStatusCback(cbacks);
|
||||
}
|
||||
return kObserversCookieUndefined;
|
||||
}
|
||||
|
||||
// The control API helps the bluetooth_audio module to unregister
|
||||
// PortStatusCallbacks and PortStatusCallbacks_2_2
|
||||
// @param: cookie - indicates which bluetooth_audio output is
|
||||
static void UnregisterControlResultCback(const SessionType_2_1& session_type,
|
||||
uint16_t cookie) {
|
||||
std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
|
||||
BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
|
||||
if (session_ptr != nullptr) {
|
||||
session_ptr->UnregisterStatusCback(cookie);
|
||||
}
|
||||
}
|
||||
|
||||
// The control API for the bluetooth_audio module to get current
|
||||
// AudioConfiguration
|
||||
static const AudioConfiguration_2_2 GetAudioConfig(
|
||||
const SessionType_2_1& session_type) {
|
||||
std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
|
||||
BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
|
||||
if (session_ptr != nullptr) {
|
||||
return session_ptr->GetAudioConfig();
|
||||
} else if (session_type ==
|
||||
SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
|
||||
return BluetoothAudioSession_2_2::kInvalidOffloadAudioConfiguration;
|
||||
} else if (
|
||||
session_type ==
|
||||
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
|
||||
session_type ==
|
||||
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
|
||||
return BluetoothAudioSession_2_2::kInvalidLeOffloadAudioConfiguration;
|
||||
} else {
|
||||
return BluetoothAudioSession_2_2::kInvalidSoftwareAudioConfiguration;
|
||||
}
|
||||
}
|
||||
|
||||
// Those control APIs for the bluetooth_audio module to start / suspend / stop
|
||||
// stream, to check position, and to update metadata.
|
||||
static bool StartStream(const SessionType_2_1& session_type) {
|
||||
std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
|
||||
BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
|
||||
if (session_ptr != nullptr) {
|
||||
return session_ptr->StartStream();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool SuspendStream(const SessionType_2_1& session_type) {
|
||||
std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
|
||||
BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
|
||||
if (session_ptr != nullptr) {
|
||||
return session_ptr->SuspendStream();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void StopStream(const SessionType_2_1& session_type) {
|
||||
std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
|
||||
BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
|
||||
if (session_ptr != nullptr) {
|
||||
session_ptr->StopStream();
|
||||
}
|
||||
}
|
||||
|
||||
static bool GetPresentationPosition(const SessionType_2_1& session_type,
|
||||
uint64_t* remote_delay_report_ns,
|
||||
uint64_t* total_bytes_readed,
|
||||
timespec* data_position) {
|
||||
std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
|
||||
BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
|
||||
if (session_ptr != nullptr) {
|
||||
return session_ptr->GetAudioSession()->GetPresentationPosition(
|
||||
remote_delay_report_ns, total_bytes_readed, data_position);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void UpdateTracksMetadata(
|
||||
const SessionType_2_1& session_type,
|
||||
const struct source_metadata* source_metadata) {
|
||||
std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
|
||||
BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
|
||||
if (session_ptr != nullptr) {
|
||||
session_ptr->UpdateTracksMetadata(source_metadata);
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdateSinkMetadata(const SessionType_2_1& session_type,
|
||||
const struct sink_metadata* sink_metadata) {
|
||||
std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
|
||||
BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
|
||||
if (session_ptr != nullptr) {
|
||||
session_ptr->UpdateSinkMetadata(sink_metadata);
|
||||
}
|
||||
}
|
||||
|
||||
// The control API writes stream to FMQ
|
||||
static size_t OutWritePcmData(const SessionType_2_1& session_type,
|
||||
const void* buffer, size_t bytes) {
|
||||
std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
|
||||
BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
|
||||
if (session_ptr != nullptr) {
|
||||
return session_ptr->GetAudioSession()->OutWritePcmData(buffer, bytes);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// The control API reads stream from FMQ
|
||||
static size_t InReadPcmData(const SessionType_2_1& session_type, void* buffer,
|
||||
size_t bytes) {
|
||||
std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
|
||||
BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
|
||||
if (session_ptr != nullptr) {
|
||||
return session_ptr->GetAudioSession()->InReadPcmData(buffer, bytes);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace android
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BluetoothAudioSession_2_2.h"
|
||||
|
||||
namespace android {
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
|
||||
class BluetoothAudioSessionReport_2_2 {
|
||||
public:
|
||||
// The API reports the Bluetooth stack has started the session, and will
|
||||
// inform registered bluetooth_audio outputs
|
||||
static void OnSessionStarted(
|
||||
const ::android::hardware::bluetooth::audio::V2_1::SessionType&
|
||||
session_type,
|
||||
const sp<IBluetoothAudioPort> host_iface,
|
||||
const DataMQ::Descriptor* dataMQ,
|
||||
const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
|
||||
audio_config) {
|
||||
std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
|
||||
BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
|
||||
if (session_ptr != nullptr) {
|
||||
session_ptr->OnSessionStarted(host_iface, dataMQ, audio_config);
|
||||
}
|
||||
}
|
||||
|
||||
// The API reports the Bluetooth stack has ended the session, and will
|
||||
// inform registered bluetooth_audio outputs
|
||||
static void OnSessionEnded(
|
||||
const ::android::hardware::bluetooth::audio::V2_1::SessionType&
|
||||
session_type) {
|
||||
std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
|
||||
BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
|
||||
if (session_ptr != nullptr) {
|
||||
session_ptr->OnSessionEnded();
|
||||
}
|
||||
}
|
||||
// The API reports the Bluetooth stack has replied the result of startStream
|
||||
// or suspendStream, and will inform registered bluetooth_audio outputs
|
||||
static void ReportControlStatus(
|
||||
const ::android::hardware::bluetooth::audio::V2_1::SessionType&
|
||||
session_type,
|
||||
const bool& start_resp, const BluetoothAudioStatus& status) {
|
||||
std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
|
||||
BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
|
||||
if (session_ptr != nullptr) {
|
||||
session_ptr->ReportControlStatus(start_resp, status);
|
||||
}
|
||||
}
|
||||
// The API reports the Bluetooth stack has replied the changed of the audio
|
||||
// configuration, and will inform registered bluetooth_audio outputs
|
||||
static void ReportAudioConfigChanged(
|
||||
const ::android::hardware::bluetooth::audio::V2_1::SessionType&
|
||||
session_type,
|
||||
const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
|
||||
audio_config) {
|
||||
std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
|
||||
BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
|
||||
if (session_ptr != nullptr) {
|
||||
session_ptr->ReportAudioConfigChanged(audio_config);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace android
|
|
@ -1,636 +0,0 @@
|
|||
/*
|
||||
* Copyright 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "BTAudioProviderSession_2_2"
|
||||
|
||||
#include "BluetoothAudioSession_2_2.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <android/hardware/bluetooth/audio/2.2/IBluetoothAudioPort.h>
|
||||
|
||||
#include "../aidl_session/HidlToAidlMiddleware_2_0.h"
|
||||
#include "../aidl_session/HidlToAidlMiddleware_2_2.h"
|
||||
|
||||
namespace android {
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
|
||||
using ::aidl::android::hardware::bluetooth::audio::HidlToAidlMiddleware_2_0;
|
||||
using ::aidl::android::hardware::bluetooth::audio::HidlToAidlMiddleware_2_2;
|
||||
using ::android::hardware::audio::common::V5_0::AudioContentType;
|
||||
using ::android::hardware::audio::common::V5_0::AudioSource;
|
||||
using ::android::hardware::audio::common::V5_0::AudioUsage;
|
||||
using ::android::hardware::audio::common::V5_0::PlaybackTrackMetadata;
|
||||
using ::android::hardware::audio::common::V5_0::RecordTrackMetadata;
|
||||
using ::android::hardware::audio::common::V5_0::SinkMetadata;
|
||||
using ::android::hardware::audio::common::V5_0::SourceMetadata;
|
||||
using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
|
||||
using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
|
||||
using ::android::hardware::bluetooth::audio::V2_2::LeAudioConfiguration;
|
||||
using ::android::hardware::bluetooth::audio::V2_2::LeAudioMode;
|
||||
using PcmParameters_2_1 =
|
||||
::android::hardware::bluetooth::audio::V2_1::PcmParameters;
|
||||
using SampleRate_2_1 = ::android::hardware::bluetooth::audio::V2_1::SampleRate;
|
||||
|
||||
using SessionType_2_1 =
|
||||
::android::hardware::bluetooth::audio::V2_1::SessionType;
|
||||
using SessionType_2_0 =
|
||||
::android::hardware::bluetooth::audio::V2_0::SessionType;
|
||||
|
||||
using AudioConfiguration_2_1 =
|
||||
::android::hardware::bluetooth::audio::V2_1::AudioConfiguration;
|
||||
|
||||
static constexpr PcmParameters_2_1 kInvalidPcmParameters = {
|
||||
.sampleRate = SampleRate_2_1::RATE_UNKNOWN,
|
||||
.channelMode = ChannelMode::UNKNOWN,
|
||||
.bitsPerSample = BitsPerSample::BITS_UNKNOWN,
|
||||
.dataIntervalUs = 0,
|
||||
};
|
||||
|
||||
static LeAudioConfiguration kInvalidLeAudioConfig = {
|
||||
.mode = LeAudioMode::UNKNOWN,
|
||||
.config = {},
|
||||
};
|
||||
|
||||
::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
|
||||
BluetoothAudioSession_2_2::invalidSoftwareAudioConfiguration = {};
|
||||
::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
|
||||
BluetoothAudioSession_2_2::invalidOffloadAudioConfiguration = {};
|
||||
::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
|
||||
BluetoothAudioSession_2_2::invalidLeOffloadAudioConfiguration = {};
|
||||
|
||||
using IBluetoothAudioPort_2_2 =
|
||||
::android::hardware::bluetooth::audio::V2_2::IBluetoothAudioPort;
|
||||
|
||||
namespace {
|
||||
bool is_2_0_session_type(
|
||||
const ::android::hardware::bluetooth::audio::V2_1::SessionType&
|
||||
session_type) {
|
||||
if (session_type == SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH ||
|
||||
session_type == SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH ||
|
||||
session_type == SessionType_2_1::HEARING_AID_SOFTWARE_ENCODING_DATAPATH) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
BluetoothAudioSession_2_2::BluetoothAudioSession_2_2(
|
||||
const ::android::hardware::bluetooth::audio::V2_1::SessionType&
|
||||
session_type)
|
||||
: audio_session(BluetoothAudioSessionInstance::GetSessionInstance(
|
||||
static_cast<SessionType_2_0>(session_type))),
|
||||
audio_session_2_1(
|
||||
BluetoothAudioSessionInstance_2_1::GetSessionInstance(session_type)) {
|
||||
if (is_2_0_session_type(session_type)) {
|
||||
session_type_2_1_ = (SessionType_2_1::UNKNOWN);
|
||||
} else {
|
||||
session_type_2_1_ = (session_type);
|
||||
}
|
||||
raw_session_type_ = session_type;
|
||||
invalidSoftwareAudioConfiguration.pcmConfig(kInvalidPcmParameters);
|
||||
invalidOffloadAudioConfiguration.codecConfig(
|
||||
audio_session->kInvalidCodecConfiguration);
|
||||
invalidLeOffloadAudioConfiguration.leAudioConfig(kInvalidLeAudioConfig);
|
||||
}
|
||||
|
||||
bool BluetoothAudioSession_2_2::IsSessionReady() {
|
||||
if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
|
||||
return HidlToAidlMiddleware_2_2::IsSessionReady(raw_session_type_);
|
||||
if (session_type_2_1_ !=
|
||||
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
|
||||
session_type_2_1_ !=
|
||||
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
|
||||
return audio_session->IsSessionReady();
|
||||
}
|
||||
|
||||
std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
|
||||
return audio_session->stack_iface_ != nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<BluetoothAudioSession>
|
||||
BluetoothAudioSession_2_2::GetAudioSession() {
|
||||
return audio_session;
|
||||
}
|
||||
std::shared_ptr<BluetoothAudioSession_2_1>
|
||||
BluetoothAudioSession_2_2::GetAudioSession_2_1() {
|
||||
return audio_session_2_1;
|
||||
}
|
||||
|
||||
void BluetoothAudioSession_2_2::UpdateTracksMetadata(
|
||||
const struct source_metadata* source_metadata) {
|
||||
if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
|
||||
return HidlToAidlMiddleware_2_2::UpdateTracksMetadata(raw_session_type_,
|
||||
source_metadata);
|
||||
std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
|
||||
if (!IsSessionReady()) {
|
||||
LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_2_1_)
|
||||
<< " has NO session";
|
||||
return;
|
||||
}
|
||||
|
||||
ssize_t track_count = source_metadata->track_count;
|
||||
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_2_1_)
|
||||
<< ", " << track_count << " track(s)";
|
||||
|
||||
if (session_type_2_1_ == SessionType_2_1::UNKNOWN) {
|
||||
audio_session->UpdateTracksMetadata(source_metadata);
|
||||
return;
|
||||
}
|
||||
|
||||
struct playback_track_metadata* track = source_metadata->tracks;
|
||||
SourceMetadata sourceMetadata;
|
||||
PlaybackTrackMetadata* halMetadata;
|
||||
|
||||
sourceMetadata.tracks.resize(track_count);
|
||||
halMetadata = sourceMetadata.tracks.data();
|
||||
while (track_count && track) {
|
||||
halMetadata->usage = static_cast<AudioUsage>(track->usage);
|
||||
halMetadata->contentType =
|
||||
static_cast<AudioContentType>(track->content_type);
|
||||
halMetadata->gain = track->gain;
|
||||
LOG(VERBOSE) << __func__ << " - SessionType=" << toString(session_type_2_1_)
|
||||
<< ", usage=" << toString(halMetadata->usage)
|
||||
<< ", content=" << toString(halMetadata->contentType)
|
||||
<< ", gain=" << halMetadata->gain;
|
||||
--track_count;
|
||||
++track;
|
||||
++halMetadata;
|
||||
}
|
||||
auto hal_retval = audio_session->stack_iface_->updateMetadata(sourceMetadata);
|
||||
if (!hal_retval.isOk()) {
|
||||
LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
|
||||
<< toString(session_type_2_1_) << " failed";
|
||||
}
|
||||
}
|
||||
|
||||
void BluetoothAudioSession_2_2::UpdateSinkMetadata(
|
||||
const struct sink_metadata* sink_metadata) {
|
||||
if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
|
||||
return HidlToAidlMiddleware_2_2::UpdateSinkMetadata(raw_session_type_,
|
||||
sink_metadata);
|
||||
std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
|
||||
if (!IsSessionReady()) {
|
||||
LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_2_1_)
|
||||
<< " has NO session";
|
||||
return;
|
||||
}
|
||||
|
||||
ssize_t track_count = sink_metadata->track_count;
|
||||
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_2_1_)
|
||||
<< ", " << track_count << " track(s)";
|
||||
if (session_type_2_1_ == SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH ||
|
||||
session_type_2_1_ == SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct record_track_metadata* track = sink_metadata->tracks;
|
||||
SinkMetadata sinkMetadata;
|
||||
RecordTrackMetadata* halMetadata;
|
||||
|
||||
sinkMetadata.tracks.resize(track_count);
|
||||
halMetadata = sinkMetadata.tracks.data();
|
||||
while (track_count && track) {
|
||||
halMetadata->source = static_cast<AudioSource>(track->source);
|
||||
halMetadata->gain = track->gain;
|
||||
// halMetadata->destination leave unspecified
|
||||
LOG(INFO) << __func__
|
||||
<< " - SessionType=" << toString(GetAudioSession()->session_type_)
|
||||
<< ", source=" << track->source
|
||||
<< ", dest_device=" << track->dest_device
|
||||
<< ", gain=" << track->gain
|
||||
<< ", dest_device_address=" << track->dest_device_address;
|
||||
--track_count;
|
||||
++track;
|
||||
++halMetadata;
|
||||
}
|
||||
|
||||
/* This is called just for 2.2 sessions, so it's safe to do this casting*/
|
||||
IBluetoothAudioPort_2_2* stack_iface_2_2_ =
|
||||
static_cast<IBluetoothAudioPort_2_2*>(audio_session->stack_iface_.get());
|
||||
auto hal_retval = stack_iface_2_2_->updateSinkMetadata(sinkMetadata);
|
||||
if (!hal_retval.isOk()) {
|
||||
LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
|
||||
<< toString(session_type_2_1_) << " failed";
|
||||
}
|
||||
}
|
||||
|
||||
// The control function is for the bluetooth_audio module to get the current
|
||||
// AudioConfiguration
|
||||
const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
|
||||
BluetoothAudioSession_2_2::GetAudioConfig() {
|
||||
if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
|
||||
return HidlToAidlMiddleware_2_2::GetAudioConfig(raw_session_type_);
|
||||
std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
|
||||
if (IsSessionReady()) {
|
||||
auto audio_config_discriminator = audio_config_2_2_.getDiscriminator();
|
||||
// If session is unknown it means it should be 2.0 type
|
||||
if (session_type_2_1_ != SessionType_2_1::UNKNOWN) {
|
||||
if ((audio_config_discriminator ==
|
||||
::android::hardware::bluetooth::audio::V2_2::AudioConfiguration::
|
||||
hidl_discriminator::pcmConfig &&
|
||||
audio_config_2_2_ != kInvalidSoftwareAudioConfiguration) ||
|
||||
(audio_config_discriminator ==
|
||||
::android::hardware::bluetooth::audio::V2_2::AudioConfiguration::
|
||||
hidl_discriminator::leAudioConfig &&
|
||||
audio_config_2_2_ != kInvalidLeOffloadAudioConfiguration))
|
||||
return audio_config_2_2_;
|
||||
|
||||
::android::hardware::bluetooth::audio::V2_2::AudioConfiguration toConf;
|
||||
const AudioConfiguration_2_1 fromConf =
|
||||
GetAudioSession_2_1()->GetAudioConfig();
|
||||
if (fromConf.getDiscriminator() ==
|
||||
AudioConfiguration_2_1::hidl_discriminator::pcmConfig) {
|
||||
toConf.pcmConfig(fromConf.pcmConfig());
|
||||
return toConf;
|
||||
}
|
||||
}
|
||||
|
||||
::android::hardware::bluetooth::audio::V2_2::AudioConfiguration toConf;
|
||||
const AudioConfiguration fromConf = GetAudioSession()->GetAudioConfig();
|
||||
// pcmConfig only differs between 2.0 and 2.1 in AudioConfiguration
|
||||
if (fromConf.getDiscriminator() ==
|
||||
AudioConfiguration::hidl_discriminator::codecConfig) {
|
||||
toConf.codecConfig(fromConf.codecConfig());
|
||||
} else {
|
||||
toConf.pcmConfig() = {
|
||||
.sampleRate = static_cast<
|
||||
::android::hardware::bluetooth::audio::V2_1::SampleRate>(
|
||||
fromConf.pcmConfig().sampleRate),
|
||||
.channelMode = fromConf.pcmConfig().channelMode,
|
||||
.bitsPerSample = fromConf.pcmConfig().bitsPerSample,
|
||||
.dataIntervalUs = 0};
|
||||
}
|
||||
return toConf;
|
||||
} else if (session_type_2_1_ ==
|
||||
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
|
||||
session_type_2_1_ ==
|
||||
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
|
||||
return kInvalidLeOffloadAudioConfiguration;
|
||||
} else {
|
||||
return kInvalidSoftwareAudioConfiguration;
|
||||
}
|
||||
}
|
||||
|
||||
// Those control functions are for the bluetooth_audio module to start, suspend,
|
||||
// stop stream, to check position, and to update metadata.
|
||||
bool BluetoothAudioSession_2_2::StartStream() {
|
||||
if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
|
||||
return HidlToAidlMiddleware_2_2::StartStream(raw_session_type_);
|
||||
std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
|
||||
if (!IsSessionReady()) {
|
||||
LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_2_1_)
|
||||
<< " has NO session";
|
||||
return false;
|
||||
}
|
||||
auto hal_retval = audio_session->stack_iface_->startStream();
|
||||
if (!hal_retval.isOk()) {
|
||||
LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
|
||||
<< toString(session_type_2_1_) << " failed";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BluetoothAudioSession_2_2::SuspendStream() {
|
||||
if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
|
||||
return HidlToAidlMiddleware_2_2::SuspendStream(raw_session_type_);
|
||||
std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
|
||||
if (!IsSessionReady()) {
|
||||
LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_2_1_)
|
||||
<< " has NO session";
|
||||
return false;
|
||||
}
|
||||
auto hal_retval = audio_session->stack_iface_->suspendStream();
|
||||
if (!hal_retval.isOk()) {
|
||||
LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
|
||||
<< toString(session_type_2_1_) << " failed";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void BluetoothAudioSession_2_2::StopStream() {
|
||||
if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
|
||||
return HidlToAidlMiddleware_2_2::StopStream(raw_session_type_);
|
||||
std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
|
||||
if (!IsSessionReady()) {
|
||||
return;
|
||||
}
|
||||
auto hal_retval = audio_session->stack_iface_->stopStream();
|
||||
if (!hal_retval.isOk()) {
|
||||
LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
|
||||
<< toString(session_type_2_1_) << " failed";
|
||||
}
|
||||
}
|
||||
|
||||
bool BluetoothAudioSession_2_2::UpdateAudioConfig(
|
||||
const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
|
||||
audio_config) {
|
||||
bool is_software_session =
|
||||
(session_type_2_1_ == SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH ||
|
||||
session_type_2_1_ ==
|
||||
SessionType_2_1::HEARING_AID_SOFTWARE_ENCODING_DATAPATH ||
|
||||
session_type_2_1_ ==
|
||||
SessionType_2_1::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH ||
|
||||
session_type_2_1_ ==
|
||||
SessionType_2_1::LE_AUDIO_SOFTWARE_DECODED_DATAPATH);
|
||||
bool is_offload_a2dp_session =
|
||||
(session_type_2_1_ == SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH);
|
||||
bool is_offload_le_audio_session =
|
||||
(session_type_2_1_ ==
|
||||
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
|
||||
session_type_2_1_ ==
|
||||
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
|
||||
auto audio_config_discriminator = audio_config.getDiscriminator();
|
||||
bool is_software_audio_config =
|
||||
(is_software_session &&
|
||||
audio_config_discriminator ==
|
||||
::android::hardware::bluetooth::audio::V2_2::AudioConfiguration::
|
||||
hidl_discriminator::pcmConfig);
|
||||
bool is_a2dp_offload_audio_config =
|
||||
(is_offload_a2dp_session &&
|
||||
audio_config_discriminator ==
|
||||
::android::hardware::bluetooth::audio::V2_2::AudioConfiguration::
|
||||
hidl_discriminator::codecConfig);
|
||||
bool is_le_audio_offload_audio_config =
|
||||
(is_offload_le_audio_session &&
|
||||
audio_config_discriminator ==
|
||||
::android::hardware::bluetooth::audio::V2_2::AudioConfiguration::
|
||||
hidl_discriminator::leAudioConfig);
|
||||
if (!is_software_audio_config && !is_a2dp_offload_audio_config &&
|
||||
!is_le_audio_offload_audio_config) {
|
||||
return false;
|
||||
}
|
||||
audio_config_2_2_ = audio_config;
|
||||
return true;
|
||||
}
|
||||
|
||||
// The report function is used to report that the Bluetooth stack has started
|
||||
// this session without any failure, and will invoke session_changed_cb_ to
|
||||
// notify those registered bluetooth_audio outputs
|
||||
void BluetoothAudioSession_2_2::OnSessionStarted(
|
||||
const sp<IBluetoothAudioPort> stack_iface, const DataMQ::Descriptor* dataMQ,
|
||||
const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
|
||||
audio_config) {
|
||||
if (session_type_2_1_ == SessionType_2_1::UNKNOWN) {
|
||||
::android::hardware::bluetooth::audio::V2_0::AudioConfiguration config;
|
||||
if (audio_config.getDiscriminator() ==
|
||||
::android::hardware::bluetooth::audio::V2_2::AudioConfiguration::
|
||||
hidl_discriminator::codecConfig) {
|
||||
config.codecConfig(audio_config.codecConfig());
|
||||
} else {
|
||||
auto& tmpPcm = audio_config.pcmConfig();
|
||||
config.pcmConfig(
|
||||
::android::hardware::bluetooth::audio::V2_0::PcmParameters{
|
||||
.sampleRate = static_cast<SampleRate>(tmpPcm.sampleRate),
|
||||
.channelMode = tmpPcm.channelMode,
|
||||
.bitsPerSample = tmpPcm.bitsPerSample
|
||||
/*dataIntervalUs is not passed to 2.0 */
|
||||
});
|
||||
}
|
||||
|
||||
audio_session->OnSessionStarted(stack_iface, dataMQ, config);
|
||||
} else {
|
||||
std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
|
||||
if (stack_iface == nullptr) {
|
||||
LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_2_1_)
|
||||
<< ", IBluetoothAudioPort Invalid";
|
||||
} else if (!UpdateAudioConfig(audio_config)) {
|
||||
LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_2_1_)
|
||||
<< ", AudioConfiguration=" << toString(audio_config)
|
||||
<< " Invalid";
|
||||
} else if (!audio_session->UpdateDataPath(dataMQ)) {
|
||||
LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_2_1_)
|
||||
<< " DataMQ Invalid";
|
||||
audio_config_2_2_ =
|
||||
((session_type_2_1_ ==
|
||||
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
|
||||
session_type_2_1_ ==
|
||||
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH)
|
||||
? kInvalidLeOffloadAudioConfiguration
|
||||
: kInvalidSoftwareAudioConfiguration);
|
||||
} else {
|
||||
audio_session->stack_iface_ = stack_iface;
|
||||
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_2_1_)
|
||||
<< ", AudioConfiguration=" << toString(audio_config);
|
||||
ReportSessionStatus();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// The report function is used to report that the Bluetooth stack has ended the
|
||||
// session, and will invoke session_changed_cb_ to notify registered
|
||||
// bluetooth_audio outputs
|
||||
void BluetoothAudioSession_2_2::OnSessionEnded() {
|
||||
std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
|
||||
bool toggled = IsSessionReady();
|
||||
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_2_1_);
|
||||
if (session_type_2_1_ == SessionType_2_1::UNKNOWN) {
|
||||
audio_session->OnSessionEnded();
|
||||
return;
|
||||
}
|
||||
|
||||
audio_config_2_2_ =
|
||||
((session_type_2_1_ ==
|
||||
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
|
||||
session_type_2_1_ ==
|
||||
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH)
|
||||
? kInvalidLeOffloadAudioConfiguration
|
||||
: kInvalidSoftwareAudioConfiguration);
|
||||
audio_session->stack_iface_ = nullptr;
|
||||
audio_session->UpdateDataPath(nullptr);
|
||||
if (toggled) {
|
||||
ReportSessionStatus();
|
||||
}
|
||||
}
|
||||
|
||||
// The control function helps the bluetooth_audio module to register
|
||||
// PortStatusCallbacks_2_2
|
||||
// @return: cookie - the assigned number to this bluetooth_audio output
|
||||
uint16_t BluetoothAudioSession_2_2::RegisterStatusCback(
|
||||
const PortStatusCallbacks_2_2& cbacks) {
|
||||
if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
|
||||
return HidlToAidlMiddleware_2_2::RegisterControlResultCback(
|
||||
raw_session_type_, cbacks);
|
||||
if (session_type_2_1_ !=
|
||||
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
|
||||
session_type_2_1_ !=
|
||||
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
|
||||
PortStatusCallbacks cb = {
|
||||
.control_result_cb_ = cbacks.control_result_cb_,
|
||||
.session_changed_cb_ = cbacks.session_changed_cb_};
|
||||
return audio_session->RegisterStatusCback(cb);
|
||||
}
|
||||
|
||||
std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
|
||||
uint16_t cookie = ObserversCookieGetInitValue(session_type_2_1_);
|
||||
uint16_t cookie_upper_bound = ObserversCookieGetUpperBound(session_type_2_1_);
|
||||
|
||||
while (cookie < cookie_upper_bound) {
|
||||
if (observers_.find(cookie) == observers_.end()) {
|
||||
break;
|
||||
}
|
||||
++cookie;
|
||||
}
|
||||
if (cookie >= cookie_upper_bound) {
|
||||
LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_2_1_)
|
||||
<< " has " << observers_.size()
|
||||
<< " observers already (No Resource)";
|
||||
return kObserversCookieUndefined;
|
||||
}
|
||||
std::shared_ptr<struct PortStatusCallbacks_2_2> cb =
|
||||
std::make_shared<struct PortStatusCallbacks_2_2>();
|
||||
*cb = cbacks;
|
||||
observers_[cookie] = cb;
|
||||
return cookie;
|
||||
}
|
||||
|
||||
// The control function helps the bluetooth_audio module to unregister
|
||||
// PortStatusCallbacks_2_2
|
||||
// @param: cookie - indicates which bluetooth_audio output is
|
||||
void BluetoothAudioSession_2_2::UnregisterStatusCback(uint16_t cookie) {
|
||||
if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
|
||||
return HidlToAidlMiddleware_2_2::UnregisterControlResultCback(
|
||||
raw_session_type_, cookie);
|
||||
std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
|
||||
if (session_type_2_1_ !=
|
||||
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
|
||||
session_type_2_1_ !=
|
||||
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
|
||||
audio_session->UnregisterStatusCback(cookie);
|
||||
return;
|
||||
}
|
||||
if (observers_.erase(cookie) != 1) {
|
||||
LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_2_1_)
|
||||
<< " no such provider=0x"
|
||||
<< android::base::StringPrintf("%04x", cookie);
|
||||
}
|
||||
}
|
||||
|
||||
// invoking the registered session_changed_cb_
|
||||
void BluetoothAudioSession_2_2::ReportSessionStatus() {
|
||||
// This is locked already by OnSessionStarted / OnSessionEnded
|
||||
if (session_type_2_1_ !=
|
||||
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
|
||||
session_type_2_1_ !=
|
||||
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
|
||||
audio_session->ReportSessionStatus();
|
||||
return;
|
||||
}
|
||||
if (observers_.empty()) {
|
||||
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_2_1_)
|
||||
<< " has NO port state observer";
|
||||
return;
|
||||
}
|
||||
for (auto& observer : observers_) {
|
||||
uint16_t cookie = observer.first;
|
||||
std::shared_ptr<struct PortStatusCallbacks_2_2> cb = observer.second;
|
||||
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_2_1_)
|
||||
<< " notify to bluetooth_audio=0x"
|
||||
<< android::base::StringPrintf("%04x", cookie);
|
||||
cb->session_changed_cb_(cookie);
|
||||
}
|
||||
}
|
||||
|
||||
// The report function is used to report that the Bluetooth stack has notified
|
||||
// the result of startStream or suspendStream, and will invoke
|
||||
// control_result_cb_ to notify registered bluetooth_audio outputs
|
||||
void BluetoothAudioSession_2_2::ReportControlStatus(
|
||||
bool start_resp, const BluetoothAudioStatus& status) {
|
||||
if (session_type_2_1_ !=
|
||||
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
|
||||
session_type_2_1_ !=
|
||||
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
|
||||
audio_session->ReportControlStatus(start_resp, status);
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
|
||||
if (observers_.empty()) {
|
||||
LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_2_1_)
|
||||
<< " has NO port state observer";
|
||||
return;
|
||||
}
|
||||
for (auto& observer : observers_) {
|
||||
uint16_t cookie = observer.first;
|
||||
std::shared_ptr<struct PortStatusCallbacks_2_2> cb = observer.second;
|
||||
LOG(INFO) << __func__ << " - status=" << toString(status)
|
||||
<< " for SessionType=" << toString(session_type_2_1_)
|
||||
<< ", bluetooth_audio=0x"
|
||||
<< android::base::StringPrintf("%04x", cookie)
|
||||
<< (start_resp ? " started" : " suspended");
|
||||
cb->control_result_cb_(cookie, start_resp, status);
|
||||
}
|
||||
}
|
||||
|
||||
// The report function is used to report that the Bluetooth stack has notified
|
||||
// the result of startStream or suspendStream, and will invoke
|
||||
// control_result_cb_ to notify registered bluetooth_audio outputs
|
||||
void BluetoothAudioSession_2_2::ReportAudioConfigChanged(
|
||||
const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
|
||||
audio_config) {
|
||||
if (session_type_2_1_ !=
|
||||
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
|
||||
session_type_2_1_ !=
|
||||
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
|
||||
audio_config_2_2_ = audio_config;
|
||||
if (observers_.empty()) {
|
||||
LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_2_1_)
|
||||
<< " has NO port state observer";
|
||||
return;
|
||||
}
|
||||
for (auto& observer : observers_) {
|
||||
uint16_t cookie = observer.first;
|
||||
std::shared_ptr<struct PortStatusCallbacks_2_2> cb = observer.second;
|
||||
LOG(INFO) << __func__ << " for SessionType=" << toString(session_type_2_1_)
|
||||
<< ", bluetooth_audio=0x"
|
||||
<< android::base::StringPrintf("%04x", cookie);
|
||||
if (cb->audio_configuration_changed_cb_ != nullptr) {
|
||||
cb->audio_configuration_changed_cb_(cookie);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<BluetoothAudioSessionInstance_2_2>
|
||||
BluetoothAudioSessionInstance_2_2::instance_ptr =
|
||||
std::unique_ptr<BluetoothAudioSessionInstance_2_2>(
|
||||
new BluetoothAudioSessionInstance_2_2());
|
||||
|
||||
// API to fetch the session of A2DP / Hearing Aid
|
||||
std::shared_ptr<BluetoothAudioSession_2_2>
|
||||
BluetoothAudioSessionInstance_2_2::GetSessionInstance(
|
||||
const SessionType_2_1& session_type) {
|
||||
std::lock_guard<std::mutex> guard(instance_ptr->mutex_);
|
||||
if (!instance_ptr->sessions_map_.empty()) {
|
||||
auto entry = instance_ptr->sessions_map_.find(session_type);
|
||||
if (entry != instance_ptr->sessions_map_.end()) {
|
||||
return entry->second;
|
||||
}
|
||||
}
|
||||
std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
|
||||
std::make_shared<BluetoothAudioSession_2_2>(session_type);
|
||||
instance_ptr->sessions_map_[session_type] = session_ptr;
|
||||
return session_ptr;
|
||||
}
|
||||
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace android
|
|
@ -1,186 +0,0 @@
|
|||
/*
|
||||
* Copyright 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <android/hardware/bluetooth/audio/2.2/types.h>
|
||||
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "BluetoothAudioSession.h"
|
||||
#include "BluetoothAudioSession_2_1.h"
|
||||
|
||||
namespace android {
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
|
||||
inline uint16_t ObserversCookieGetInitValue(
|
||||
const ::android::hardware::bluetooth::audio::V2_1::SessionType&
|
||||
session_type) {
|
||||
return (static_cast<uint16_t>(session_type) << 8 & 0xff00);
|
||||
}
|
||||
inline uint16_t ObserversCookieGetUpperBound(
|
||||
const ::android::hardware::bluetooth::audio::V2_1::SessionType&
|
||||
session_type) {
|
||||
return (static_cast<uint16_t>(session_type) << 8 & 0xff00) +
|
||||
kObserversCookieSize;
|
||||
}
|
||||
|
||||
struct PortStatusCallbacks_2_2 {
|
||||
// control_result_cb_ - when the Bluetooth stack reports results of
|
||||
// streamStarted or streamSuspended, the BluetoothAudioProvider will invoke
|
||||
// this callback to report to the bluetooth_audio module.
|
||||
// @param: cookie - indicates which bluetooth_audio output should handle
|
||||
// @param: start_resp - this report is for startStream or not
|
||||
// @param: status - the result of startStream
|
||||
std::function<void(uint16_t cookie, bool start_resp,
|
||||
const BluetoothAudioStatus& status)>
|
||||
control_result_cb_;
|
||||
// session_changed_cb_ - when the Bluetooth stack start / end session, the
|
||||
// BluetoothAudioProvider will invoke this callback to notify to the
|
||||
// bluetooth_audio module.
|
||||
// @param: cookie - indicates which bluetooth_audio output should handle
|
||||
std::function<void(uint16_t cookie)> session_changed_cb_;
|
||||
// audio_configuration_changed_cb_ - when the Bluetooth stack change the audio
|
||||
// configuration, the BluetoothAudioProvider will invoke this callback to
|
||||
// notify to the bluetooth_audio module.
|
||||
// @param: cookie - indicates which bluetooth_audio output should handle
|
||||
std::function<void(uint16_t cookie)> audio_configuration_changed_cb_;
|
||||
};
|
||||
|
||||
class BluetoothAudioSession_2_2 {
|
||||
private:
|
||||
std::shared_ptr<BluetoothAudioSession> audio_session;
|
||||
std::shared_ptr<BluetoothAudioSession_2_1> audio_session_2_1;
|
||||
|
||||
::android::hardware::bluetooth::audio::V2_1::SessionType session_type_2_1_;
|
||||
::android::hardware::bluetooth::audio::V2_1::SessionType raw_session_type_;
|
||||
|
||||
// audio data configuration for both software and offloading
|
||||
::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
|
||||
audio_config_2_2_;
|
||||
|
||||
bool UpdateAudioConfig(
|
||||
const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
|
||||
audio_config);
|
||||
|
||||
static ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
|
||||
invalidSoftwareAudioConfiguration;
|
||||
static ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
|
||||
invalidOffloadAudioConfiguration;
|
||||
static ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
|
||||
invalidLeOffloadAudioConfiguration;
|
||||
|
||||
// saving those registered bluetooth_audio's callbacks
|
||||
std::unordered_map<uint16_t, std::shared_ptr<struct PortStatusCallbacks_2_2>>
|
||||
observers_;
|
||||
|
||||
// invoking the registered session_changed_cb_
|
||||
void ReportSessionStatus();
|
||||
|
||||
public:
|
||||
BluetoothAudioSession_2_2(
|
||||
const ::android::hardware::bluetooth::audio::V2_1::SessionType&
|
||||
session_type);
|
||||
|
||||
// The function helps to check if this session is ready or not
|
||||
// @return: true if the Bluetooth stack has started the specified session
|
||||
bool IsSessionReady();
|
||||
|
||||
std::shared_ptr<BluetoothAudioSession> GetAudioSession();
|
||||
std::shared_ptr<BluetoothAudioSession_2_1> GetAudioSession_2_1();
|
||||
|
||||
// The report function is used to report that the Bluetooth stack has started
|
||||
// this session without any failure, and will invoke session_changed_cb_ to
|
||||
// notify those registered bluetooth_audio outputs
|
||||
void OnSessionStarted(
|
||||
const sp<IBluetoothAudioPort> stack_iface,
|
||||
const DataMQ::Descriptor* dataMQ,
|
||||
const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
|
||||
audio_config);
|
||||
|
||||
// The report function is used to report that the Bluetooth stack has ended
|
||||
// the session, and will invoke session_changed_cb_ to notify registered
|
||||
// bluetooth_audio outputs
|
||||
void OnSessionEnded();
|
||||
|
||||
// Those control functions are for the bluetooth_audio module to start,
|
||||
// suspend, stop stream, to check position, and to update metadata.
|
||||
bool StartStream();
|
||||
bool SuspendStream();
|
||||
void StopStream();
|
||||
|
||||
// The control function helps the bluetooth_audio module to register
|
||||
// PortStatusCallbacks_2_2
|
||||
// @return: cookie - the assigned number to this bluetooth_audio output
|
||||
uint16_t RegisterStatusCback(const PortStatusCallbacks_2_2& cbacks);
|
||||
|
||||
// The control function helps the bluetooth_audio module to unregister
|
||||
// PortStatusCallbacks_2_2
|
||||
// @param: cookie - indicates which bluetooth_audio output is
|
||||
void UnregisterStatusCback(uint16_t cookie);
|
||||
|
||||
// The report function is used to report that the Bluetooth stack has notified
|
||||
// the result of startStream or suspendStream, and will invoke
|
||||
// control_result_cb_ to notify registered bluetooth_audio outputs
|
||||
void ReportControlStatus(bool start_resp, const BluetoothAudioStatus& status);
|
||||
|
||||
// The report function is used to report that the Bluetooth stack has notified
|
||||
// the audio configuration changed, and will invoke
|
||||
// audio_configuration_changed_cb_ to notify registered bluetooth_audio
|
||||
// outputs
|
||||
void ReportAudioConfigChanged(
|
||||
const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
|
||||
audio_config);
|
||||
|
||||
// The control function is for the bluetooth_audio module to get the current
|
||||
// AudioConfiguration
|
||||
const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
|
||||
GetAudioConfig();
|
||||
|
||||
void UpdateTracksMetadata(const struct source_metadata* source_metadata);
|
||||
void UpdateSinkMetadata(const struct sink_metadata* sink_metadata);
|
||||
|
||||
static constexpr ::android::hardware::bluetooth::audio::V2_2::
|
||||
AudioConfiguration& kInvalidSoftwareAudioConfiguration =
|
||||
invalidSoftwareAudioConfiguration;
|
||||
static constexpr ::android::hardware::bluetooth::audio::V2_2::
|
||||
AudioConfiguration& kInvalidOffloadAudioConfiguration =
|
||||
invalidOffloadAudioConfiguration;
|
||||
static constexpr ::android::hardware::bluetooth::audio::V2_2::
|
||||
AudioConfiguration& kInvalidLeOffloadAudioConfiguration =
|
||||
invalidLeOffloadAudioConfiguration;
|
||||
};
|
||||
|
||||
class BluetoothAudioSessionInstance_2_2 {
|
||||
public:
|
||||
// The API is to fetch the specified session of A2DP / Hearing Aid
|
||||
static std::shared_ptr<BluetoothAudioSession_2_2> GetSessionInstance(
|
||||
const ::android::hardware::bluetooth::audio::V2_1::SessionType&
|
||||
session_type);
|
||||
|
||||
private:
|
||||
static std::unique_ptr<BluetoothAudioSessionInstance_2_2> instance_ptr;
|
||||
std::mutex mutex_;
|
||||
std::unordered_map<::android::hardware::bluetooth::audio::V2_1::SessionType,
|
||||
std::shared_ptr<BluetoothAudioSession_2_2>>
|
||||
sessions_map_;
|
||||
};
|
||||
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace android
|
|
@ -1,161 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021 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 "BTAudioProviderSessionCodecsDB_2_2"
|
||||
|
||||
#include "BluetoothAudioSupportedCodecsDB_2_2.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
|
||||
namespace android {
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
|
||||
using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
|
||||
using ::android::hardware::bluetooth::audio::V2_1::CodecType;
|
||||
using ::android::hardware::bluetooth::audio::V2_1::Lc3FrameDuration;
|
||||
using ::android::hardware::bluetooth::audio::V2_1::Lc3Parameters;
|
||||
using ::android::hardware::bluetooth::audio::V2_1::SampleRate;
|
||||
using ::android::hardware::bluetooth::audio::V2_2::AudioLocation;
|
||||
using ::android::hardware::bluetooth::audio::V2_2::BroadcastCapability;
|
||||
using ::android::hardware::bluetooth::audio::V2_2::
|
||||
LeAudioCodecCapabilitiesSetting;
|
||||
using ::android::hardware::bluetooth::audio::V2_2::UnicastCapability;
|
||||
using SessionType_2_1 =
|
||||
::android::hardware::bluetooth::audio::V2_1::SessionType;
|
||||
|
||||
// Stores the list of offload supported capability
|
||||
std::vector<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 Lc3Parameters kLc3Capability_16_1 = {
|
||||
.samplingFrequency = SampleRate::RATE_16000,
|
||||
.frameDuration = Lc3FrameDuration::DURATION_7500US,
|
||||
.octetsPerFrame = 30};
|
||||
|
||||
// Default Supported Codecs
|
||||
// LC3 16_2: sample rate: 16 kHz, frame duration: 10 ms, octets per frame: 40
|
||||
static const Lc3Parameters kLc3Capability_16_2 = {
|
||||
.samplingFrequency = SampleRate::RATE_16000,
|
||||
.frameDuration = Lc3FrameDuration::DURATION_10000US,
|
||||
.octetsPerFrame = 40};
|
||||
|
||||
// Default Supported Codecs
|
||||
// LC3 48_4: sample rate: 48 kHz, frame duration: 10 ms, octets per frame: 120
|
||||
static const Lc3Parameters kLc3Capability_48_4 = {
|
||||
.samplingFrequency = SampleRate::RATE_48000,
|
||||
.frameDuration = Lc3FrameDuration::DURATION_10000US,
|
||||
.octetsPerFrame = 120};
|
||||
|
||||
static const std::vector<Lc3Parameters> supportedLc3CapabilityList = {
|
||||
kLc3Capability_48_4, kLc3Capability_16_2, kLc3Capability_16_1};
|
||||
|
||||
static AudioLocation stereoAudio = static_cast<AudioLocation>(
|
||||
AudioLocation::FRONT_LEFT | 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)};
|
||||
|
||||
bool IsOffloadLeAudioConfigurationValid(
|
||||
const ::android::hardware::bluetooth::audio::V2_1::SessionType&
|
||||
session_type,
|
||||
const ::android::hardware::bluetooth::audio::V2_2::LeAudioConfiguration&) {
|
||||
if (session_type !=
|
||||
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
|
||||
session_type !=
|
||||
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: perform checks on le_audio_codec_config once we know supported
|
||||
// parameters
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
UnicastCapability composeUnicastLc3Capability(AudioLocation audioLocation,
|
||||
uint8_t deviceCnt,
|
||||
uint8_t channelCount,
|
||||
Lc3Parameters capability) {
|
||||
return UnicastCapability{.codecType = CodecType::LC3,
|
||||
.supportedChannel = audioLocation,
|
||||
.deviceCount = deviceCnt,
|
||||
.channelCountPerDevice = channelCount,
|
||||
.capabilities = capability};
|
||||
}
|
||||
|
||||
std::vector<LeAudioCodecCapabilitiesSetting> GetLeAudioOffloadCodecCapabilities(
|
||||
const SessionType_2_1& session_type) {
|
||||
if (session_type !=
|
||||
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
|
||||
session_type !=
|
||||
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
|
||||
return std::vector<LeAudioCodecCapabilitiesSetting>(0);
|
||||
}
|
||||
|
||||
if (kDefaultOffloadLeAudioCapabilities.empty()) {
|
||||
for (auto [audioLocation, deviceCnt, channelCount] :
|
||||
supportedDeviceSetting) {
|
||||
for (auto capability : supportedLc3CapabilityList) {
|
||||
UnicastCapability lc3Capability = composeUnicastLc3Capability(
|
||||
audioLocation, deviceCnt, channelCount, capability);
|
||||
UnicastCapability lc3MonoDecodeCapability =
|
||||
composeUnicastLc3Capability(monoAudio, 1, 1, capability);
|
||||
|
||||
// Adds the capability for encode only
|
||||
kDefaultOffloadLeAudioCapabilities.push_back(
|
||||
{.unicastEncodeCapability = lc3Capability,
|
||||
.unicastDecodeCapability = kInvalidUnicastCapability,
|
||||
.broadcastCapability = kInvalidBroadcastCapability});
|
||||
|
||||
// Adds the capability for decode only
|
||||
kDefaultOffloadLeAudioCapabilities.push_back(
|
||||
{.unicastEncodeCapability = kInvalidUnicastCapability,
|
||||
.unicastDecodeCapability = lc3Capability,
|
||||
.broadcastCapability = kInvalidBroadcastCapability});
|
||||
|
||||
// Adds the capability for the case that encode and decode exist at the
|
||||
// same time
|
||||
kDefaultOffloadLeAudioCapabilities.push_back(
|
||||
{.unicastEncodeCapability = lc3Capability,
|
||||
.unicastDecodeCapability = lc3MonoDecodeCapability,
|
||||
.broadcastCapability = kInvalidBroadcastCapability});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return kDefaultOffloadLeAudioCapabilities;
|
||||
}
|
||||
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace android
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021 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 <android/hardware/bluetooth/audio/2.2/types.h>
|
||||
|
||||
#include "BluetoothAudioSupportedCodecsDB.h"
|
||||
#include "BluetoothAudioSupportedCodecsDB_2_1.h"
|
||||
|
||||
namespace android {
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
|
||||
bool IsOffloadLeAudioConfigurationValid(
|
||||
const ::android::hardware::bluetooth::audio::V2_1::SessionType&
|
||||
session_type,
|
||||
const ::android::hardware::bluetooth::audio::V2_2::LeAudioConfiguration&
|
||||
le_audio_codec_config);
|
||||
|
||||
std::vector<hardware::bluetooth::audio::V2_2::LeAudioCodecCapabilitiesSetting>
|
||||
GetLeAudioOffloadCodecCapabilities(
|
||||
const ::android::hardware::bluetooth::audio::V2_1::SessionType&
|
||||
session_type);
|
||||
} // namespace audio
|
||||
} // namespace bluetooth
|
||||
} // namespace android
|
Loading…
Reference in a new issue