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