mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 11:36:00 +00:00
Merge changes from topic "bluetooth_audio_hidl2.2" am: e1dc0e5365
Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/1872877 Change-Id: I21df41fdd4f0ace606317f9f473592b7fb6fe71c
This commit is contained in:
32
bluetooth/audio/2.2/Android.bp
Normal file
32
bluetooth/audio/2.2/Android.bp
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
// This file is autogenerated by hidl-gen -Landroidbp.
|
||||||
|
|
||||||
|
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"],
|
||||||
|
}
|
||||||
|
|
||||||
|
hidl_interface {
|
||||||
|
name: "android.hardware.bluetooth.audio@2.2",
|
||||||
|
root: "android.hardware",
|
||||||
|
srcs: [
|
||||||
|
"types.hal",
|
||||||
|
"IBluetoothAudioProvider.hal",
|
||||||
|
"IBluetoothAudioProvidersFactory.hal",
|
||||||
|
],
|
||||||
|
interfaces: [
|
||||||
|
"android.hardware.audio.common@5.0",
|
||||||
|
"android.hardware.bluetooth.audio@2.0",
|
||||||
|
"android.hardware.bluetooth.audio@2.1",
|
||||||
|
"android.hidl.base@1.0",
|
||||||
|
"android.hidl.safe_union@1.0",
|
||||||
|
],
|
||||||
|
apex_available: [
|
||||||
|
"//apex_available:platform",
|
||||||
|
"com.android.bluetooth.updatable",
|
||||||
|
],
|
||||||
|
gen_java: false,
|
||||||
|
}
|
||||||
62
bluetooth/audio/2.2/IBluetoothAudioProvider.hal
Normal file
62
bluetooth/audio/2.2/IBluetoothAudioProvider.hal
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.hardware.bluetooth.audio@2.2;
|
||||||
|
|
||||||
|
import @2.1::IBluetoothAudioProvider;
|
||||||
|
import @2.0::IBluetoothAudioPort;
|
||||||
|
import @2.0::Status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HAL interface from the Bluetooth stack to the Audio HAL
|
||||||
|
*
|
||||||
|
* The Bluetooth stack calls methods in this interface to start and end audio
|
||||||
|
* sessions and sends callback events to the Audio HAL.
|
||||||
|
*
|
||||||
|
* Note: For HIDL APIs with a "generates" statement, the callback parameter used
|
||||||
|
* for return value must be invoked synchronously before the API call returns.
|
||||||
|
*/
|
||||||
|
interface IBluetoothAudioProvider extends @2.1::IBluetoothAudioProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method indicates that the Bluetooth stack is ready to stream audio.
|
||||||
|
* It registers an instance of IBluetoothAudioPort with and provides the
|
||||||
|
* current negotiated codec to the Audio HAL. After this method is called,
|
||||||
|
* the Audio HAL can invoke IBluetoothAudioPort.startStream().
|
||||||
|
*
|
||||||
|
* Note: endSession() must be called to unregister this IBluetoothAudioPort
|
||||||
|
*
|
||||||
|
* @param hostIf An instance of IBluetoothAudioPort for stream control
|
||||||
|
* @param audioConfig The audio configuration negotiated with the remote
|
||||||
|
* device. The PCM parameters are set if software based encoding,
|
||||||
|
* otherwise the correct codec configuration is used for hardware
|
||||||
|
* encoding.
|
||||||
|
*
|
||||||
|
* @return status One of the following
|
||||||
|
* SUCCESS if this IBluetoothAudioPort was successfully registered with
|
||||||
|
* the Audio HAL
|
||||||
|
* UNSUPPORTED_CODEC_CONFIGURATION if the Audio HAL cannot register this
|
||||||
|
* IBluetoothAudioPort with the given codec configuration
|
||||||
|
* FAILURE if the Audio HAL cannot register this IBluetoothAudioPort for
|
||||||
|
* any other reason
|
||||||
|
* @return dataMQ The fast message queue for audio data from/to this
|
||||||
|
* provider. Audio data will be in PCM format as specified by the
|
||||||
|
* audioConfig.pcmConfig parameter. Invalid if streaming is offloaded
|
||||||
|
* from/to hardware or on failure.
|
||||||
|
*/
|
||||||
|
startSession_2_2(IBluetoothAudioPort hostIf, AudioConfiguration audioConfig)
|
||||||
|
generates (Status status, fmq_sync<uint8_t> dataMQ);
|
||||||
|
};
|
||||||
33
bluetooth/audio/2.2/IBluetoothAudioProvidersFactory.hal
Normal file
33
bluetooth/audio/2.2/IBluetoothAudioProvidersFactory.hal
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.hardware.bluetooth.audio@2.2;
|
||||||
|
|
||||||
|
import @2.1::IBluetoothAudioProvidersFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This factory allows a HAL implementation to be split into multiple
|
||||||
|
* independent providers.
|
||||||
|
*
|
||||||
|
* When the Bluetooth stack is ready to create an audio session, it must first
|
||||||
|
* obtain the IBluetoothAudioProvider for that session type by calling
|
||||||
|
* openProvider().
|
||||||
|
*
|
||||||
|
* Note: For HIDL APIs with a "generates" statement, the callback parameter used
|
||||||
|
* for return value must be invoked synchronously before the API call returns.
|
||||||
|
*/
|
||||||
|
interface IBluetoothAudioProvidersFactory extends @2.1::IBluetoothAudioProvidersFactory {
|
||||||
|
};
|
||||||
95
bluetooth/audio/2.2/default/A2dpOffloadAudioProvider.cpp
Normal file
95
bluetooth/audio/2.2/default/A2dpOffloadAudioProvider.cpp
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* 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<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
|
||||||
48
bluetooth/audio/2.2/default/A2dpOffloadAudioProvider.h
Normal file
48
bluetooth/audio/2.2/default/A2dpOffloadAudioProvider.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
117
bluetooth/audio/2.2/default/A2dpSoftwareAudioProvider.cpp
Normal file
117
bluetooth/audio/2.2/default/A2dpSoftwareAudioProvider.cpp
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* 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_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::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<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
|
||||||
59
bluetooth/audio/2.2/default/A2dpSoftwareAudioProvider.h
Normal file
59
bluetooth/audio/2.2/default/A2dpSoftwareAudioProvider.h
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* 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<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
|
||||||
37
bluetooth/audio/2.2/default/Android.bp
Normal file
37
bluetooth/audio/2.2/default/Android.bp
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
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",
|
||||||
|
],
|
||||||
|
}
|
||||||
189
bluetooth/audio/2.2/default/BluetoothAudioProvider.cpp
Normal file
189
bluetooth/audio/2.2/default/BluetoothAudioProvider.cpp
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
/*
|
||||||
|
* 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 "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 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<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());
|
||||||
|
}
|
||||||
|
|
||||||
|
return startSession_2_2(hostIf, audioConfig_2_2, _hidl_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
Return<void> BluetoothAudioProvider::startSession_2_1(
|
||||||
|
const sp<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());
|
||||||
|
}
|
||||||
|
|
||||||
|
return startSession_2_2(hostIf, audioConfig_2_2, _hidl_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
Return<void> BluetoothAudioProvider::startSession_2_2(
|
||||||
|
const sp<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();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace implementation
|
||||||
|
} // namespace V2_2
|
||||||
|
} // namespace audio
|
||||||
|
} // namespace bluetooth
|
||||||
|
} // namespace hardware
|
||||||
|
} // namespace android
|
||||||
85
bluetooth/audio/2.2/default/BluetoothAudioProvider.h
Normal file
85
bluetooth/audio/2.2/default/BluetoothAudioProvider.h
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* 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_0::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<IBluetoothAudioPort>& hostIf,
|
||||||
|
const V2_0::AudioConfiguration& audioConfig,
|
||||||
|
startSession_cb _hidl_cb) override;
|
||||||
|
Return<void> startSession_2_1(const sp<IBluetoothAudioPort>& hostIf,
|
||||||
|
const V2_1::AudioConfiguration& audioConfig,
|
||||||
|
startSession_cb _hidl_cb) override;
|
||||||
|
Return<void> startSession_2_2(const sp<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;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
sp<BluetoothAudioDeathRecipient> death_recipient_;
|
||||||
|
|
||||||
|
V2_1::SessionType session_type_;
|
||||||
|
AudioConfiguration audio_config_;
|
||||||
|
sp<V2_0::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
|
||||||
191
bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp
Normal file
191
bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
/*
|
||||||
|
* 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_1.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_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();
|
||||||
|
}
|
||||||
|
|
||||||
|
IBluetoothAudioProvidersFactory* HIDL_FETCH_IBluetoothAudioProvidersFactory(
|
||||||
|
const char* /* name */) {
|
||||||
|
return new BluetoothAudioProvidersFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace implementation
|
||||||
|
} // namespace V2_2
|
||||||
|
} // namespace audio
|
||||||
|
} // namespace bluetooth
|
||||||
|
} // namespace hardware
|
||||||
|
} // namespace android
|
||||||
73
bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.h
Normal file
73
bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.h
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* 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> getProviderCapabilities_2_1(
|
||||||
|
const V2_1::SessionType sessionType,
|
||||||
|
getProviderCapabilities_2_1_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
|
||||||
112
bluetooth/audio/2.2/default/HearingAidAudioProvider.cpp
Normal file
112
bluetooth/audio/2.2/default/HearingAidAudioProvider.cpp
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* 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_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::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<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
|
||||||
59
bluetooth/audio/2.2/default/HearingAidAudioProvider.h
Normal file
59
bluetooth/audio/2.2/default/HearingAidAudioProvider.h
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* 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<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
|
||||||
219
bluetooth/audio/2.2/default/LeAudioAudioProvider.cpp
Normal file
219
bluetooth/audio/2.2/default/LeAudioAudioProvider.cpp
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
/*
|
||||||
|
* 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 "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::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});
|
||||||
|
|
||||||
|
return startSession_2_2(hostIf, audioConfig_2_2, _hidl_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
Return<void> LeAudioAudioProvider::startSession_2_2(
|
||||||
|
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_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
|
||||||
74
bluetooth/audio/2.2/default/LeAudioAudioProvider.h
Normal file
74
bluetooth/audio/2.2/default/LeAudioAudioProvider.h
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* 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_0::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
|
||||||
141
bluetooth/audio/2.2/default/LeAudioOffloadAudioProvider.cpp
Normal file
141
bluetooth/audio/2.2/default/LeAudioOffloadAudioProvider.cpp
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* 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 "BluetoothAudioSessionReport_2_2.h"
|
||||||
|
#include "BluetoothAudioSupportedCodecsDB_2_1.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};
|
||||||
|
|
||||||
|
return startSession_2_2(hostIf, audioConfig_2_2, _hidl_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
Return<void> LeAudioOffloadAudioProvider::startSession_2_2(
|
||||||
|
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::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
|
||||||
64
bluetooth/audio/2.2/default/LeAudioOffloadAudioProvider.h
Normal file
64
bluetooth/audio/2.2/default/LeAudioOffloadAudioProvider.h
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* 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_0::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
|
||||||
72
bluetooth/audio/2.2/types.hal
Normal file
72
bluetooth/audio/2.2/types.hal
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.hardware.bluetooth.audio@2.2;
|
||||||
|
|
||||||
|
import @2.1::Lc3Parameters;
|
||||||
|
import @2.1::PcmParameters;
|
||||||
|
import @2.0::CodecConfiguration;
|
||||||
|
|
||||||
|
enum LeAudioMode : uint8_t {
|
||||||
|
UNKNOWN = 0x00,
|
||||||
|
UNICAST = 0x01,
|
||||||
|
BROADCAST = 0x02,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UnicastStreamMap {
|
||||||
|
/* The connection handle used for a unicast or a broadcast group. */
|
||||||
|
uint16_t streamHandle;
|
||||||
|
/* Audio channel allocation is a bit field, each enabled bit means that given audio direction,
|
||||||
|
* i.e. "left", or "right" is used. Ordering of audio channels comes from the least significant
|
||||||
|
* bit to the most significant bit. */
|
||||||
|
uint32_t audioChannelAllocation;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BroadcastStreamMap {
|
||||||
|
/* The connection handle used for a unicast or a broadcast group. */
|
||||||
|
uint16_t streamHandle;
|
||||||
|
/* Audio channel allocation is a bit field, each enabled bit means that given audio direction,
|
||||||
|
* i.e. "left", or "right" is used. Ordering of audio channels comes from the least significant
|
||||||
|
* bit to the most significant bit. */
|
||||||
|
uint32_t audioChannelAllocation;
|
||||||
|
Lc3Parameters lc3Config;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UnicastConfig {
|
||||||
|
vec<UnicastStreamMap> streamMap;
|
||||||
|
uint32_t peerDelay;
|
||||||
|
Lc3Parameters lc3Config;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BroadcastConfig {
|
||||||
|
vec<BroadcastStreamMap> streamMap;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LeAudioConfiguration {
|
||||||
|
/* The mode of the LE audio */
|
||||||
|
LeAudioMode mode;
|
||||||
|
safe_union CodecConfig {
|
||||||
|
UnicastConfig unicastConfig;
|
||||||
|
BroadcastConfig broadcastConfig;
|
||||||
|
} config;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Used to configure either a Hardware or Software Encoding session based on session type */
|
||||||
|
safe_union AudioConfiguration {
|
||||||
|
PcmParameters pcmConfig;
|
||||||
|
CodecConfiguration codecConfig;
|
||||||
|
LeAudioConfiguration leAudioConfig;
|
||||||
|
};
|
||||||
@@ -14,14 +14,17 @@ cc_library_shared {
|
|||||||
srcs: [
|
srcs: [
|
||||||
"session/BluetoothAudioSession.cpp",
|
"session/BluetoothAudioSession.cpp",
|
||||||
"session/BluetoothAudioSession_2_1.cpp",
|
"session/BluetoothAudioSession_2_1.cpp",
|
||||||
|
"session/BluetoothAudioSession_2_2.cpp",
|
||||||
"session/BluetoothAudioSupportedCodecsDB.cpp",
|
"session/BluetoothAudioSupportedCodecsDB.cpp",
|
||||||
"session/BluetoothAudioSupportedCodecsDB_2_1.cpp",
|
"session/BluetoothAudioSupportedCodecsDB_2_1.cpp",
|
||||||
|
"session/BluetoothAudioSupportedCodecsDB_2_2.cpp",
|
||||||
],
|
],
|
||||||
export_include_dirs: ["session/"],
|
export_include_dirs: ["session/"],
|
||||||
header_libs: ["libhardware_headers"],
|
header_libs: ["libhardware_headers"],
|
||||||
shared_libs: [
|
shared_libs: [
|
||||||
"android.hardware.bluetooth.audio@2.0",
|
"android.hardware.bluetooth.audio@2.0",
|
||||||
"android.hardware.bluetooth.audio@2.1",
|
"android.hardware.bluetooth.audio@2.1",
|
||||||
|
"android.hardware.bluetooth.audio@2.2",
|
||||||
"libbase",
|
"libbase",
|
||||||
"libcutils",
|
"libcutils",
|
||||||
"libfmq",
|
"libfmq",
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ struct PortStatusCallbacks {
|
|||||||
|
|
||||||
class BluetoothAudioSession {
|
class BluetoothAudioSession {
|
||||||
friend class BluetoothAudioSession_2_1;
|
friend class BluetoothAudioSession_2_1;
|
||||||
|
friend class BluetoothAudioSession_2_2;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// using recursive_mutex to allow hwbinder to re-enter agian.
|
// using recursive_mutex to allow hwbinder to re-enter agian.
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* 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->GetAudioSession()->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->GetAudioSession()->ReportControlStatus(start_resp, status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace audio
|
||||||
|
} // namespace bluetooth
|
||||||
|
} // namespace android
|
||||||
227
bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
Normal file
227
bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
/*
|
||||||
|
* 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>
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
namespace bluetooth {
|
||||||
|
namespace audio {
|
||||||
|
using SessionType_2_1 =
|
||||||
|
::android::hardware::bluetooth::audio::V2_1::SessionType;
|
||||||
|
using SessionType_2_0 =
|
||||||
|
::android::hardware::bluetooth::audio::V2_0::SessionType;
|
||||||
|
|
||||||
|
::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
|
||||||
|
BluetoothAudioSession_2_2::invalidSoftwareAudioConfiguration = {};
|
||||||
|
::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
|
||||||
|
BluetoothAudioSession_2_2::invalidOffloadAudioConfiguration = {};
|
||||||
|
|
||||||
|
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))) {
|
||||||
|
if (is_2_0_session_type(session_type)) {
|
||||||
|
session_type_2_1_ = (SessionType_2_1::UNKNOWN);
|
||||||
|
} else {
|
||||||
|
session_type_2_1_ = (session_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BluetoothAudioSession_2_2::IsSessionReady() {
|
||||||
|
if (session_type_2_1_ !=
|
||||||
|
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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() {
|
||||||
|
std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
|
||||||
|
if (IsSessionReady()) {
|
||||||
|
// If session is unknown it means it should be 2.0 type
|
||||||
|
if (session_type_2_1_ != SessionType_2_1::UNKNOWN) return audio_config_2_2_;
|
||||||
|
|
||||||
|
::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::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
|
||||||
|
return kInvalidOffloadAudioConfiguration;
|
||||||
|
} else {
|
||||||
|
return kInvalidSoftwareAudioConfiguration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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::A2DP_HARDWARE_OFFLOAD_DATAPATH
|
||||||
|
? kInvalidOffloadAudioConfiguration
|
||||||
|
: kInvalidSoftwareAudioConfiguration);
|
||||||
|
} else {
|
||||||
|
audio_session->stack_iface_ = stack_iface;
|
||||||
|
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_2_1_)
|
||||||
|
<< ", AudioConfiguration=" << toString(audio_config);
|
||||||
|
audio_session->ReportSessionStatus();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
99
bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
Normal file
99
bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
namespace bluetooth {
|
||||||
|
namespace audio {
|
||||||
|
|
||||||
|
class BluetoothAudioSession_2_2 {
|
||||||
|
private:
|
||||||
|
std::shared_ptr<BluetoothAudioSession> audio_session;
|
||||||
|
|
||||||
|
::android::hardware::bluetooth::audio::V2_1::SessionType session_type_2_1_;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
// 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 control function is for the bluetooth_audio module to get the current
|
||||||
|
// AudioConfiguration
|
||||||
|
const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
|
||||||
|
GetAudioConfig();
|
||||||
|
|
||||||
|
static constexpr ::android::hardware::bluetooth::audio::V2_2::
|
||||||
|
AudioConfiguration& kInvalidSoftwareAudioConfiguration =
|
||||||
|
invalidSoftwareAudioConfiguration;
|
||||||
|
static constexpr ::android::hardware::bluetooth::audio::V2_2::
|
||||||
|
AudioConfiguration& kInvalidOffloadAudioConfiguration =
|
||||||
|
invalidOffloadAudioConfiguration;
|
||||||
|
};
|
||||||
|
|
||||||
|
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
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* 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 SessionType_2_1 =
|
||||||
|
::android::hardware::bluetooth::audio::V2_1::SessionType;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace audio
|
||||||
|
} // namespace bluetooth
|
||||||
|
} // namespace android
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
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);
|
||||||
|
} // namespace audio
|
||||||
|
} // namespace bluetooth
|
||||||
|
} // namespace android
|
||||||
@@ -133,7 +133,7 @@
|
|||||||
</hal>
|
</hal>
|
||||||
<hal format="hidl" optional="true">
|
<hal format="hidl" optional="true">
|
||||||
<name>android.hardware.bluetooth.audio</name>
|
<name>android.hardware.bluetooth.audio</name>
|
||||||
<version>2.0-1</version>
|
<version>2.0-2</version>
|
||||||
<interface>
|
<interface>
|
||||||
<name>IBluetoothAudioProvidersFactory</name>
|
<name>IBluetoothAudioProvidersFactory</name>
|
||||||
<instance>default</instance>
|
<instance>default</instance>
|
||||||
|
|||||||
Reference in New Issue
Block a user