blob: d0f2a26e68a5ca0baa9e26e4d9e15c5235c19b4f [file] [log] [blame]
Josh Wu20bac522021-12-29 23:52:39 -08001/*
2 * Copyright (C) 2022 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#include <sys/types.h>
18#define LOG_TAG "BTAudioSessionAidl"
19
20#include <android-base/logging.h>
21#include <android-base/stringprintf.h>
22#include <android/binder_manager.h>
Limon Miab58cee42023-12-01 12:16:00 +000023#include <com_android_btaudio_hal_flags.h>
Mikhail Naganovd5f0d132023-07-26 17:26:02 -070024#include <hardware/audio.h>
Josh Wu20bac522021-12-29 23:52:39 -080025
26#include "BluetoothAudioSession.h"
27
28namespace aidl {
29namespace android {
30namespace hardware {
31namespace bluetooth {
32namespace audio {
33
34static constexpr int kFmqSendTimeoutMs = 1000; // 1000 ms timeout for sending
35static constexpr int kFmqReceiveTimeoutMs =
36 1000; // 1000 ms timeout for receiving
37static constexpr int kWritePollMs = 1; // polled non-blocking interval
38static constexpr int kReadPollMs = 1; // polled non-blocking interval
39
Limon Miab58cee42023-12-01 12:16:00 +000040static std::string toString(const std::vector<LatencyMode>& latencies) {
41 std::stringstream latencyModesStr;
42 for (LatencyMode mode : latencies) {
43 latencyModesStr << " " << toString(mode);
44 }
45 return latencyModesStr.str();
46}
47
Josh Wu20bac522021-12-29 23:52:39 -080048BluetoothAudioSession::BluetoothAudioSession(const SessionType& session_type)
Josh Wu75462aa2022-01-21 21:51:21 -080049 : session_type_(session_type), stack_iface_(nullptr), data_mq_(nullptr) {}
Josh Wu20bac522021-12-29 23:52:39 -080050
51/***
52 *
53 * Callback methods
54 *
55 ***/
56
57void BluetoothAudioSession::OnSessionStarted(
58 const std::shared_ptr<IBluetoothAudioPort> stack_iface,
Cheney Ni6ecbc762022-03-03 00:12:48 +080059 const DataMQDesc* mq_desc, const AudioConfiguration& audio_config,
60 const std::vector<LatencyMode>& latency_modes) {
Josh Wu20bac522021-12-29 23:52:39 -080061 std::lock_guard<std::recursive_mutex> guard(mutex_);
62 if (stack_iface == nullptr) {
63 LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
64 << ", IBluetoothAudioPort Invalid";
65 } else if (!UpdateAudioConfig(audio_config)) {
66 LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
67 << ", AudioConfiguration=" << audio_config.toString()
68 << " Invalid";
69 } else if (!UpdateDataPath(mq_desc)) {
70 LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
71 << " MqDescriptor Invalid";
Josh Wu75462aa2022-01-21 21:51:21 -080072 audio_config_ = nullptr;
Josh Wu20bac522021-12-29 23:52:39 -080073 } else {
74 stack_iface_ = stack_iface;
Cheney Ni6ecbc762022-03-03 00:12:48 +080075 latency_modes_ = latency_modes;
Josh Wu20bac522021-12-29 23:52:39 -080076 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
Limon Miab58cee42023-12-01 12:16:00 +000077 << " - All LatencyModes=" << toString(latency_modes)
Josh Wu20bac522021-12-29 23:52:39 -080078 << ", AudioConfiguration=" << audio_config.toString();
79 ReportSessionStatus();
80 }
81}
82
83void BluetoothAudioSession::OnSessionEnded() {
84 std::lock_guard<std::recursive_mutex> guard(mutex_);
85 bool toggled = IsSessionReady();
86 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
Josh Wu75462aa2022-01-21 21:51:21 -080087 audio_config_ = nullptr;
Josh Wu20bac522021-12-29 23:52:39 -080088 stack_iface_ = nullptr;
89 UpdateDataPath(nullptr);
90 if (toggled) {
91 ReportSessionStatus();
92 }
93}
94
95/***
96 *
97 * Util methods
98 *
99 ***/
100
Josh Wu75462aa2022-01-21 21:51:21 -0800101const AudioConfiguration BluetoothAudioSession::GetAudioConfig() {
Josh Wu20bac522021-12-29 23:52:39 -0800102 std::lock_guard<std::recursive_mutex> guard(mutex_);
103 if (!IsSessionReady()) {
Josh Wu20bac522021-12-29 23:52:39 -0800104 switch (session_type_) {
105 case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
Alice Kuoadcceec2022-03-28 13:28:43 +0800106 case SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH:
Josh Wu75462aa2022-01-21 21:51:21 -0800107 return AudioConfiguration(CodecConfiguration{});
Yuyang Huangaa70c112023-10-26 16:01:45 -0700108 case SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH:
109 return AudioConfiguration(HfpConfiguration{});
Josh Wu20bac522021-12-29 23:52:39 -0800110 case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
111 case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
Josh Wu75462aa2022-01-21 21:51:21 -0800112 return AudioConfiguration(LeAudioConfiguration{});
Alice Kuoe80a5762022-02-09 14:44:29 +0800113 case SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
114 return AudioConfiguration(LeAudioBroadcastConfiguration{});
Josh Wu20bac522021-12-29 23:52:39 -0800115 default:
Josh Wu75462aa2022-01-21 21:51:21 -0800116 return AudioConfiguration(PcmConfiguration{});
Josh Wu20bac522021-12-29 23:52:39 -0800117 }
118 }
119 return *audio_config_;
120}
121
122void BluetoothAudioSession::ReportAudioConfigChanged(
123 const AudioConfiguration& audio_config) {
Josh Wu20bac522021-12-29 23:52:39 -0800124 std::lock_guard<std::recursive_mutex> guard(mutex_);
silens1f196882024-05-07 09:59:50 +0800125 if (com::android::btaudio::hal::flags::leaudio_report_broadcast_ac_to_hal()) {
126 if (session_type_ ==
127 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
128 session_type_ ==
129 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
130 if (audio_config.getTag() != AudioConfiguration::leAudioConfig) {
131 LOG(ERROR) << __func__ << " invalid audio config type for SessionType ="
132 << toString(session_type_);
133 return;
134 }
135 } else if (session_type_ ==
136 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
137 if (audio_config.getTag() != AudioConfiguration::leAudioBroadcastConfig) {
138 LOG(ERROR) << __func__ << " invalid audio config type for SessionType ="
139 << toString(session_type_);
140 return;
141 }
142 } else {
143 LOG(ERROR) << __func__ << " invalid SessionType ="
144 << toString(session_type_);
145 return;
146 }
147 } else {
148 if (session_type_ !=
149 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
150 session_type_ !=
151 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
152 return;
153 }
154 if (audio_config.getTag() != AudioConfiguration::leAudioConfig) {
155 LOG(ERROR) << __func__ << " invalid audio config type for SessionType ="
156 << toString(session_type_);
157 return;
158 }
Alice Kuo851ef342022-08-25 02:45:02 +0800159 }
160
Patty Huangf5b38af2023-03-23 23:19:00 +0800161 audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
Alice Kuo851ef342022-08-25 02:45:02 +0800162
Josh Wu20bac522021-12-29 23:52:39 -0800163 if (observers_.empty()) {
164 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
165 << " has NO port state observer";
166 return;
167 }
168 for (auto& observer : observers_) {
169 uint16_t cookie = observer.first;
170 std::shared_ptr<struct PortStatusCallbacks> cb = observer.second;
171 LOG(INFO) << __func__ << " for SessionType=" << toString(session_type_)
172 << ", bluetooth_audio=0x"
173 << ::android::base::StringPrintf("%04x", cookie);
Patty Huangf5b38af2023-03-23 23:19:00 +0800174 if (cb->audio_configuration_changed_cb_ != nullptr) {
Josh Wu20bac522021-12-29 23:52:39 -0800175 cb->audio_configuration_changed_cb_(cookie);
176 }
177 }
178}
179
180bool BluetoothAudioSession::IsSessionReady() {
181 std::lock_guard<std::recursive_mutex> guard(mutex_);
182
183 bool is_mq_valid =
184 (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
185 session_type_ ==
186 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
187 session_type_ ==
188 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
Alice Kuoe80a5762022-02-09 14:44:29 +0800189 session_type_ ==
190 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
Alice Kuoadcceec2022-03-28 13:28:43 +0800191 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
Yuyang Huangaa70c112023-10-26 16:01:45 -0700192 session_type_ == SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH ||
Josh Wu20bac522021-12-29 23:52:39 -0800193 (data_mq_ != nullptr && data_mq_->isValid()));
Josh Wu75462aa2022-01-21 21:51:21 -0800194 return stack_iface_ != nullptr && is_mq_valid && audio_config_ != nullptr;
Josh Wu20bac522021-12-29 23:52:39 -0800195}
196
197/***
198 *
199 * Status callback methods
200 *
201 ***/
202
203uint16_t BluetoothAudioSession::RegisterStatusCback(
204 const PortStatusCallbacks& callbacks) {
205 std::lock_guard<std::recursive_mutex> guard(mutex_);
206 uint16_t cookie = ObserversCookieGetInitValue(session_type_);
207 uint16_t cookie_upper_bound = ObserversCookieGetUpperBound(session_type_);
208
209 while (cookie < cookie_upper_bound) {
210 if (observers_.find(cookie) == observers_.end()) {
211 break;
212 }
213 ++cookie;
214 }
215 if (cookie >= cookie_upper_bound) {
216 LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
217 << " has " << observers_.size()
218 << " observers already (No Resource)";
219 return kObserversCookieUndefined;
220 }
221 std::shared_ptr<PortStatusCallbacks> cb =
222 std::make_shared<PortStatusCallbacks>();
223 *cb = callbacks;
224 observers_[cookie] = cb;
225 return cookie;
226}
227
228void BluetoothAudioSession::UnregisterStatusCback(uint16_t cookie) {
229 std::lock_guard<std::recursive_mutex> guard(mutex_);
230 if (observers_.erase(cookie) != 1) {
231 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
232 << " no such provider=0x"
233 << ::android::base::StringPrintf("%04x", cookie);
234 }
235}
236
237/***
238 *
239 * Stream methods
240 *
241 ***/
242
Cheney Ni6ecbc762022-03-03 00:12:48 +0800243bool BluetoothAudioSession::StartStream(bool is_low_latency) {
Josh Wu20bac522021-12-29 23:52:39 -0800244 std::lock_guard<std::recursive_mutex> guard(mutex_);
245 if (!IsSessionReady()) {
246 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
247 << " has NO session";
248 return false;
249 }
Cheney Ni6ecbc762022-03-03 00:12:48 +0800250 auto hal_retval = stack_iface_->startStream(is_low_latency);
Josh Wu20bac522021-12-29 23:52:39 -0800251 if (!hal_retval.isOk()) {
252 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
253 << toString(session_type_) << " failed";
254 return false;
255 }
256 return true;
257}
258
259bool BluetoothAudioSession::SuspendStream() {
260 std::lock_guard<std::recursive_mutex> guard(mutex_);
261 if (!IsSessionReady()) {
262 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
263 << " has NO session";
264 return false;
265 }
266 auto hal_retval = stack_iface_->suspendStream();
267 if (!hal_retval.isOk()) {
268 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
269 << toString(session_type_) << " failed";
270 return false;
271 }
272 return true;
273}
274
275void BluetoothAudioSession::StopStream() {
276 std::lock_guard<std::recursive_mutex> guard(mutex_);
277 if (!IsSessionReady()) {
278 return;
279 }
280 auto hal_retval = stack_iface_->stopStream();
281 if (!hal_retval.isOk()) {
282 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
283 << toString(session_type_) << " failed";
284 }
285}
286
287/***
288 *
289 * Private methods
290 *
291 ***/
292
293bool BluetoothAudioSession::UpdateDataPath(const DataMQDesc* mq_desc) {
294 if (mq_desc == nullptr) {
295 // usecase of reset by nullptr
296 data_mq_ = nullptr;
297 return true;
298 }
299 std::unique_ptr<DataMQ> temp_mq;
300 temp_mq.reset(new DataMQ(*mq_desc));
301 if (!temp_mq || !temp_mq->isValid()) {
302 data_mq_ = nullptr;
303 return false;
304 }
305 data_mq_ = std::move(temp_mq);
306 return true;
307}
308
309bool BluetoothAudioSession::UpdateAudioConfig(
310 const AudioConfiguration& audio_config) {
311 bool is_software_session =
312 (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
313 session_type_ == SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH ||
Yuyang Huangaa70c112023-10-26 16:01:45 -0700314 session_type_ == SessionType::HFP_SOFTWARE_ENCODING_DATAPATH ||
315 session_type_ == SessionType::HFP_SOFTWARE_DECODING_DATAPATH ||
Josh Wu20bac522021-12-29 23:52:39 -0800316 session_type_ == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH ||
Alice Kuoe80a5762022-02-09 14:44:29 +0800317 session_type_ == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH ||
318 session_type_ ==
Alice Kuoadcceec2022-03-28 13:28:43 +0800319 SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH ||
320 session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH);
Josh Wu20bac522021-12-29 23:52:39 -0800321 bool is_offload_a2dp_session =
Alice Kuoadcceec2022-03-28 13:28:43 +0800322 (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
323 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH);
Yuyang Huangaa70c112023-10-26 16:01:45 -0700324 bool is_offload_hfp_session =
325 session_type_ == SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH;
Alice Kuoee398a92022-07-10 23:59:18 +0800326 bool is_offload_le_audio_unicast_session =
Josh Wu20bac522021-12-29 23:52:39 -0800327 (session_type_ ==
328 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
329 session_type_ ==
330 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
Alice Kuoee398a92022-07-10 23:59:18 +0800331 bool is_offload_le_audio_broadcast_session =
332 (session_type_ ==
333 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
Josh Wu20bac522021-12-29 23:52:39 -0800334 auto audio_config_tag = audio_config.getTag();
335 bool is_software_audio_config =
336 (is_software_session &&
337 audio_config_tag == AudioConfiguration::pcmConfig);
338 bool is_a2dp_offload_audio_config =
339 (is_offload_a2dp_session &&
Antoine SOULIER4e34d052023-09-29 19:10:07 +0000340 (audio_config_tag == AudioConfiguration::a2dp ||
341 audio_config_tag == AudioConfiguration::a2dpConfig));
Yuyang Huangaa70c112023-10-26 16:01:45 -0700342 bool is_hfp_offload_audio_config =
343 (is_offload_hfp_session &&
344 audio_config_tag == AudioConfiguration::hfpConfig);
Alice Kuoee398a92022-07-10 23:59:18 +0800345 bool is_le_audio_offload_unicast_audio_config =
346 (is_offload_le_audio_unicast_session &&
Josh Wu20bac522021-12-29 23:52:39 -0800347 audio_config_tag == AudioConfiguration::leAudioConfig);
Alice Kuoee398a92022-07-10 23:59:18 +0800348 bool is_le_audio_offload_broadcast_audio_config =
349 (is_offload_le_audio_broadcast_session &&
350 audio_config_tag == AudioConfiguration::leAudioBroadcastConfig);
Josh Wu20bac522021-12-29 23:52:39 -0800351 if (!is_software_audio_config && !is_a2dp_offload_audio_config &&
Yuyang Huangaa70c112023-10-26 16:01:45 -0700352 !is_hfp_offload_audio_config &&
Alice Kuoee398a92022-07-10 23:59:18 +0800353 !is_le_audio_offload_unicast_audio_config &&
354 !is_le_audio_offload_broadcast_audio_config) {
Josh Wu20bac522021-12-29 23:52:39 -0800355 return false;
356 }
357 audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
358 return true;
359}
360
361void BluetoothAudioSession::ReportSessionStatus() {
362 // This is locked already by OnSessionStarted / OnSessionEnded
363 if (observers_.empty()) {
364 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
365 << " has NO port state observer";
366 return;
367 }
368 for (auto& observer : observers_) {
369 uint16_t cookie = observer.first;
370 std::shared_ptr<PortStatusCallbacks> callback = observer.second;
371 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
372 << " notify to bluetooth_audio=0x"
373 << ::android::base::StringPrintf("%04x", cookie);
374 callback->session_changed_cb_(cookie);
375 }
376}
377
378/***
379 *
380 * PCM methods
381 *
382 ***/
383
384size_t BluetoothAudioSession::OutWritePcmData(const void* buffer,
385 size_t bytes) {
386 if (buffer == nullptr || bytes <= 0) {
387 return 0;
388 }
389 size_t total_written = 0;
390 int timeout_ms = kFmqSendTimeoutMs;
391 do {
392 std::unique_lock<std::recursive_mutex> lock(mutex_);
393 if (!IsSessionReady()) {
394 break;
395 }
396 size_t num_bytes_to_write = data_mq_->availableToWrite();
397 if (num_bytes_to_write) {
398 if (num_bytes_to_write > (bytes - total_written)) {
399 num_bytes_to_write = bytes - total_written;
400 }
401
402 if (!data_mq_->write(
403 static_cast<const MQDataType*>(buffer) + total_written,
404 num_bytes_to_write)) {
405 LOG(ERROR) << "FMQ datapath writing " << total_written << "/" << bytes
406 << " failed";
407 return total_written;
408 }
409 total_written += num_bytes_to_write;
410 } else if (timeout_ms >= kWritePollMs) {
411 lock.unlock();
412 usleep(kWritePollMs * 1000);
413 timeout_ms -= kWritePollMs;
414 } else {
415 LOG(DEBUG) << "Data " << total_written << "/" << bytes << " overflow "
416 << (kFmqSendTimeoutMs - timeout_ms) << " ms";
417 return total_written;
418 }
419 } while (total_written < bytes);
420 return total_written;
421}
422
423size_t BluetoothAudioSession::InReadPcmData(void* buffer, size_t bytes) {
424 if (buffer == nullptr || bytes <= 0) {
425 return 0;
426 }
427 size_t total_read = 0;
428 int timeout_ms = kFmqReceiveTimeoutMs;
429 do {
430 std::unique_lock<std::recursive_mutex> lock(mutex_);
431 if (!IsSessionReady()) {
432 break;
433 }
434 size_t num_bytes_to_read = data_mq_->availableToRead();
435 if (num_bytes_to_read) {
436 if (num_bytes_to_read > (bytes - total_read)) {
437 num_bytes_to_read = bytes - total_read;
438 }
439 if (!data_mq_->read(static_cast<MQDataType*>(buffer) + total_read,
440 num_bytes_to_read)) {
441 LOG(ERROR) << "FMQ datapath reading " << total_read << "/" << bytes
442 << " failed";
443 return total_read;
444 }
445 total_read += num_bytes_to_read;
446 } else if (timeout_ms >= kReadPollMs) {
447 lock.unlock();
448 usleep(kReadPollMs * 1000);
449 timeout_ms -= kReadPollMs;
450 continue;
451 } else {
452 LOG(DEBUG) << "Data " << total_read << "/" << bytes << " overflow "
453 << (kFmqReceiveTimeoutMs - timeout_ms) << " ms";
454 return total_read;
455 }
456 } while (total_read < bytes);
457 return total_read;
458}
459
460/***
461 *
462 * Other methods
463 *
464 ***/
465
466void BluetoothAudioSession::ReportControlStatus(bool start_resp,
467 BluetoothAudioStatus status) {
468 std::lock_guard<std::recursive_mutex> guard(mutex_);
469 if (observers_.empty()) {
470 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
471 << " has NO port state observer";
472 return;
473 }
474 for (auto& observer : observers_) {
475 uint16_t cookie = observer.first;
476 std::shared_ptr<PortStatusCallbacks> callback = observer.second;
477 LOG(INFO) << __func__ << " - status=" << toString(status)
478 << " for SessionType=" << toString(session_type_)
479 << ", bluetooth_audio=0x"
480 << ::android::base::StringPrintf("%04x", cookie)
481 << (start_resp ? " started" : " suspended");
482 callback->control_result_cb_(cookie, start_resp, status);
483 }
484}
485
Chen Chen81f38e52022-02-09 13:27:35 -0800486void BluetoothAudioSession::ReportLowLatencyModeAllowedChanged(bool allowed) {
Alice Kuo42b85ab2023-11-20 14:28:41 +0800487 if (session_type_ != SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
488 return;
489 }
Chen Chen81f38e52022-02-09 13:27:35 -0800490 std::lock_guard<std::recursive_mutex> guard(mutex_);
Cheney Ni6ecbc762022-03-03 00:12:48 +0800491 low_latency_allowed_ = allowed;
kuanyuhuang25b48192023-08-07 05:05:52 +0000492 // TODO(b/294498919): Remove this after there is API to update latency mode
493 // after audio session started. If low_latency_allowed_ is true, the session
494 // can support LOW_LATENCY and FREE LatencyMode.
495 if (low_latency_allowed_) {
496 if (std::find(latency_modes_.begin(), latency_modes_.end(),
497 LatencyMode::LOW_LATENCY) == latency_modes_.end()) {
498 LOG(INFO) << __func__ << " - insert LOW_LATENCY LatencyMode";
499 latency_modes_.push_back(LatencyMode::LOW_LATENCY);
500 }
501 }
Chen Chen81f38e52022-02-09 13:27:35 -0800502 if (observers_.empty()) {
503 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
504 << " has NO port state observer";
505 return;
506 }
507 for (auto& observer : observers_) {
508 uint16_t cookie = observer.first;
509 std::shared_ptr<PortStatusCallbacks> callback = observer.second;
Greg Kaiser42d931a2022-02-11 06:43:59 -0800510 LOG(INFO) << __func__
511 << " - allowed=" << (allowed ? " allowed" : " disallowed");
Chen Chen3b46c052022-03-14 13:16:44 -0700512 if (callback->low_latency_mode_allowed_cb_ != nullptr) {
513 callback->low_latency_mode_allowed_cb_(cookie, allowed);
514 }
Chen Chen81f38e52022-02-09 13:27:35 -0800515 }
516}
517
Josh Wu20bac522021-12-29 23:52:39 -0800518bool BluetoothAudioSession::GetPresentationPosition(
519 PresentationPosition& presentation_position) {
520 std::lock_guard<std::recursive_mutex> guard(mutex_);
521 if (!IsSessionReady()) {
522 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
523 << " has NO session";
524 return false;
525 }
Josh Wu20bac522021-12-29 23:52:39 -0800526 if (!stack_iface_->getPresentationPosition(&presentation_position).isOk()) {
527 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
528 << toString(session_type_) << " failed";
529 return false;
530 }
Mikhail Naganova88cf602023-12-13 14:35:11 -0800531 return true;
Josh Wu20bac522021-12-29 23:52:39 -0800532}
533
534void BluetoothAudioSession::UpdateSourceMetadata(
535 const struct source_metadata& source_metadata) {
Josh Wu20bac522021-12-29 23:52:39 -0800536 ssize_t track_count = source_metadata.track_count;
537 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
538 << track_count << " track(s)";
Josh Wu20bac522021-12-29 23:52:39 -0800539 SourceMetadata hal_source_metadata;
540 hal_source_metadata.tracks.resize(track_count);
541 for (int i = 0; i < track_count; i++) {
542 hal_source_metadata.tracks[i].usage =
543 static_cast<media::audio::common::AudioUsage>(
544 source_metadata.tracks[i].usage);
545 hal_source_metadata.tracks[i].contentType =
546 static_cast<media::audio::common::AudioContentType>(
547 source_metadata.tracks[i].content_type);
548 hal_source_metadata.tracks[i].gain = source_metadata.tracks[i].gain;
549 LOG(VERBOSE) << __func__ << " - SessionType=" << toString(session_type_)
550 << ", usage=" << toString(hal_source_metadata.tracks[i].usage)
551 << ", content="
552 << toString(hal_source_metadata.tracks[i].contentType)
553 << ", gain=" << hal_source_metadata.tracks[i].gain;
554 }
Mikhail Naganovd5f0d132023-07-26 17:26:02 -0700555 UpdateSourceMetadata(hal_source_metadata);
Josh Wu20bac522021-12-29 23:52:39 -0800556}
557
558void BluetoothAudioSession::UpdateSinkMetadata(
559 const struct sink_metadata& sink_metadata) {
Josh Wu20bac522021-12-29 23:52:39 -0800560 ssize_t track_count = sink_metadata.track_count;
561 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
562 << track_count << " track(s)";
Josh Wu20bac522021-12-29 23:52:39 -0800563 SinkMetadata hal_sink_metadata;
564 hal_sink_metadata.tracks.resize(track_count);
565 for (int i = 0; i < track_count; i++) {
566 hal_sink_metadata.tracks[i].source =
567 static_cast<media::audio::common::AudioSource>(
568 sink_metadata.tracks[i].source);
569 hal_sink_metadata.tracks[i].gain = sink_metadata.tracks[i].gain;
570 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
571 << ", source=" << sink_metadata.tracks[i].source
572 << ", dest_device=" << sink_metadata.tracks[i].dest_device
573 << ", gain=" << sink_metadata.tracks[i].gain
574 << ", dest_device_address="
575 << sink_metadata.tracks[i].dest_device_address;
576 }
Mikhail Naganovd5f0d132023-07-26 17:26:02 -0700577 UpdateSinkMetadata(hal_sink_metadata);
578}
579
580bool BluetoothAudioSession::UpdateSourceMetadata(
581 const SourceMetadata& hal_source_metadata) {
582 std::lock_guard<std::recursive_mutex> guard(mutex_);
583 if (!IsSessionReady()) {
584 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
585 << " has NO session";
586 return false;
587 }
588
589 if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
590 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
591 session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
592 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
593 return false;
594 }
595
596 auto hal_retval = stack_iface_->updateSourceMetadata(hal_source_metadata);
597 if (!hal_retval.isOk()) {
598 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
599 << toString(session_type_) << " failed";
600 return false;
601 }
602 return true;
603}
604
605bool BluetoothAudioSession::UpdateSinkMetadata(
606 const SinkMetadata& hal_sink_metadata) {
607 std::lock_guard<std::recursive_mutex> guard(mutex_);
608 if (!IsSessionReady()) {
609 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
610 << " has NO session";
611 return false;
612 }
613
614 if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
615 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
616 session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
617 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
618 return false;
619 }
Josh Wu20bac522021-12-29 23:52:39 -0800620
621 auto hal_retval = stack_iface_->updateSinkMetadata(hal_sink_metadata);
622 if (!hal_retval.isOk()) {
623 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
624 << toString(session_type_) << " failed";
Mikhail Naganovd5f0d132023-07-26 17:26:02 -0700625 return false;
Josh Wu20bac522021-12-29 23:52:39 -0800626 }
Mikhail Naganovd5f0d132023-07-26 17:26:02 -0700627 return true;
Josh Wu20bac522021-12-29 23:52:39 -0800628}
629
Cheney Ni6ecbc762022-03-03 00:12:48 +0800630std::vector<LatencyMode> BluetoothAudioSession::GetSupportedLatencyModes() {
631 std::lock_guard<std::recursive_mutex> guard(mutex_);
632 if (!IsSessionReady()) {
633 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
634 << " has NO session";
635 return std::vector<LatencyMode>();
636 }
Limon Mia7c480342023-11-20 03:59:49 +0000637
Limon Miab58cee42023-12-01 12:16:00 +0000638 if (com::android::btaudio::hal::flags::dsa_lea()) {
639 std::vector<LatencyMode> supported_latency_modes;
640 if (session_type_ ==
641 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
642 for (LatencyMode mode : latency_modes_) {
643 if (mode == LatencyMode::LOW_LATENCY) {
644 // LOW_LATENCY is not supported for LE_HARDWARE_OFFLOAD_ENC sessions
645 continue;
646 }
647 supported_latency_modes.push_back(mode);
Limon Mia7c480342023-11-20 03:59:49 +0000648 }
Limon Miab58cee42023-12-01 12:16:00 +0000649 } else {
650 for (LatencyMode mode : latency_modes_) {
651 if (!low_latency_allowed_ && mode == LatencyMode::LOW_LATENCY) {
652 // ignore LOW_LATENCY mode if Bluetooth stack doesn't allow
653 continue;
654 }
655 if (mode == LatencyMode::DYNAMIC_SPATIAL_AUDIO_SOFTWARE ||
656 mode == LatencyMode::DYNAMIC_SPATIAL_AUDIO_HARDWARE) {
657 // DSA_SW and DSA_HW only supported for LE_HARDWARE_OFFLOAD_ENC
658 // sessions
659 continue;
660 }
661 supported_latency_modes.push_back(mode);
662 }
Limon Mia7c480342023-11-20 03:59:49 +0000663 }
Limon Miab58cee42023-12-01 12:16:00 +0000664 LOG(DEBUG) << __func__ << " - Supported LatencyMode="
665 << toString(supported_latency_modes);
666 return supported_latency_modes;
Cheney Ni6ecbc762022-03-03 00:12:48 +0800667 }
Limon Miab58cee42023-12-01 12:16:00 +0000668
669 if (low_latency_allowed_) return latency_modes_;
670 std::vector<LatencyMode> modes;
671 for (LatencyMode mode : latency_modes_) {
672 if (mode == LatencyMode::LOW_LATENCY)
673 // ignore those low latency mode if Bluetooth stack doesn't allow
674 continue;
675 modes.push_back(mode);
676 }
677 return modes;
Cheney Ni6ecbc762022-03-03 00:12:48 +0800678}
679
680void BluetoothAudioSession::SetLatencyMode(const LatencyMode& latency_mode) {
Chen Chena4c4c612022-02-07 18:01:05 -0800681 std::lock_guard<std::recursive_mutex> guard(mutex_);
682 if (!IsSessionReady()) {
683 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
684 << " has NO session";
685 return;
686 }
687
688 auto hal_retval = stack_iface_->setLatencyMode(latency_mode);
689 if (!hal_retval.isOk()) {
690 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
691 << toString(session_type_) << " failed";
692 }
693}
694
Josh Wu20bac522021-12-29 23:52:39 -0800695bool BluetoothAudioSession::IsAidlAvailable() {
696 if (is_aidl_checked) return is_aidl_available;
697 is_aidl_available =
698 (AServiceManager_checkService(
699 kDefaultAudioProviderFactoryInterface.c_str()) != nullptr);
700 is_aidl_checked = true;
701 return is_aidl_available;
702}
703
704/***
705 *
706 * BluetoothAudioSessionInstance
707 *
708 ***/
709std::mutex BluetoothAudioSessionInstance::mutex_;
710std::unordered_map<SessionType, std::shared_ptr<BluetoothAudioSession>>
711 BluetoothAudioSessionInstance::sessions_map_;
712
713std::shared_ptr<BluetoothAudioSession>
714BluetoothAudioSessionInstance::GetSessionInstance(
715 const SessionType& session_type) {
716 std::lock_guard<std::mutex> guard(mutex_);
717
718 if (!sessions_map_.empty()) {
719 auto entry = sessions_map_.find(session_type);
720 if (entry != sessions_map_.end()) {
721 return entry->second;
722 }
723 }
724 std::shared_ptr<BluetoothAudioSession> session_ptr =
725 std::make_shared<BluetoothAudioSession>(session_type);
726 sessions_map_[session_type] = session_ptr;
727 return session_ptr;
728}
729
730} // namespace audio
731} // namespace bluetooth
732} // namespace hardware
733} // namespace android
Greg Kaiser42d931a2022-02-11 06:43:59 -0800734} // namespace aidl