blob: 2b0caadeae050f5e2e13b59154cf52658efdae87 [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;
Alice Kuo851ef342022-08-25 02:45:02 +080063 leaudio_connection_map_ = 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();
Alice Kuo851ef342022-08-25 02:45:02 +080070 is_streaming_ = false;
Josh Wu20bac522021-12-29 23:52:39 -080071 }
72}
73
74void BluetoothAudioSession::OnSessionEnded() {
75 std::lock_guard<std::recursive_mutex> guard(mutex_);
76 bool toggled = IsSessionReady();
77 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
Josh Wu75462aa2022-01-21 21:51:21 -080078 audio_config_ = nullptr;
Alice Kuo851ef342022-08-25 02:45:02 +080079 leaudio_connection_map_ = nullptr;
Josh Wu20bac522021-12-29 23:52:39 -080080 stack_iface_ = nullptr;
81 UpdateDataPath(nullptr);
82 if (toggled) {
83 ReportSessionStatus();
84 }
Alice Kuo851ef342022-08-25 02:45:02 +080085 is_streaming_ = false;
Josh Wu20bac522021-12-29 23:52:39 -080086}
87
88/***
89 *
90 * Util methods
91 *
92 ***/
93
Josh Wu75462aa2022-01-21 21:51:21 -080094const AudioConfiguration BluetoothAudioSession::GetAudioConfig() {
Josh Wu20bac522021-12-29 23:52:39 -080095 std::lock_guard<std::recursive_mutex> guard(mutex_);
96 if (!IsSessionReady()) {
Josh Wu20bac522021-12-29 23:52:39 -080097 switch (session_type_) {
98 case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
Alice Kuoadcceec2022-03-28 13:28:43 +080099 case SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH:
Josh Wu75462aa2022-01-21 21:51:21 -0800100 return AudioConfiguration(CodecConfiguration{});
Josh Wu20bac522021-12-29 23:52:39 -0800101 case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
102 case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
Josh Wu75462aa2022-01-21 21:51:21 -0800103 return AudioConfiguration(LeAudioConfiguration{});
Alice Kuoe80a5762022-02-09 14:44:29 +0800104 case SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
105 return AudioConfiguration(LeAudioBroadcastConfiguration{});
Josh Wu20bac522021-12-29 23:52:39 -0800106 default:
Josh Wu75462aa2022-01-21 21:51:21 -0800107 return AudioConfiguration(PcmConfiguration{});
Josh Wu20bac522021-12-29 23:52:39 -0800108 }
109 }
110 return *audio_config_;
111}
112
Alice Kuo851ef342022-08-25 02:45:02 +0800113const AudioConfiguration BluetoothAudioSession::GetLeAudioConnectionMap() {
114 std::lock_guard<std::recursive_mutex> guard(mutex_);
115 if (!IsSessionReady()) {
116 return AudioConfiguration(LeAudioConfiguration{});
117 }
118 return *leaudio_connection_map_;
119}
120
Josh Wu20bac522021-12-29 23:52:39 -0800121void BluetoothAudioSession::ReportAudioConfigChanged(
122 const AudioConfiguration& audio_config) {
123 if (session_type_ !=
124 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
125 session_type_ !=
Alice Kuo851ef342022-08-25 02:45:02 +0800126 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
Josh Wu20bac522021-12-29 23:52:39 -0800127 return;
128 }
Alice Kuo851ef342022-08-25 02:45:02 +0800129
Josh Wu20bac522021-12-29 23:52:39 -0800130 std::lock_guard<std::recursive_mutex> guard(mutex_);
Alice Kuo851ef342022-08-25 02:45:02 +0800131 if (audio_config.getTag() != AudioConfiguration::leAudioConfig) {
132 LOG(ERROR) << __func__ << " invalid audio config type for SessionType ="
133 << toString(session_type_);
134 return;
135 }
136
137 if (is_streaming_) {
138 if (audio_config_ == nullptr) {
139 LOG(ERROR) << __func__ << " for SessionType=" << toString(session_type_)
140 << " audio_config_ is nullptr during streaming. It shouldn't "
141 "be happened";
142 return;
143 }
144
145 auto new_leaudio_config =
146 audio_config.get<AudioConfiguration::leAudioConfig>();
147 auto current_leaudio_config =
148 (*audio_config_).get<AudioConfiguration::leAudioConfig>();
149 if (new_leaudio_config.codecType != current_leaudio_config.codecType) {
150 LOG(ERROR)
151 << __func__ << " for SessionType=" << toString(session_type_)
152 << " codec type changed during streaming. It shouldn't be happened ";
153 }
154 auto new_lc3_config = new_leaudio_config.leAudioCodecConfig
155 .get<LeAudioCodecConfiguration::lc3Config>();
156 auto current_lc3_config = current_leaudio_config.leAudioCodecConfig
157 .get<LeAudioCodecConfiguration::lc3Config>();
158 if ((new_lc3_config.pcmBitDepth != current_lc3_config.pcmBitDepth) ||
159 (new_lc3_config.samplingFrequencyHz !=
160 current_lc3_config.samplingFrequencyHz) ||
161 (new_lc3_config.frameDurationUs !=
162 current_lc3_config.frameDurationUs) ||
163 (new_lc3_config.octetsPerFrame != current_lc3_config.octetsPerFrame) ||
164 (new_lc3_config.blocksPerSdu != current_lc3_config.blocksPerSdu)) {
165 LOG(ERROR)
166 << __func__ << " for SessionType=" << toString(session_type_)
167 << " lc3 config changed during streaming. It shouldn't be happened";
168 return;
169 }
170
171 leaudio_connection_map_ =
172 std::make_unique<AudioConfiguration>(audio_config);
173 } else {
174 audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
175 leaudio_connection_map_ =
176 std::make_unique<AudioConfiguration>(audio_config);
177 }
178
Josh Wu20bac522021-12-29 23:52:39 -0800179 if (observers_.empty()) {
180 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
181 << " has NO port state observer";
182 return;
183 }
184 for (auto& observer : observers_) {
185 uint16_t cookie = observer.first;
186 std::shared_ptr<struct PortStatusCallbacks> cb = observer.second;
187 LOG(INFO) << __func__ << " for SessionType=" << toString(session_type_)
188 << ", bluetooth_audio=0x"
189 << ::android::base::StringPrintf("%04x", cookie);
Alice Kuo851ef342022-08-25 02:45:02 +0800190 if (is_streaming_) {
191 if (cb->soft_audio_configuration_changed_cb_ != nullptr) {
192 cb->soft_audio_configuration_changed_cb_(cookie);
193 }
194 } else if (cb->audio_configuration_changed_cb_ != nullptr) {
Josh Wu20bac522021-12-29 23:52:39 -0800195 cb->audio_configuration_changed_cb_(cookie);
196 }
197 }
198}
199
200bool BluetoothAudioSession::IsSessionReady() {
201 std::lock_guard<std::recursive_mutex> guard(mutex_);
202
203 bool is_mq_valid =
204 (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
205 session_type_ ==
206 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
207 session_type_ ==
208 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
Alice Kuoe80a5762022-02-09 14:44:29 +0800209 session_type_ ==
210 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
Alice Kuoadcceec2022-03-28 13:28:43 +0800211 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
Josh Wu20bac522021-12-29 23:52:39 -0800212 (data_mq_ != nullptr && data_mq_->isValid()));
Josh Wu75462aa2022-01-21 21:51:21 -0800213 return stack_iface_ != nullptr && is_mq_valid && audio_config_ != nullptr;
Josh Wu20bac522021-12-29 23:52:39 -0800214}
215
216/***
217 *
218 * Status callback methods
219 *
220 ***/
221
222uint16_t BluetoothAudioSession::RegisterStatusCback(
223 const PortStatusCallbacks& callbacks) {
224 std::lock_guard<std::recursive_mutex> guard(mutex_);
225 uint16_t cookie = ObserversCookieGetInitValue(session_type_);
226 uint16_t cookie_upper_bound = ObserversCookieGetUpperBound(session_type_);
227
228 while (cookie < cookie_upper_bound) {
229 if (observers_.find(cookie) == observers_.end()) {
230 break;
231 }
232 ++cookie;
233 }
234 if (cookie >= cookie_upper_bound) {
235 LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
236 << " has " << observers_.size()
237 << " observers already (No Resource)";
238 return kObserversCookieUndefined;
239 }
240 std::shared_ptr<PortStatusCallbacks> cb =
241 std::make_shared<PortStatusCallbacks>();
242 *cb = callbacks;
243 observers_[cookie] = cb;
244 return cookie;
245}
246
247void BluetoothAudioSession::UnregisterStatusCback(uint16_t cookie) {
248 std::lock_guard<std::recursive_mutex> guard(mutex_);
249 if (observers_.erase(cookie) != 1) {
250 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
251 << " no such provider=0x"
252 << ::android::base::StringPrintf("%04x", cookie);
253 }
254}
255
256/***
257 *
258 * Stream methods
259 *
260 ***/
261
Cheney Ni6ecbc762022-03-03 00:12:48 +0800262bool BluetoothAudioSession::StartStream(bool is_low_latency) {
Josh Wu20bac522021-12-29 23:52:39 -0800263 std::lock_guard<std::recursive_mutex> guard(mutex_);
264 if (!IsSessionReady()) {
265 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
266 << " has NO session";
267 return false;
268 }
Cheney Ni6ecbc762022-03-03 00:12:48 +0800269 auto hal_retval = stack_iface_->startStream(is_low_latency);
Josh Wu20bac522021-12-29 23:52:39 -0800270 if (!hal_retval.isOk()) {
271 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
272 << toString(session_type_) << " failed";
273 return false;
274 }
275 return true;
276}
277
278bool BluetoothAudioSession::SuspendStream() {
279 std::lock_guard<std::recursive_mutex> guard(mutex_);
280 if (!IsSessionReady()) {
281 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
282 << " has NO session";
283 return false;
284 }
285 auto hal_retval = stack_iface_->suspendStream();
286 if (!hal_retval.isOk()) {
287 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
288 << toString(session_type_) << " failed";
289 return false;
290 }
291 return true;
292}
293
294void BluetoothAudioSession::StopStream() {
295 std::lock_guard<std::recursive_mutex> guard(mutex_);
296 if (!IsSessionReady()) {
297 return;
298 }
299 auto hal_retval = stack_iface_->stopStream();
300 if (!hal_retval.isOk()) {
301 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
302 << toString(session_type_) << " failed";
303 }
304}
305
306/***
307 *
308 * Private methods
309 *
310 ***/
311
312bool BluetoothAudioSession::UpdateDataPath(const DataMQDesc* mq_desc) {
313 if (mq_desc == nullptr) {
314 // usecase of reset by nullptr
315 data_mq_ = nullptr;
316 return true;
317 }
318 std::unique_ptr<DataMQ> temp_mq;
319 temp_mq.reset(new DataMQ(*mq_desc));
320 if (!temp_mq || !temp_mq->isValid()) {
321 data_mq_ = nullptr;
322 return false;
323 }
324 data_mq_ = std::move(temp_mq);
325 return true;
326}
327
328bool BluetoothAudioSession::UpdateAudioConfig(
329 const AudioConfiguration& audio_config) {
330 bool is_software_session =
331 (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
332 session_type_ == SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH ||
333 session_type_ == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH ||
Alice Kuoe80a5762022-02-09 14:44:29 +0800334 session_type_ == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH ||
335 session_type_ ==
Alice Kuoadcceec2022-03-28 13:28:43 +0800336 SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH ||
337 session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH);
Josh Wu20bac522021-12-29 23:52:39 -0800338 bool is_offload_a2dp_session =
Alice Kuoadcceec2022-03-28 13:28:43 +0800339 (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
340 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH);
Alice Kuoee398a92022-07-10 23:59:18 +0800341 bool is_offload_le_audio_unicast_session =
Josh Wu20bac522021-12-29 23:52:39 -0800342 (session_type_ ==
343 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
344 session_type_ ==
345 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
Alice Kuoee398a92022-07-10 23:59:18 +0800346 bool is_offload_le_audio_broadcast_session =
347 (session_type_ ==
348 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
Josh Wu20bac522021-12-29 23:52:39 -0800349 auto audio_config_tag = audio_config.getTag();
350 bool is_software_audio_config =
351 (is_software_session &&
352 audio_config_tag == AudioConfiguration::pcmConfig);
353 bool is_a2dp_offload_audio_config =
354 (is_offload_a2dp_session &&
355 audio_config_tag == AudioConfiguration::a2dpConfig);
Alice Kuoee398a92022-07-10 23:59:18 +0800356 bool is_le_audio_offload_unicast_audio_config =
357 (is_offload_le_audio_unicast_session &&
Josh Wu20bac522021-12-29 23:52:39 -0800358 audio_config_tag == AudioConfiguration::leAudioConfig);
Alice Kuoee398a92022-07-10 23:59:18 +0800359 bool is_le_audio_offload_broadcast_audio_config =
360 (is_offload_le_audio_broadcast_session &&
361 audio_config_tag == AudioConfiguration::leAudioBroadcastConfig);
Josh Wu20bac522021-12-29 23:52:39 -0800362 if (!is_software_audio_config && !is_a2dp_offload_audio_config &&
Alice Kuoee398a92022-07-10 23:59:18 +0800363 !is_le_audio_offload_unicast_audio_config &&
364 !is_le_audio_offload_broadcast_audio_config) {
Josh Wu20bac522021-12-29 23:52:39 -0800365 return false;
366 }
367 audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
368 return true;
369}
370
371void BluetoothAudioSession::ReportSessionStatus() {
372 // This is locked already by OnSessionStarted / OnSessionEnded
373 if (observers_.empty()) {
374 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
375 << " has NO port state observer";
376 return;
377 }
378 for (auto& observer : observers_) {
379 uint16_t cookie = observer.first;
380 std::shared_ptr<PortStatusCallbacks> callback = observer.second;
381 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
382 << " notify to bluetooth_audio=0x"
383 << ::android::base::StringPrintf("%04x", cookie);
384 callback->session_changed_cb_(cookie);
385 }
386}
387
388/***
389 *
390 * PCM methods
391 *
392 ***/
393
394size_t BluetoothAudioSession::OutWritePcmData(const void* buffer,
395 size_t bytes) {
396 if (buffer == nullptr || bytes <= 0) {
397 return 0;
398 }
399 size_t total_written = 0;
400 int timeout_ms = kFmqSendTimeoutMs;
401 do {
402 std::unique_lock<std::recursive_mutex> lock(mutex_);
403 if (!IsSessionReady()) {
404 break;
405 }
406 size_t num_bytes_to_write = data_mq_->availableToWrite();
407 if (num_bytes_to_write) {
408 if (num_bytes_to_write > (bytes - total_written)) {
409 num_bytes_to_write = bytes - total_written;
410 }
411
412 if (!data_mq_->write(
413 static_cast<const MQDataType*>(buffer) + total_written,
414 num_bytes_to_write)) {
415 LOG(ERROR) << "FMQ datapath writing " << total_written << "/" << bytes
416 << " failed";
417 return total_written;
418 }
419 total_written += num_bytes_to_write;
420 } else if (timeout_ms >= kWritePollMs) {
421 lock.unlock();
422 usleep(kWritePollMs * 1000);
423 timeout_ms -= kWritePollMs;
424 } else {
425 LOG(DEBUG) << "Data " << total_written << "/" << bytes << " overflow "
426 << (kFmqSendTimeoutMs - timeout_ms) << " ms";
427 return total_written;
428 }
429 } while (total_written < bytes);
430 return total_written;
431}
432
433size_t BluetoothAudioSession::InReadPcmData(void* buffer, size_t bytes) {
434 if (buffer == nullptr || bytes <= 0) {
435 return 0;
436 }
437 size_t total_read = 0;
438 int timeout_ms = kFmqReceiveTimeoutMs;
439 do {
440 std::unique_lock<std::recursive_mutex> lock(mutex_);
441 if (!IsSessionReady()) {
442 break;
443 }
444 size_t num_bytes_to_read = data_mq_->availableToRead();
445 if (num_bytes_to_read) {
446 if (num_bytes_to_read > (bytes - total_read)) {
447 num_bytes_to_read = bytes - total_read;
448 }
449 if (!data_mq_->read(static_cast<MQDataType*>(buffer) + total_read,
450 num_bytes_to_read)) {
451 LOG(ERROR) << "FMQ datapath reading " << total_read << "/" << bytes
452 << " failed";
453 return total_read;
454 }
455 total_read += num_bytes_to_read;
456 } else if (timeout_ms >= kReadPollMs) {
457 lock.unlock();
458 usleep(kReadPollMs * 1000);
459 timeout_ms -= kReadPollMs;
460 continue;
461 } else {
462 LOG(DEBUG) << "Data " << total_read << "/" << bytes << " overflow "
463 << (kFmqReceiveTimeoutMs - timeout_ms) << " ms";
464 return total_read;
465 }
466 } while (total_read < bytes);
467 return total_read;
468}
469
470/***
471 *
472 * Other methods
473 *
474 ***/
475
476void BluetoothAudioSession::ReportControlStatus(bool start_resp,
477 BluetoothAudioStatus status) {
478 std::lock_guard<std::recursive_mutex> guard(mutex_);
479 if (observers_.empty()) {
480 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
481 << " has NO port state observer";
482 return;
483 }
Alice Kuo851ef342022-08-25 02:45:02 +0800484 if (start_resp && status == BluetoothAudioStatus::SUCCESS) {
485 is_streaming_ = true;
486 } else if (!start_resp && (status == BluetoothAudioStatus::SUCCESS ||
487 status == BluetoothAudioStatus::RECONFIGURATION)) {
488 is_streaming_ = false;
489 }
Josh Wu20bac522021-12-29 23:52:39 -0800490 for (auto& observer : observers_) {
491 uint16_t cookie = observer.first;
492 std::shared_ptr<PortStatusCallbacks> callback = observer.second;
493 LOG(INFO) << __func__ << " - status=" << toString(status)
494 << " for SessionType=" << toString(session_type_)
495 << ", bluetooth_audio=0x"
496 << ::android::base::StringPrintf("%04x", cookie)
497 << (start_resp ? " started" : " suspended");
498 callback->control_result_cb_(cookie, start_resp, status);
499 }
500}
501
Chen Chen81f38e52022-02-09 13:27:35 -0800502void BluetoothAudioSession::ReportLowLatencyModeAllowedChanged(bool allowed) {
503 std::lock_guard<std::recursive_mutex> guard(mutex_);
Cheney Ni6ecbc762022-03-03 00:12:48 +0800504 low_latency_allowed_ = allowed;
Chen Chen81f38e52022-02-09 13:27:35 -0800505 if (observers_.empty()) {
506 LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
507 << " has NO port state observer";
508 return;
509 }
510 for (auto& observer : observers_) {
511 uint16_t cookie = observer.first;
512 std::shared_ptr<PortStatusCallbacks> callback = observer.second;
Greg Kaiser42d931a2022-02-11 06:43:59 -0800513 LOG(INFO) << __func__
514 << " - allowed=" << (allowed ? " allowed" : " disallowed");
Chen Chen3b46c052022-03-14 13:16:44 -0700515 if (callback->low_latency_mode_allowed_cb_ != nullptr) {
516 callback->low_latency_mode_allowed_cb_(cookie, allowed);
517 }
Chen Chen81f38e52022-02-09 13:27:35 -0800518 }
519}
520
Josh Wu20bac522021-12-29 23:52:39 -0800521bool BluetoothAudioSession::GetPresentationPosition(
522 PresentationPosition& presentation_position) {
523 std::lock_guard<std::recursive_mutex> guard(mutex_);
524 if (!IsSessionReady()) {
525 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
526 << " has NO session";
527 return false;
528 }
529 bool retval = false;
530
531 if (!stack_iface_->getPresentationPosition(&presentation_position).isOk()) {
532 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
533 << toString(session_type_) << " failed";
534 return false;
535 }
536 return retval;
537}
538
539void BluetoothAudioSession::UpdateSourceMetadata(
540 const struct source_metadata& source_metadata) {
541 std::lock_guard<std::recursive_mutex> guard(mutex_);
542 if (!IsSessionReady()) {
543 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
544 << " has NO session";
545 return;
546 }
547
548 ssize_t track_count = source_metadata.track_count;
549 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
550 << track_count << " track(s)";
551 if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
Alice Kuoadcceec2022-03-28 13:28:43 +0800552 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
553 session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
554 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
Josh Wu20bac522021-12-29 23:52:39 -0800555 return;
556 }
557
558 SourceMetadata hal_source_metadata;
559 hal_source_metadata.tracks.resize(track_count);
560 for (int i = 0; i < track_count; i++) {
561 hal_source_metadata.tracks[i].usage =
562 static_cast<media::audio::common::AudioUsage>(
563 source_metadata.tracks[i].usage);
564 hal_source_metadata.tracks[i].contentType =
565 static_cast<media::audio::common::AudioContentType>(
566 source_metadata.tracks[i].content_type);
567 hal_source_metadata.tracks[i].gain = source_metadata.tracks[i].gain;
568 LOG(VERBOSE) << __func__ << " - SessionType=" << toString(session_type_)
569 << ", usage=" << toString(hal_source_metadata.tracks[i].usage)
570 << ", content="
571 << toString(hal_source_metadata.tracks[i].contentType)
572 << ", gain=" << hal_source_metadata.tracks[i].gain;
573 }
574
575 auto hal_retval = stack_iface_->updateSourceMetadata(hal_source_metadata);
576 if (!hal_retval.isOk()) {
577 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
578 << toString(session_type_) << " failed";
579 }
580}
581
582void BluetoothAudioSession::UpdateSinkMetadata(
583 const struct sink_metadata& sink_metadata) {
584 std::lock_guard<std::recursive_mutex> guard(mutex_);
585 if (!IsSessionReady()) {
586 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
587 << " has NO session";
588 return;
589 }
590
591 ssize_t track_count = sink_metadata.track_count;
592 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
593 << track_count << " track(s)";
594 if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
Alice Kuoadcceec2022-03-28 13:28:43 +0800595 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
596 session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
597 session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
Josh Wu20bac522021-12-29 23:52:39 -0800598 return;
599 }
600
601 SinkMetadata hal_sink_metadata;
602 hal_sink_metadata.tracks.resize(track_count);
603 for (int i = 0; i < track_count; i++) {
604 hal_sink_metadata.tracks[i].source =
605 static_cast<media::audio::common::AudioSource>(
606 sink_metadata.tracks[i].source);
607 hal_sink_metadata.tracks[i].gain = sink_metadata.tracks[i].gain;
608 LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
609 << ", source=" << sink_metadata.tracks[i].source
610 << ", dest_device=" << sink_metadata.tracks[i].dest_device
611 << ", gain=" << sink_metadata.tracks[i].gain
612 << ", dest_device_address="
613 << sink_metadata.tracks[i].dest_device_address;
614 }
615
616 auto hal_retval = stack_iface_->updateSinkMetadata(hal_sink_metadata);
617 if (!hal_retval.isOk()) {
618 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
619 << toString(session_type_) << " failed";
620 }
621}
622
Cheney Ni6ecbc762022-03-03 00:12:48 +0800623std::vector<LatencyMode> BluetoothAudioSession::GetSupportedLatencyModes() {
624 std::lock_guard<std::recursive_mutex> guard(mutex_);
625 if (!IsSessionReady()) {
626 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
627 << " has NO session";
628 return std::vector<LatencyMode>();
629 }
630 if (low_latency_allowed_) return latency_modes_;
631 std::vector<LatencyMode> modes;
632 for (LatencyMode mode : latency_modes_) {
633 if (mode == LatencyMode::LOW_LATENCY)
634 // ignore those low latency mode if Bluetooth stack doesn't allow
635 continue;
636 modes.push_back(mode);
637 }
638 return modes;
639}
640
641void BluetoothAudioSession::SetLatencyMode(const LatencyMode& latency_mode) {
Chen Chena4c4c612022-02-07 18:01:05 -0800642 std::lock_guard<std::recursive_mutex> guard(mutex_);
643 if (!IsSessionReady()) {
644 LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
645 << " has NO session";
646 return;
647 }
648
649 auto hal_retval = stack_iface_->setLatencyMode(latency_mode);
650 if (!hal_retval.isOk()) {
651 LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
652 << toString(session_type_) << " failed";
653 }
654}
655
Josh Wu20bac522021-12-29 23:52:39 -0800656bool BluetoothAudioSession::IsAidlAvailable() {
657 if (is_aidl_checked) return is_aidl_available;
658 is_aidl_available =
659 (AServiceManager_checkService(
660 kDefaultAudioProviderFactoryInterface.c_str()) != nullptr);
661 is_aidl_checked = true;
662 return is_aidl_available;
663}
664
665/***
666 *
667 * BluetoothAudioSessionInstance
668 *
669 ***/
670std::mutex BluetoothAudioSessionInstance::mutex_;
671std::unordered_map<SessionType, std::shared_ptr<BluetoothAudioSession>>
672 BluetoothAudioSessionInstance::sessions_map_;
673
674std::shared_ptr<BluetoothAudioSession>
675BluetoothAudioSessionInstance::GetSessionInstance(
676 const SessionType& session_type) {
677 std::lock_guard<std::mutex> guard(mutex_);
678
679 if (!sessions_map_.empty()) {
680 auto entry = sessions_map_.find(session_type);
681 if (entry != sessions_map_.end()) {
682 return entry->second;
683 }
684 }
685 std::shared_ptr<BluetoothAudioSession> session_ptr =
686 std::make_shared<BluetoothAudioSession>(session_type);
687 sessions_map_[session_type] = session_ptr;
688 return session_ptr;
689}
690
691} // namespace audio
692} // namespace bluetooth
693} // namespace hardware
694} // namespace android
Greg Kaiser42d931a2022-02-11 06:43:59 -0800695} // namespace aidl