blob: af6ec99a921fcad7c29d97bdf445557dc69e53ea [file] [log] [blame]
Alice Kuo84e87672021-10-28 12:53:38 +08001/*
2 * Copyright 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "BTAudioProviderLeAudio"
18
19#include "LeAudioAudioProvider.h"
20
21#include <android-base/logging.h>
22
23#include "BluetoothAudioSessionReport_2_2.h"
24#include "BluetoothAudioSupportedCodecsDB_2_1.h"
25
26namespace android {
27namespace hardware {
28namespace bluetooth {
29namespace audio {
30namespace V2_2 {
31namespace implementation {
32
33using ::android::bluetooth::audio::BluetoothAudioSessionReport_2_2;
34using ::android::hardware::Void;
35using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
36using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
37using ::android::hardware::bluetooth::audio::V2_1::SampleRate;
38
39static constexpr uint32_t kBufferOutCount = 2; // two frame buffer
40static constexpr uint32_t kBufferInCount = 2; // two frame buffer
41
42LeAudioOutputAudioProvider::LeAudioOutputAudioProvider()
43 : LeAudioAudioProvider() {
44 session_type_ = V2_1::SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
45}
46
47LeAudioInputAudioProvider::LeAudioInputAudioProvider()
48 : LeAudioAudioProvider() {
49 session_type_ = V2_1::SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH;
50}
51
52LeAudioAudioProvider::LeAudioAudioProvider()
53 : BluetoothAudioProvider(), mDataMQ(nullptr) {}
54
55bool LeAudioAudioProvider::isValid(const V2_0::SessionType& sessionType) {
56 LOG(ERROR) << __func__ << ", invalid session type for Le Audio provider: "
57 << toString(sessionType);
58
59 return false;
60}
61
62bool LeAudioAudioProvider::isValid(const V2_1::SessionType& sessionType) {
63 return (sessionType == session_type_);
64}
65
66Return<void> LeAudioAudioProvider::startSession_2_1(
67 const sp<V2_0::IBluetoothAudioPort>& hostIf,
68 const V2_1::AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
69 if (audioConfig.getDiscriminator() !=
70 V2_1::AudioConfiguration::hidl_discriminator::pcmConfig) {
71 LOG(WARNING) << __func__
72 << " - Invalid Audio Configuration=" << toString(audioConfig);
73 _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
74 DataMQ::Descriptor());
75 return Void();
76 }
77
78 AudioConfiguration audioConfig_2_2;
79 audioConfig_2_2.pcmConfig(
80 {.sampleRate =
81 static_cast<V2_1::SampleRate>(audioConfig.pcmConfig().sampleRate),
82 .channelMode = audioConfig.pcmConfig().channelMode,
83 .bitsPerSample = audioConfig.pcmConfig().bitsPerSample,
84 .dataIntervalUs = 0});
85
86 return startSession_2_2(hostIf, audioConfig_2_2, _hidl_cb);
87}
88
89Return<void> LeAudioAudioProvider::startSession_2_2(
90 const sp<V2_0::IBluetoothAudioPort>& hostIf,
91 const AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
92 /**
93 * Initialize the audio platform if audioConfiguration is supported.
94 * Save the IBluetoothAudioPort interface, so that it can be used
95 * later to send stream control commands to the HAL client, based on
96 * interaction with Audio framework.
97 */
98 if (audioConfig.getDiscriminator() !=
99 AudioConfiguration::hidl_discriminator::pcmConfig) {
100 LOG(WARNING) << __func__
101 << " - Invalid Audio Configuration=" << toString(audioConfig);
102 _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
103 DataMQ::Descriptor());
104 return Void();
105 } else if (!android::bluetooth::audio::IsSoftwarePcmConfigurationValid_2_1(
106 audioConfig.pcmConfig())) {
107 LOG(WARNING) << __func__ << " - Unsupported PCM Configuration="
108 << toString(audioConfig.pcmConfig());
109 _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
110 DataMQ::Descriptor());
111 return Void();
112 }
113
114 uint32_t kDataMqSize = 0;
115 switch (audioConfig.pcmConfig().sampleRate) {
116 case SampleRate::RATE_8000:
117 kDataMqSize = 8000;
118 break;
119 case SampleRate::RATE_16000:
120 kDataMqSize = 16000;
121 break;
122 case SampleRate::RATE_24000:
123 kDataMqSize = 24000;
124 break;
125 case SampleRate::RATE_32000:
126 kDataMqSize = 32000;
127 break;
128 case SampleRate::RATE_44100:
129 kDataMqSize = 44100;
130 break;
131 case SampleRate::RATE_48000:
132 kDataMqSize = 48000;
133 break;
134 default:
135 LOG(WARNING) << __func__ << " - Unsupported sampling frequency="
136 << toString(audioConfig.pcmConfig());
137 _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
138 DataMQ::Descriptor());
139 return Void();
140 }
141
142 /* Number of samples per millisecond */
143 kDataMqSize = ceil(kDataMqSize / 1000);
144
145 switch (audioConfig.pcmConfig().channelMode) {
146 case ChannelMode::MONO:
147 break;
148 case ChannelMode::STEREO:
149 kDataMqSize *= 2;
150 break;
151 default:
152 /* This should never happen it would be caught while validating
153 * parameters.
154 */
155 break;
156 }
157
158 switch (audioConfig.pcmConfig().bitsPerSample) {
159 case BitsPerSample::BITS_16:
160 kDataMqSize *= 2;
161 break;
162 case BitsPerSample::BITS_24:
163 kDataMqSize *= 3;
164 break;
165 case BitsPerSample::BITS_32:
166 kDataMqSize *= 4;
167 break;
168 default:
169 /* This should never happen it would be caught while validating
170 * parameters.
171 */
172 break;
173 }
174
175 if (session_type_ == V2_1::SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH)
176 kDataMqSize *= kBufferOutCount;
177 else if (session_type_ ==
178 V2_1::SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH)
179 kDataMqSize *= kBufferInCount;
180 else
181 LOG(WARNING) << __func__ << ", default single buffer used";
182
183 kDataMqSize *= audioConfig.pcmConfig().dataIntervalUs / 1000;
184
185 LOG(INFO) << __func__ << " - size of audio buffer " << kDataMqSize
186 << " byte(s)";
187
188 std::unique_ptr<DataMQ> tempDataMQ(
189 new DataMQ(kDataMqSize, /* EventFlag */ true));
190 if (tempDataMQ && tempDataMQ->isValid()) {
191 mDataMQ = std::move(tempDataMQ);
192 } else {
193 ALOGE_IF(!tempDataMQ, "failed to allocate data MQ");
194 ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(), "data MQ is invalid");
195 _hidl_cb(BluetoothAudioStatus::FAILURE, DataMQ::Descriptor());
196 return Void();
197 }
198
199 return BluetoothAudioProvider::startSession_2_2(hostIf, audioConfig,
200 _hidl_cb);
201}
202
203Return<void> LeAudioAudioProvider::onSessionReady(startSession_cb _hidl_cb) {
204 if (mDataMQ && mDataMQ->isValid()) {
205 BluetoothAudioSessionReport_2_2::OnSessionStarted(
206 session_type_, stack_iface_, mDataMQ->getDesc(), audio_config_);
207 _hidl_cb(BluetoothAudioStatus::SUCCESS, *mDataMQ->getDesc());
208 } else {
209 _hidl_cb(BluetoothAudioStatus::FAILURE, DataMQ::Descriptor());
210 }
211 return Void();
212}
213
214} // namespace implementation
215} // namespace V2_2
216} // namespace audio
217} // namespace bluetooth
218} // namespace hardware
219} // namespace android