blob: c283148a38965d5d59b6bcc0e733a1bb5f661614 [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>
Mikhail Naganovd5f0d132023-07-26 17:26:02 -070023#include <hardware/audio.h>
Josh Wu20bac522021-12-29 23:52:39 -080024
25#include "BluetoothAudioSession.h"
26
27namespace aidl {
28namespace android {
29namespace hardware {
30namespace bluetooth {
31namespace audio {
32
33static constexpr int kFmqSendTimeoutMs = 1000; // 1000 ms timeout for sending
34static constexpr int kFmqReceiveTimeoutMs =
35 1000; // 1000 ms timeout for receiving
36static constexpr int kWritePollMs = 1; // polled non-blocking interval
37static constexpr int kReadPollMs = 1; // polled non-blocking interval
38
Josh Wu20bac522021-12-29 23:52:39 -080039BluetoothAudioSession::BluetoothAudioSession(const SessionType& session_type)
Josh Wu75462aa2022-01-21 21:51:21 -080040 : session_type_(session_type), stack_iface_(nullptr), data_mq_(nullptr) {}
Josh Wu20bac522021-12-29 23:52:39 -080041
42/***
43 *
44 * Callback methods
45 *
46 ***/
47
48void BluetoothAudioSession::OnSessionStarted(
49 const std::shared_ptr<IBluetoothAudioPort> stack_iface,
Cheney Ni6ecbc762022-03-03 00:12:48 +080050 const DataMQDesc* mq_desc, const AudioConfiguration& audio_config,
51 const std::vector<LatencyMode>& latency_modes) {
Josh Wu20bac522021-12-29 23:52:39 -080052 std::lock_guard<std::recursive_mutex> guard(mutex_);
53 if (stack_iface == nullptr) {
54 LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
55 << ", IBluetoothAudioPort Invalid";
56 } else if (!UpdateAudioConfig(audio_config)) {
57 LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
58 << ", AudioConfiguration=" << audio_config.toString()
59 << " Invalid";
60 } else if (!UpdateDataPath(mq_desc)) {
61 LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
62 << " MqDescriptor Invalid";
Josh Wu75462aa2022-01-21 21:51:21 -080063 audio_config_ = nullptr;
Josh Wu20bac522021-12-29 23:52:39 -080064 } else {
65 stack_iface_ = stack_iface;
Cheney Ni6ecbc762022-03-03 00:12:48 +080066 latency_modes_ = latency_modes;
Josh Wu20bac522021-12-29 23:52:39 -080067 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
68 << ", AudioConfiguration=" << audio_config.toString();
69 ReportSessionStatus();
70 }
71}
72
73void BluetoothAudioSession::OnSessionEnded() {
74 std::lock_guard<std::recursive_mutex> guard(mutex_);
75 bool toggled = IsSessionReady();
76 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
Josh Wu75462aa2022-01-21 21:51:21 -080077 audio_config_ = nullptr;
Josh Wu20bac522021-12-29 23:52:39 -080078 stack_iface_ = nullptr;
79 UpdateDataPath(nullptr);
80 if (toggled) {
81 ReportSessionStatus();
82 }
83}
84
85/***
86 *
87 * Util methods
88 *
89 ***/
90
Josh Wu75462aa2022-01-21 21:51:21 -080091const AudioConfiguration BluetoothAudioSession::GetAudioConfig() {
Josh Wu20bac522021-12-29 23:52:39 -080092 std::lock_guard<std::recursive_mutex> guard(mutex_);
93 if (!IsSessionReady()) {
Josh Wu20bac522021-12-29 23:52:39 -080094 switch (session_type_) {
95 case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
Alice Kuoadcceec2022-03-28 13:28:43 +080096 case SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH:
Josh Wu75462aa2022-01-21 21:51:21 -080097 return AudioConfiguration(CodecConfiguration{});
Josh Wu20bac522021-12-29 23:52:39 -080098 case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
99 case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
Josh Wu75462aa2022-01-21 21:51:21 -0800100 return AudioConfiguration(LeAudioConfiguration{});
Alice Kuoe80a5762022-02-09 14:44:29 +0800101 case SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
102 return AudioConfiguration(LeAudioBroadcastConfiguration{});
Josh Wu20bac522021-12-29 23:52:39 -0800103 default:
Josh Wu75462aa2022-01-21 21:51:21 -0800104 return AudioConfiguration(PcmConfiguration{});
Josh Wu20bac522021-12-29 23:52:39 -0800105 }
106 }
107 return *audio_config_;
108}
109
110void BluetoothAudioSession::ReportAudioConfigChanged(
111 const AudioConfiguration& audio_config) {
112 if (session_type_ !=
113 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
114 session_type_ !=
Alice Kuo851ef342022-08-25 02:45:02 +0800115 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
Josh Wu20bac522021-12-29 23:52:39 -0800116 return;
117 }
Alice Kuo851ef342022-08-25 02:45:02 +0800118
Josh Wu20bac522021-12-29 23:52:39 -0800119 std::lock_guard<std::recursive_mutex> guard(mutex_);
Alice Kuo851ef342022-08-25 02:45:02 +0800120 if (audio_config.getTag() != AudioConfiguration::leAudioConfig) {
121 LOG(ERROR) << __func__ << " invalid audio config type for SessionType ="
122 << toString(session_type_);
123 return;
124 }
125
Patty Huangf5b38af2023-03-23 23:19:00 +0800126 audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
Alice Kuo851ef342022-08-25 02:45:02 +0800127
Josh Wu20bac522021-12-29 23:52:39 -0800128 if (observers_.empty()) {
129 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
130 << " has NO port state observer";
131 return;
132 }
133 for (auto& observer : observers_) {
134 uint16_t cookie = observer.first;
135 std::shared_ptr<struct PortStatusCallbacks> cb = observer.second;
136 LOG(INFO) << __func__ << " for SessionType=" << toString(session_type_)
137 << ", bluetooth_audio=0x"
138 << ::android::base::StringPrintf("%04x", cookie);
Patty Huangf5b38af2023-03-23 23:19:00 +0800139 if (cb->audio_configuration_changed_cb_ != nullptr) {
Josh Wu20bac522021-12-29 23:52:39 -0800140 cb->audio_configuration_changed_cb_(cookie);
141 }
142 }
143}
144
145bool BluetoothAudioSession::IsSessionReady() {
146 std::lock_guard<std::recursive_mutex> guard(mutex_);
147
148 bool is_mq_valid =
149 (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
150 session_type_ ==
151 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
152 session_type_ ==
153 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
Alice Kuoe80a5762022-02-09 14:44:29 +0800154 session_type_ ==
155 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
Alice Kuoadcceec2022-03-28 13:28:43 +0800156 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
Josh Wu20bac522021-12-29 23:52:39 -0800157 (data_mq_ != nullptr && data_mq_->isValid()));
Josh Wu75462aa2022-01-21 21:51:21 -0800158 return stack_iface_ != nullptr && is_mq_valid && audio_config_ != nullptr;
Josh Wu20bac522021-12-29 23:52:39 -0800159}
160
161/***
162 *
163 * Status callback methods
164 *
165 ***/
166
167uint16_t BluetoothAudioSession::RegisterStatusCback(
168 const PortStatusCallbacks& callbacks) {
169 std::lock_guard<std::recursive_mutex> guard(mutex_);
170 uint16_t cookie = ObserversCookieGetInitValue(session_type_);
171 uint16_t cookie_upper_bound = ObserversCookieGetUpperBound(session_type_);
172
173 while (cookie < cookie_upper_bound) {
174 if (observers_.find(cookie) == observers_.end()) {
175 break;
176 }
177 ++cookie;
178 }
179 if (cookie >= cookie_upper_bound) {
180 LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
181 << " has " << observers_.size()
182 << " observers already (No Resource)";
183 return kObserversCookieUndefined;
184 }
185 std::shared_ptr<PortStatusCallbacks> cb =
186 std::make_shared<PortStatusCallbacks>();
187 *cb = callbacks;
188 observers_[cookie] = cb;
189 return cookie;
190}
191
192void BluetoothAudioSession::UnregisterStatusCback(uint16_t cookie) {
193 std::lock_guard<std::recursive_mutex> guard(mutex_);
194 if (observers_.erase(cookie) != 1) {
195 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
196 << " no such provider=0x"
197 << ::android::base::StringPrintf("%04x", cookie);
198 }
199}
200
201/***
202 *
203 * Stream methods
204 *
205 ***/
206
Cheney Ni6ecbc762022-03-03 00:12:48 +0800207bool BluetoothAudioSession::StartStream(bool is_low_latency) {
Josh Wu20bac522021-12-29 23:52:39 -0800208 std::lock_guard<std::recursive_mutex> guard(mutex_);
209 if (!IsSessionReady()) {
210 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
211 << " has NO session";
212 return false;
213 }
Cheney Ni6ecbc762022-03-03 00:12:48 +0800214 auto hal_retval = stack_iface_->startStream(is_low_latency);
Josh Wu20bac522021-12-29 23:52:39 -0800215 if (!hal_retval.isOk()) {
216 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
217 << toString(session_type_) << " failed";
218 return false;
219 }
220 return true;
221}
222
223bool BluetoothAudioSession::SuspendStream() {
224 std::lock_guard<std::recursive_mutex> guard(mutex_);
225 if (!IsSessionReady()) {
226 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
227 << " has NO session";
228 return false;
229 }
230 auto hal_retval = stack_iface_->suspendStream();
231 if (!hal_retval.isOk()) {
232 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
233 << toString(session_type_) << " failed";
234 return false;
235 }
236 return true;
237}
238
239void BluetoothAudioSession::StopStream() {
240 std::lock_guard<std::recursive_mutex> guard(mutex_);
241 if (!IsSessionReady()) {
242 return;
243 }
244 auto hal_retval = stack_iface_->stopStream();
245 if (!hal_retval.isOk()) {
246 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
247 << toString(session_type_) << " failed";
248 }
249}
250
251/***
252 *
253 * Private methods
254 *
255 ***/
256
257bool BluetoothAudioSession::UpdateDataPath(const DataMQDesc* mq_desc) {
258 if (mq_desc == nullptr) {
259 // usecase of reset by nullptr
260 data_mq_ = nullptr;
261 return true;
262 }
263 std::unique_ptr<DataMQ> temp_mq;
264 temp_mq.reset(new DataMQ(*mq_desc));
265 if (!temp_mq || !temp_mq->isValid()) {
266 data_mq_ = nullptr;
267 return false;
268 }
269 data_mq_ = std::move(temp_mq);
270 return true;
271}
272
273bool BluetoothAudioSession::UpdateAudioConfig(
274 const AudioConfiguration& audio_config) {
275 bool is_software_session =
276 (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
277 session_type_ == SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH ||
278 session_type_ == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH ||
Alice Kuoe80a5762022-02-09 14:44:29 +0800279 session_type_ == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH ||
280 session_type_ ==
Alice Kuoadcceec2022-03-28 13:28:43 +0800281 SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH ||
282 session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH);
Josh Wu20bac522021-12-29 23:52:39 -0800283 bool is_offload_a2dp_session =
Alice Kuoadcceec2022-03-28 13:28:43 +0800284 (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
285 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH);
Alice Kuoee398a92022-07-10 23:59:18 +0800286 bool is_offload_le_audio_unicast_session =
Josh Wu20bac522021-12-29 23:52:39 -0800287 (session_type_ ==
288 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
289 session_type_ ==
290 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
Alice Kuoee398a92022-07-10 23:59:18 +0800291 bool is_offload_le_audio_broadcast_session =
292 (session_type_ ==
293 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
Josh Wu20bac522021-12-29 23:52:39 -0800294 auto audio_config_tag = audio_config.getTag();
295 bool is_software_audio_config =
296 (is_software_session &&
297 audio_config_tag == AudioConfiguration::pcmConfig);
298 bool is_a2dp_offload_audio_config =
299 (is_offload_a2dp_session &&
300 audio_config_tag == AudioConfiguration::a2dpConfig);
Alice Kuoee398a92022-07-10 23:59:18 +0800301 bool is_le_audio_offload_unicast_audio_config =
302 (is_offload_le_audio_unicast_session &&
Josh Wu20bac522021-12-29 23:52:39 -0800303 audio_config_tag == AudioConfiguration::leAudioConfig);
Alice Kuoee398a92022-07-10 23:59:18 +0800304 bool is_le_audio_offload_broadcast_audio_config =
305 (is_offload_le_audio_broadcast_session &&
306 audio_config_tag == AudioConfiguration::leAudioBroadcastConfig);
Josh Wu20bac522021-12-29 23:52:39 -0800307 if (!is_software_audio_config && !is_a2dp_offload_audio_config &&
Alice Kuoee398a92022-07-10 23:59:18 +0800308 !is_le_audio_offload_unicast_audio_config &&
309 !is_le_audio_offload_broadcast_audio_config) {
Josh Wu20bac522021-12-29 23:52:39 -0800310 return false;
311 }
312 audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
313 return true;
314}
315
316void BluetoothAudioSession::ReportSessionStatus() {
317 // This is locked already by OnSessionStarted / OnSessionEnded
318 if (observers_.empty()) {
319 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
320 << " has NO port state observer";
321 return;
322 }
323 for (auto& observer : observers_) {
324 uint16_t cookie = observer.first;
325 std::shared_ptr<PortStatusCallbacks> callback = observer.second;
326 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
327 << " notify to bluetooth_audio=0x"
328 << ::android::base::StringPrintf("%04x", cookie);
329 callback->session_changed_cb_(cookie);
330 }
331}
332
333/***
334 *
335 * PCM methods
336 *
337 ***/
338
339size_t BluetoothAudioSession::OutWritePcmData(const void* buffer,
340 size_t bytes) {
341 if (buffer == nullptr || bytes <= 0) {
342 return 0;
343 }
344 size_t total_written = 0;
345 int timeout_ms = kFmqSendTimeoutMs;
346 do {
347 std::unique_lock<std::recursive_mutex> lock(mutex_);
348 if (!IsSessionReady()) {
349 break;
350 }
351 size_t num_bytes_to_write = data_mq_->availableToWrite();
352 if (num_bytes_to_write) {
353 if (num_bytes_to_write > (bytes - total_written)) {
354 num_bytes_to_write = bytes - total_written;
355 }
356
357 if (!data_mq_->write(
358 static_cast<const MQDataType*>(buffer) + total_written,
359 num_bytes_to_write)) {
360 LOG(ERROR) << "FMQ datapath writing " << total_written << "/" << bytes
361 << " failed";
362 return total_written;
363 }
364 total_written += num_bytes_to_write;
365 } else if (timeout_ms >= kWritePollMs) {
366 lock.unlock();
367 usleep(kWritePollMs * 1000);
368 timeout_ms -= kWritePollMs;
369 } else {
370 LOG(DEBUG) << "Data " << total_written << "/" << bytes << " overflow "
371 << (kFmqSendTimeoutMs - timeout_ms) << " ms";
372 return total_written;
373 }
374 } while (total_written < bytes);
375 return total_written;
376}
377
378size_t BluetoothAudioSession::InReadPcmData(void* buffer, size_t bytes) {
379 if (buffer == nullptr || bytes <= 0) {
380 return 0;
381 }
382 size_t total_read = 0;
383 int timeout_ms = kFmqReceiveTimeoutMs;
384 do {
385 std::unique_lock<std::recursive_mutex> lock(mutex_);
386 if (!IsSessionReady()) {
387 break;
388 }
389 size_t num_bytes_to_read = data_mq_->availableToRead();
390 if (num_bytes_to_read) {
391 if (num_bytes_to_read > (bytes - total_read)) {
392 num_bytes_to_read = bytes - total_read;
393 }
394 if (!data_mq_->read(static_cast<MQDataType*>(buffer) + total_read,
395 num_bytes_to_read)) {
396 LOG(ERROR) << "FMQ datapath reading " << total_read << "/" << bytes
397 << " failed";
398 return total_read;
399 }
400 total_read += num_bytes_to_read;
401 } else if (timeout_ms >= kReadPollMs) {
402 lock.unlock();
403 usleep(kReadPollMs * 1000);
404 timeout_ms -= kReadPollMs;
405 continue;
406 } else {
407 LOG(DEBUG) << "Data " << total_read << "/" << bytes << " overflow "
408 << (kFmqReceiveTimeoutMs - timeout_ms) << " ms";
409 return total_read;
410 }
411 } while (total_read < bytes);
412 return total_read;
413}
414
415/***
416 *
417 * Other methods
418 *
419 ***/
420
421void BluetoothAudioSession::ReportControlStatus(bool start_resp,
422 BluetoothAudioStatus status) {
423 std::lock_guard<std::recursive_mutex> guard(mutex_);
424 if (observers_.empty()) {
425 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
426 << " has NO port state observer";
427 return;
428 }
429 for (auto& observer : observers_) {
430 uint16_t cookie = observer.first;
431 std::shared_ptr<PortStatusCallbacks> callback = observer.second;
432 LOG(INFO) << __func__ << " - status=" << toString(status)
433 << " for SessionType=" << toString(session_type_)
434 << ", bluetooth_audio=0x"
435 << ::android::base::StringPrintf("%04x", cookie)
436 << (start_resp ? " started" : " suspended");
437 callback->control_result_cb_(cookie, start_resp, status);
438 }
439}
440
Chen Chen81f38e52022-02-09 13:27:35 -0800441void BluetoothAudioSession::ReportLowLatencyModeAllowedChanged(bool allowed) {
Alice Kuo42b85ab2023-11-20 14:28:41 +0800442 if (session_type_ != SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
443 return;
444 }
Chen Chen81f38e52022-02-09 13:27:35 -0800445 std::lock_guard<std::recursive_mutex> guard(mutex_);
Cheney Ni6ecbc762022-03-03 00:12:48 +0800446 low_latency_allowed_ = allowed;
kuanyuhuang25b48192023-08-07 05:05:52 +0000447 // TODO(b/294498919): Remove this after there is API to update latency mode
448 // after audio session started. If low_latency_allowed_ is true, the session
449 // can support LOW_LATENCY and FREE LatencyMode.
450 if (low_latency_allowed_) {
451 if (std::find(latency_modes_.begin(), latency_modes_.end(),
452 LatencyMode::LOW_LATENCY) == latency_modes_.end()) {
453 LOG(INFO) << __func__ << " - insert LOW_LATENCY LatencyMode";
454 latency_modes_.push_back(LatencyMode::LOW_LATENCY);
455 }
456 }
Chen Chen81f38e52022-02-09 13:27:35 -0800457 if (observers_.empty()) {
458 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
459 << " has NO port state observer";
460 return;
461 }
462 for (auto& observer : observers_) {
463 uint16_t cookie = observer.first;
464 std::shared_ptr<PortStatusCallbacks> callback = observer.second;
Greg Kaiser42d931a2022-02-11 06:43:59 -0800465 LOG(INFO) << __func__
466 << " - allowed=" << (allowed ? " allowed" : " disallowed");
Chen Chen3b46c052022-03-14 13:16:44 -0700467 if (callback->low_latency_mode_allowed_cb_ != nullptr) {
468 callback->low_latency_mode_allowed_cb_(cookie, allowed);
469 }
Chen Chen81f38e52022-02-09 13:27:35 -0800470 }
471}
472
Josh Wu20bac522021-12-29 23:52:39 -0800473bool BluetoothAudioSession::GetPresentationPosition(
474 PresentationPosition& presentation_position) {
475 std::lock_guard<std::recursive_mutex> guard(mutex_);
476 if (!IsSessionReady()) {
477 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
478 << " has NO session";
479 return false;
480 }
481 bool retval = false;
482
483 if (!stack_iface_->getPresentationPosition(&presentation_position).isOk()) {
484 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
485 << toString(session_type_) << " failed";
486 return false;
487 }
488 return retval;
489}
490
491void BluetoothAudioSession::UpdateSourceMetadata(
492 const struct source_metadata& source_metadata) {
Josh Wu20bac522021-12-29 23:52:39 -0800493 ssize_t track_count = source_metadata.track_count;
494 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
495 << track_count << " track(s)";
Josh Wu20bac522021-12-29 23:52:39 -0800496 SourceMetadata hal_source_metadata;
497 hal_source_metadata.tracks.resize(track_count);
498 for (int i = 0; i < track_count; i++) {
499 hal_source_metadata.tracks[i].usage =
500 static_cast<media::audio::common::AudioUsage>(
501 source_metadata.tracks[i].usage);
502 hal_source_metadata.tracks[i].contentType =
503 static_cast<media::audio::common::AudioContentType>(
504 source_metadata.tracks[i].content_type);
505 hal_source_metadata.tracks[i].gain = source_metadata.tracks[i].gain;
506 LOG(VERBOSE) << __func__ << " - SessionType=" << toString(session_type_)
507 << ", usage=" << toString(hal_source_metadata.tracks[i].usage)
508 << ", content="
509 << toString(hal_source_metadata.tracks[i].contentType)
510 << ", gain=" << hal_source_metadata.tracks[i].gain;
511 }
Mikhail Naganovd5f0d132023-07-26 17:26:02 -0700512 UpdateSourceMetadata(hal_source_metadata);
Josh Wu20bac522021-12-29 23:52:39 -0800513}
514
515void BluetoothAudioSession::UpdateSinkMetadata(
516 const struct sink_metadata& sink_metadata) {
Josh Wu20bac522021-12-29 23:52:39 -0800517 ssize_t track_count = sink_metadata.track_count;
518 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
519 << track_count << " track(s)";
Josh Wu20bac522021-12-29 23:52:39 -0800520 SinkMetadata hal_sink_metadata;
521 hal_sink_metadata.tracks.resize(track_count);
522 for (int i = 0; i < track_count; i++) {
523 hal_sink_metadata.tracks[i].source =
524 static_cast<media::audio::common::AudioSource>(
525 sink_metadata.tracks[i].source);
526 hal_sink_metadata.tracks[i].gain = sink_metadata.tracks[i].gain;
527 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
528 << ", source=" << sink_metadata.tracks[i].source
529 << ", dest_device=" << sink_metadata.tracks[i].dest_device
530 << ", gain=" << sink_metadata.tracks[i].gain
531 << ", dest_device_address="
532 << sink_metadata.tracks[i].dest_device_address;
533 }
Mikhail Naganovd5f0d132023-07-26 17:26:02 -0700534 UpdateSinkMetadata(hal_sink_metadata);
535}
536
537bool BluetoothAudioSession::UpdateSourceMetadata(
538 const SourceMetadata& hal_source_metadata) {
539 std::lock_guard<std::recursive_mutex> guard(mutex_);
540 if (!IsSessionReady()) {
541 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
542 << " has NO session";
543 return false;
544 }
545
546 if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
547 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
548 session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
549 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
550 return false;
551 }
552
553 auto hal_retval = stack_iface_->updateSourceMetadata(hal_source_metadata);
554 if (!hal_retval.isOk()) {
555 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
556 << toString(session_type_) << " failed";
557 return false;
558 }
559 return true;
560}
561
562bool BluetoothAudioSession::UpdateSinkMetadata(
563 const SinkMetadata& hal_sink_metadata) {
564 std::lock_guard<std::recursive_mutex> guard(mutex_);
565 if (!IsSessionReady()) {
566 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
567 << " has NO session";
568 return false;
569 }
570
571 if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
572 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
573 session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
574 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
575 return false;
576 }
Josh Wu20bac522021-12-29 23:52:39 -0800577
578 auto hal_retval = stack_iface_->updateSinkMetadata(hal_sink_metadata);
579 if (!hal_retval.isOk()) {
580 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
581 << toString(session_type_) << " failed";
Mikhail Naganovd5f0d132023-07-26 17:26:02 -0700582 return false;
Josh Wu20bac522021-12-29 23:52:39 -0800583 }
Mikhail Naganovd5f0d132023-07-26 17:26:02 -0700584 return true;
Josh Wu20bac522021-12-29 23:52:39 -0800585}
586
Cheney Ni6ecbc762022-03-03 00:12:48 +0800587std::vector<LatencyMode> BluetoothAudioSession::GetSupportedLatencyModes() {
588 std::lock_guard<std::recursive_mutex> guard(mutex_);
589 if (!IsSessionReady()) {
590 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
591 << " has NO session";
592 return std::vector<LatencyMode>();
593 }
Limon Mia7c480342023-11-20 03:59:49 +0000594
595 std::vector<LatencyMode> supported_latency_modes;
596 if (session_type_ ==
597 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
598 for (LatencyMode mode : latency_modes_) {
599 if (mode == LatencyMode::LOW_LATENCY) {
600 // LOW_LATENCY is not supported for LE_HARDWARE_OFFLOAD_ENC sessions
601 continue;
602 }
603 supported_latency_modes.push_back(mode);
604 }
605 } else {
606 for (LatencyMode mode : latency_modes_) {
607 if (!low_latency_allowed_ && mode == LatencyMode::LOW_LATENCY) {
608 // ignore LOW_LATENCY mode if Bluetooth stack doesn't allow
609 continue;
610 }
611 if (mode == LatencyMode::DYNAMIC_SPATIAL_AUDIO_SOFTWARE ||
612 mode == LatencyMode::DYNAMIC_SPATIAL_AUDIO_HARDWARE) {
613 // DSA_SW and DSA_HW only supported for LE_HARDWARE_OFFLOAD_ENC sessions
614 continue;
615 }
616 supported_latency_modes.push_back(mode);
617 }
Cheney Ni6ecbc762022-03-03 00:12:48 +0800618 }
Limon Mia7c480342023-11-20 03:59:49 +0000619 return supported_latency_modes;
Cheney Ni6ecbc762022-03-03 00:12:48 +0800620}
621
622void BluetoothAudioSession::SetLatencyMode(const LatencyMode& latency_mode) {
Chen Chena4c4c612022-02-07 18:01:05 -0800623 std::lock_guard<std::recursive_mutex> guard(mutex_);
624 if (!IsSessionReady()) {
625 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
626 << " has NO session";
627 return;
628 }
629
630 auto hal_retval = stack_iface_->setLatencyMode(latency_mode);
631 if (!hal_retval.isOk()) {
632 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
633 << toString(session_type_) << " failed";
634 }
635}
636
Josh Wu20bac522021-12-29 23:52:39 -0800637bool BluetoothAudioSession::IsAidlAvailable() {
638 if (is_aidl_checked) return is_aidl_available;
639 is_aidl_available =
640 (AServiceManager_checkService(
641 kDefaultAudioProviderFactoryInterface.c_str()) != nullptr);
642 is_aidl_checked = true;
643 return is_aidl_available;
644}
645
646/***
647 *
648 * BluetoothAudioSessionInstance
649 *
650 ***/
651std::mutex BluetoothAudioSessionInstance::mutex_;
652std::unordered_map<SessionType, std::shared_ptr<BluetoothAudioSession>>
653 BluetoothAudioSessionInstance::sessions_map_;
654
655std::shared_ptr<BluetoothAudioSession>
656BluetoothAudioSessionInstance::GetSessionInstance(
657 const SessionType& session_type) {
658 std::lock_guard<std::mutex> guard(mutex_);
659
660 if (!sessions_map_.empty()) {
661 auto entry = sessions_map_.find(session_type);
662 if (entry != sessions_map_.end()) {
663 return entry->second;
664 }
665 }
666 std::shared_ptr<BluetoothAudioSession> session_ptr =
667 std::make_shared<BluetoothAudioSession>(session_type);
668 sessions_map_[session_type] = session_ptr;
669 return session_ptr;
670}
671
672} // namespace audio
673} // namespace bluetooth
674} // namespace hardware
675} // namespace android
Greg Kaiser42d931a2022-02-11 06:43:59 -0800676} // namespace aidl