blob: 292d352b9c6a86c8224b4259fabb89118d78bb27 [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>
23
24#include "BluetoothAudioSession.h"
25
26namespace aidl {
27namespace android {
28namespace hardware {
29namespace bluetooth {
30namespace audio {
31
32static constexpr int kFmqSendTimeoutMs = 1000; // 1000 ms timeout for sending
33static constexpr int kFmqReceiveTimeoutMs =
34 1000; // 1000 ms timeout for receiving
35static constexpr int kWritePollMs = 1; // polled non-blocking interval
36static constexpr int kReadPollMs = 1; // polled non-blocking interval
37
Josh Wu20bac522021-12-29 23:52:39 -080038BluetoothAudioSession::BluetoothAudioSession(const SessionType& session_type)
Josh Wu75462aa2022-01-21 21:51:21 -080039 : session_type_(session_type), stack_iface_(nullptr), data_mq_(nullptr) {}
Josh Wu20bac522021-12-29 23:52:39 -080040
41/***
42 *
43 * Callback methods
44 *
45 ***/
46
47void BluetoothAudioSession::OnSessionStarted(
48 const std::shared_ptr<IBluetoothAudioPort> stack_iface,
Cheney Ni6ecbc762022-03-03 00:12:48 +080049 const DataMQDesc* mq_desc, const AudioConfiguration& audio_config,
50 const std::vector<LatencyMode>& latency_modes) {
Josh Wu20bac522021-12-29 23:52:39 -080051 std::lock_guard<std::recursive_mutex> guard(mutex_);
52 if (stack_iface == nullptr) {
53 LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
54 << ", IBluetoothAudioPort Invalid";
55 } else if (!UpdateAudioConfig(audio_config)) {
56 LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
57 << ", AudioConfiguration=" << audio_config.toString()
58 << " Invalid";
59 } else if (!UpdateDataPath(mq_desc)) {
60 LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
61 << " MqDescriptor Invalid";
Josh Wu75462aa2022-01-21 21:51:21 -080062 audio_config_ = nullptr;
Josh Wu20bac522021-12-29 23:52:39 -080063 } else {
64 stack_iface_ = stack_iface;
Cheney Ni6ecbc762022-03-03 00:12:48 +080065 latency_modes_ = latency_modes;
Josh Wu20bac522021-12-29 23:52:39 -080066 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
67 << ", AudioConfiguration=" << audio_config.toString();
68 ReportSessionStatus();
69 }
70}
71
72void BluetoothAudioSession::OnSessionEnded() {
73 std::lock_guard<std::recursive_mutex> guard(mutex_);
74 bool toggled = IsSessionReady();
75 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
Josh Wu75462aa2022-01-21 21:51:21 -080076 audio_config_ = nullptr;
Josh Wu20bac522021-12-29 23:52:39 -080077 stack_iface_ = nullptr;
78 UpdateDataPath(nullptr);
79 if (toggled) {
80 ReportSessionStatus();
81 }
82}
83
84/***
85 *
86 * Util methods
87 *
88 ***/
89
Josh Wu75462aa2022-01-21 21:51:21 -080090const AudioConfiguration BluetoothAudioSession::GetAudioConfig() {
Josh Wu20bac522021-12-29 23:52:39 -080091 std::lock_guard<std::recursive_mutex> guard(mutex_);
92 if (!IsSessionReady()) {
Josh Wu20bac522021-12-29 23:52:39 -080093 switch (session_type_) {
94 case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
Alice Kuoadcceec2022-03-28 13:28:43 +080095 case SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH:
Josh Wu75462aa2022-01-21 21:51:21 -080096 return AudioConfiguration(CodecConfiguration{});
Josh Wu20bac522021-12-29 23:52:39 -080097 case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
98 case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
Josh Wu75462aa2022-01-21 21:51:21 -080099 return AudioConfiguration(LeAudioConfiguration{});
Alice Kuoe80a5762022-02-09 14:44:29 +0800100 case SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
101 return AudioConfiguration(LeAudioBroadcastConfiguration{});
Josh Wu20bac522021-12-29 23:52:39 -0800102 default:
Josh Wu75462aa2022-01-21 21:51:21 -0800103 return AudioConfiguration(PcmConfiguration{});
Josh Wu20bac522021-12-29 23:52:39 -0800104 }
105 }
106 return *audio_config_;
107}
108
109void BluetoothAudioSession::ReportAudioConfigChanged(
110 const AudioConfiguration& audio_config) {
111 if (session_type_ !=
112 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
113 session_type_ !=
Alice Kuo36a87972022-07-08 00:32:04 +0800114 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH &&
115 session_type_ !=
116 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
Josh Wu20bac522021-12-29 23:52:39 -0800117 return;
118 }
119 std::lock_guard<std::recursive_mutex> guard(mutex_);
120 audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
121 if (observers_.empty()) {
122 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
123 << " has NO port state observer";
124 return;
125 }
126 for (auto& observer : observers_) {
127 uint16_t cookie = observer.first;
128 std::shared_ptr<struct PortStatusCallbacks> cb = observer.second;
129 LOG(INFO) << __func__ << " for SessionType=" << toString(session_type_)
130 << ", bluetooth_audio=0x"
131 << ::android::base::StringPrintf("%04x", cookie);
132 if (cb->audio_configuration_changed_cb_ != nullptr) {
133 cb->audio_configuration_changed_cb_(cookie);
134 }
135 }
136}
137
138bool BluetoothAudioSession::IsSessionReady() {
139 std::lock_guard<std::recursive_mutex> guard(mutex_);
140
141 bool is_mq_valid =
142 (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
143 session_type_ ==
144 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
145 session_type_ ==
146 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
Alice Kuoe80a5762022-02-09 14:44:29 +0800147 session_type_ ==
148 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
Alice Kuoadcceec2022-03-28 13:28:43 +0800149 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
Josh Wu20bac522021-12-29 23:52:39 -0800150 (data_mq_ != nullptr && data_mq_->isValid()));
Josh Wu75462aa2022-01-21 21:51:21 -0800151 return stack_iface_ != nullptr && is_mq_valid && audio_config_ != nullptr;
Josh Wu20bac522021-12-29 23:52:39 -0800152}
153
154/***
155 *
156 * Status callback methods
157 *
158 ***/
159
160uint16_t BluetoothAudioSession::RegisterStatusCback(
161 const PortStatusCallbacks& callbacks) {
162 std::lock_guard<std::recursive_mutex> guard(mutex_);
163 uint16_t cookie = ObserversCookieGetInitValue(session_type_);
164 uint16_t cookie_upper_bound = ObserversCookieGetUpperBound(session_type_);
165
166 while (cookie < cookie_upper_bound) {
167 if (observers_.find(cookie) == observers_.end()) {
168 break;
169 }
170 ++cookie;
171 }
172 if (cookie >= cookie_upper_bound) {
173 LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
174 << " has " << observers_.size()
175 << " observers already (No Resource)";
176 return kObserversCookieUndefined;
177 }
178 std::shared_ptr<PortStatusCallbacks> cb =
179 std::make_shared<PortStatusCallbacks>();
180 *cb = callbacks;
181 observers_[cookie] = cb;
182 return cookie;
183}
184
185void BluetoothAudioSession::UnregisterStatusCback(uint16_t cookie) {
186 std::lock_guard<std::recursive_mutex> guard(mutex_);
187 if (observers_.erase(cookie) != 1) {
188 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
189 << " no such provider=0x"
190 << ::android::base::StringPrintf("%04x", cookie);
191 }
192}
193
194/***
195 *
196 * Stream methods
197 *
198 ***/
199
Cheney Ni6ecbc762022-03-03 00:12:48 +0800200bool BluetoothAudioSession::StartStream(bool is_low_latency) {
Josh Wu20bac522021-12-29 23:52:39 -0800201 std::lock_guard<std::recursive_mutex> guard(mutex_);
202 if (!IsSessionReady()) {
203 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
204 << " has NO session";
205 return false;
206 }
Cheney Ni6ecbc762022-03-03 00:12:48 +0800207 auto hal_retval = stack_iface_->startStream(is_low_latency);
Josh Wu20bac522021-12-29 23:52:39 -0800208 if (!hal_retval.isOk()) {
209 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
210 << toString(session_type_) << " failed";
211 return false;
212 }
213 return true;
214}
215
216bool BluetoothAudioSession::SuspendStream() {
217 std::lock_guard<std::recursive_mutex> guard(mutex_);
218 if (!IsSessionReady()) {
219 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
220 << " has NO session";
221 return false;
222 }
223 auto hal_retval = stack_iface_->suspendStream();
224 if (!hal_retval.isOk()) {
225 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
226 << toString(session_type_) << " failed";
227 return false;
228 }
229 return true;
230}
231
232void BluetoothAudioSession::StopStream() {
233 std::lock_guard<std::recursive_mutex> guard(mutex_);
234 if (!IsSessionReady()) {
235 return;
236 }
237 auto hal_retval = stack_iface_->stopStream();
238 if (!hal_retval.isOk()) {
239 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
240 << toString(session_type_) << " failed";
241 }
242}
243
244/***
245 *
246 * Private methods
247 *
248 ***/
249
250bool BluetoothAudioSession::UpdateDataPath(const DataMQDesc* mq_desc) {
251 if (mq_desc == nullptr) {
252 // usecase of reset by nullptr
253 data_mq_ = nullptr;
254 return true;
255 }
256 std::unique_ptr<DataMQ> temp_mq;
257 temp_mq.reset(new DataMQ(*mq_desc));
258 if (!temp_mq || !temp_mq->isValid()) {
259 data_mq_ = nullptr;
260 return false;
261 }
262 data_mq_ = std::move(temp_mq);
263 return true;
264}
265
266bool BluetoothAudioSession::UpdateAudioConfig(
267 const AudioConfiguration& audio_config) {
268 bool is_software_session =
269 (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
270 session_type_ == SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH ||
271 session_type_ == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH ||
Alice Kuoe80a5762022-02-09 14:44:29 +0800272 session_type_ == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH ||
273 session_type_ ==
Alice Kuoadcceec2022-03-28 13:28:43 +0800274 SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH ||
275 session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH);
Josh Wu20bac522021-12-29 23:52:39 -0800276 bool is_offload_a2dp_session =
Alice Kuoadcceec2022-03-28 13:28:43 +0800277 (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
278 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH);
Alice Kuoee398a92022-07-10 23:59:18 +0800279 bool is_offload_le_audio_unicast_session =
Josh Wu20bac522021-12-29 23:52:39 -0800280 (session_type_ ==
281 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
282 session_type_ ==
283 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
Alice Kuoee398a92022-07-10 23:59:18 +0800284 bool is_offload_le_audio_broadcast_session =
285 (session_type_ ==
286 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
Josh Wu20bac522021-12-29 23:52:39 -0800287 auto audio_config_tag = audio_config.getTag();
288 bool is_software_audio_config =
289 (is_software_session &&
290 audio_config_tag == AudioConfiguration::pcmConfig);
291 bool is_a2dp_offload_audio_config =
292 (is_offload_a2dp_session &&
293 audio_config_tag == AudioConfiguration::a2dpConfig);
Alice Kuoee398a92022-07-10 23:59:18 +0800294 bool is_le_audio_offload_unicast_audio_config =
295 (is_offload_le_audio_unicast_session &&
Josh Wu20bac522021-12-29 23:52:39 -0800296 audio_config_tag == AudioConfiguration::leAudioConfig);
Alice Kuoee398a92022-07-10 23:59:18 +0800297 bool is_le_audio_offload_broadcast_audio_config =
298 (is_offload_le_audio_broadcast_session &&
299 audio_config_tag == AudioConfiguration::leAudioBroadcastConfig);
Josh Wu20bac522021-12-29 23:52:39 -0800300 if (!is_software_audio_config && !is_a2dp_offload_audio_config &&
Alice Kuoee398a92022-07-10 23:59:18 +0800301 !is_le_audio_offload_unicast_audio_config &&
302 !is_le_audio_offload_broadcast_audio_config) {
Josh Wu20bac522021-12-29 23:52:39 -0800303 return false;
304 }
305 audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
306 return true;
307}
308
309void BluetoothAudioSession::ReportSessionStatus() {
310 // This is locked already by OnSessionStarted / OnSessionEnded
311 if (observers_.empty()) {
312 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
313 << " has NO port state observer";
314 return;
315 }
316 for (auto& observer : observers_) {
317 uint16_t cookie = observer.first;
318 std::shared_ptr<PortStatusCallbacks> callback = observer.second;
319 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
320 << " notify to bluetooth_audio=0x"
321 << ::android::base::StringPrintf("%04x", cookie);
322 callback->session_changed_cb_(cookie);
323 }
324}
325
326/***
327 *
328 * PCM methods
329 *
330 ***/
331
332size_t BluetoothAudioSession::OutWritePcmData(const void* buffer,
333 size_t bytes) {
334 if (buffer == nullptr || bytes <= 0) {
335 return 0;
336 }
337 size_t total_written = 0;
338 int timeout_ms = kFmqSendTimeoutMs;
339 do {
340 std::unique_lock<std::recursive_mutex> lock(mutex_);
341 if (!IsSessionReady()) {
342 break;
343 }
344 size_t num_bytes_to_write = data_mq_->availableToWrite();
345 if (num_bytes_to_write) {
346 if (num_bytes_to_write > (bytes - total_written)) {
347 num_bytes_to_write = bytes - total_written;
348 }
349
350 if (!data_mq_->write(
351 static_cast<const MQDataType*>(buffer) + total_written,
352 num_bytes_to_write)) {
353 LOG(ERROR) << "FMQ datapath writing " << total_written << "/" << bytes
354 << " failed";
355 return total_written;
356 }
357 total_written += num_bytes_to_write;
358 } else if (timeout_ms >= kWritePollMs) {
359 lock.unlock();
360 usleep(kWritePollMs * 1000);
361 timeout_ms -= kWritePollMs;
362 } else {
363 LOG(DEBUG) << "Data " << total_written << "/" << bytes << " overflow "
364 << (kFmqSendTimeoutMs - timeout_ms) << " ms";
365 return total_written;
366 }
367 } while (total_written < bytes);
368 return total_written;
369}
370
371size_t BluetoothAudioSession::InReadPcmData(void* buffer, size_t bytes) {
372 if (buffer == nullptr || bytes <= 0) {
373 return 0;
374 }
375 size_t total_read = 0;
376 int timeout_ms = kFmqReceiveTimeoutMs;
377 do {
378 std::unique_lock<std::recursive_mutex> lock(mutex_);
379 if (!IsSessionReady()) {
380 break;
381 }
382 size_t num_bytes_to_read = data_mq_->availableToRead();
383 if (num_bytes_to_read) {
384 if (num_bytes_to_read > (bytes - total_read)) {
385 num_bytes_to_read = bytes - total_read;
386 }
387 if (!data_mq_->read(static_cast<MQDataType*>(buffer) + total_read,
388 num_bytes_to_read)) {
389 LOG(ERROR) << "FMQ datapath reading " << total_read << "/" << bytes
390 << " failed";
391 return total_read;
392 }
393 total_read += num_bytes_to_read;
394 } else if (timeout_ms >= kReadPollMs) {
395 lock.unlock();
396 usleep(kReadPollMs * 1000);
397 timeout_ms -= kReadPollMs;
398 continue;
399 } else {
400 LOG(DEBUG) << "Data " << total_read << "/" << bytes << " overflow "
401 << (kFmqReceiveTimeoutMs - timeout_ms) << " ms";
402 return total_read;
403 }
404 } while (total_read < bytes);
405 return total_read;
406}
407
408/***
409 *
410 * Other methods
411 *
412 ***/
413
414void BluetoothAudioSession::ReportControlStatus(bool start_resp,
415 BluetoothAudioStatus status) {
416 std::lock_guard<std::recursive_mutex> guard(mutex_);
417 if (observers_.empty()) {
418 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
419 << " has NO port state observer";
420 return;
421 }
422 for (auto& observer : observers_) {
423 uint16_t cookie = observer.first;
424 std::shared_ptr<PortStatusCallbacks> callback = observer.second;
425 LOG(INFO) << __func__ << " - status=" << toString(status)
426 << " for SessionType=" << toString(session_type_)
427 << ", bluetooth_audio=0x"
428 << ::android::base::StringPrintf("%04x", cookie)
429 << (start_resp ? " started" : " suspended");
430 callback->control_result_cb_(cookie, start_resp, status);
431 }
432}
433
Chen Chen81f38e52022-02-09 13:27:35 -0800434void BluetoothAudioSession::ReportLowLatencyModeAllowedChanged(bool allowed) {
435 std::lock_guard<std::recursive_mutex> guard(mutex_);
Cheney Ni6ecbc762022-03-03 00:12:48 +0800436 low_latency_allowed_ = allowed;
Chen Chen81f38e52022-02-09 13:27:35 -0800437 if (observers_.empty()) {
438 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
439 << " has NO port state observer";
440 return;
441 }
442 for (auto& observer : observers_) {
443 uint16_t cookie = observer.first;
444 std::shared_ptr<PortStatusCallbacks> callback = observer.second;
Greg Kaiser42d931a2022-02-11 06:43:59 -0800445 LOG(INFO) << __func__
446 << " - allowed=" << (allowed ? " allowed" : " disallowed");
Chen Chen3b46c052022-03-14 13:16:44 -0700447 if (callback->low_latency_mode_allowed_cb_ != nullptr) {
448 callback->low_latency_mode_allowed_cb_(cookie, allowed);
449 }
Chen Chen81f38e52022-02-09 13:27:35 -0800450 }
451}
452
Josh Wu20bac522021-12-29 23:52:39 -0800453bool BluetoothAudioSession::GetPresentationPosition(
454 PresentationPosition& presentation_position) {
455 std::lock_guard<std::recursive_mutex> guard(mutex_);
456 if (!IsSessionReady()) {
457 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
458 << " has NO session";
459 return false;
460 }
461 bool retval = false;
462
463 if (!stack_iface_->getPresentationPosition(&presentation_position).isOk()) {
464 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
465 << toString(session_type_) << " failed";
466 return false;
467 }
468 return retval;
469}
470
471void BluetoothAudioSession::UpdateSourceMetadata(
472 const struct source_metadata& source_metadata) {
473 std::lock_guard<std::recursive_mutex> guard(mutex_);
474 if (!IsSessionReady()) {
475 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
476 << " has NO session";
477 return;
478 }
479
480 ssize_t track_count = source_metadata.track_count;
481 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
482 << track_count << " track(s)";
483 if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
Alice Kuoadcceec2022-03-28 13:28:43 +0800484 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
485 session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
486 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
Josh Wu20bac522021-12-29 23:52:39 -0800487 return;
488 }
489
490 SourceMetadata hal_source_metadata;
491 hal_source_metadata.tracks.resize(track_count);
492 for (int i = 0; i < track_count; i++) {
493 hal_source_metadata.tracks[i].usage =
494 static_cast<media::audio::common::AudioUsage>(
495 source_metadata.tracks[i].usage);
496 hal_source_metadata.tracks[i].contentType =
497 static_cast<media::audio::common::AudioContentType>(
498 source_metadata.tracks[i].content_type);
499 hal_source_metadata.tracks[i].gain = source_metadata.tracks[i].gain;
500 LOG(VERBOSE) << __func__ << " - SessionType=" << toString(session_type_)
501 << ", usage=" << toString(hal_source_metadata.tracks[i].usage)
502 << ", content="
503 << toString(hal_source_metadata.tracks[i].contentType)
504 << ", gain=" << hal_source_metadata.tracks[i].gain;
505 }
506
507 auto hal_retval = stack_iface_->updateSourceMetadata(hal_source_metadata);
508 if (!hal_retval.isOk()) {
509 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
510 << toString(session_type_) << " failed";
511 }
512}
513
514void BluetoothAudioSession::UpdateSinkMetadata(
515 const struct sink_metadata& sink_metadata) {
516 std::lock_guard<std::recursive_mutex> guard(mutex_);
517 if (!IsSessionReady()) {
518 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
519 << " has NO session";
520 return;
521 }
522
523 ssize_t track_count = sink_metadata.track_count;
524 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
525 << track_count << " track(s)";
526 if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
Alice Kuoadcceec2022-03-28 13:28:43 +0800527 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
528 session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
529 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
Josh Wu20bac522021-12-29 23:52:39 -0800530 return;
531 }
532
533 SinkMetadata hal_sink_metadata;
534 hal_sink_metadata.tracks.resize(track_count);
535 for (int i = 0; i < track_count; i++) {
536 hal_sink_metadata.tracks[i].source =
537 static_cast<media::audio::common::AudioSource>(
538 sink_metadata.tracks[i].source);
539 hal_sink_metadata.tracks[i].gain = sink_metadata.tracks[i].gain;
540 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
541 << ", source=" << sink_metadata.tracks[i].source
542 << ", dest_device=" << sink_metadata.tracks[i].dest_device
543 << ", gain=" << sink_metadata.tracks[i].gain
544 << ", dest_device_address="
545 << sink_metadata.tracks[i].dest_device_address;
546 }
547
548 auto hal_retval = stack_iface_->updateSinkMetadata(hal_sink_metadata);
549 if (!hal_retval.isOk()) {
550 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
551 << toString(session_type_) << " failed";
552 }
553}
554
Cheney Ni6ecbc762022-03-03 00:12:48 +0800555std::vector<LatencyMode> BluetoothAudioSession::GetSupportedLatencyModes() {
556 std::lock_guard<std::recursive_mutex> guard(mutex_);
557 if (!IsSessionReady()) {
558 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
559 << " has NO session";
560 return std::vector<LatencyMode>();
561 }
562 if (low_latency_allowed_) return latency_modes_;
563 std::vector<LatencyMode> modes;
564 for (LatencyMode mode : latency_modes_) {
565 if (mode == LatencyMode::LOW_LATENCY)
566 // ignore those low latency mode if Bluetooth stack doesn't allow
567 continue;
568 modes.push_back(mode);
569 }
570 return modes;
571}
572
573void BluetoothAudioSession::SetLatencyMode(const LatencyMode& latency_mode) {
Chen Chena4c4c612022-02-07 18:01:05 -0800574 std::lock_guard<std::recursive_mutex> guard(mutex_);
575 if (!IsSessionReady()) {
576 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
577 << " has NO session";
578 return;
579 }
580
581 auto hal_retval = stack_iface_->setLatencyMode(latency_mode);
582 if (!hal_retval.isOk()) {
583 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
584 << toString(session_type_) << " failed";
585 }
586}
587
Josh Wu20bac522021-12-29 23:52:39 -0800588bool BluetoothAudioSession::IsAidlAvailable() {
589 if (is_aidl_checked) return is_aidl_available;
590 is_aidl_available =
591 (AServiceManager_checkService(
592 kDefaultAudioProviderFactoryInterface.c_str()) != nullptr);
593 is_aidl_checked = true;
594 return is_aidl_available;
595}
596
597/***
598 *
599 * BluetoothAudioSessionInstance
600 *
601 ***/
602std::mutex BluetoothAudioSessionInstance::mutex_;
603std::unordered_map<SessionType, std::shared_ptr<BluetoothAudioSession>>
604 BluetoothAudioSessionInstance::sessions_map_;
605
606std::shared_ptr<BluetoothAudioSession>
607BluetoothAudioSessionInstance::GetSessionInstance(
608 const SessionType& session_type) {
609 std::lock_guard<std::mutex> guard(mutex_);
610
611 if (!sessions_map_.empty()) {
612 auto entry = sessions_map_.find(session_type);
613 if (entry != sessions_map_.end()) {
614 return entry->second;
615 }
616 }
617 std::shared_ptr<BluetoothAudioSession> session_ptr =
618 std::make_shared<BluetoothAudioSession>(session_type);
619 sessions_map_[session_type] = session_ptr;
620 return session_ptr;
621}
622
623} // namespace audio
624} // namespace bluetooth
625} // namespace hardware
626} // namespace android
Greg Kaiser42d931a2022-02-11 06:43:59 -0800627} // namespace aidl