1 /*
2 * Copyright 2023 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 #define LOG_TAG "AHAL_BluetoothAudioPort"
18
19 #include <android-base/logging.h>
20 #include <android-base/stringprintf.h>
21 #include <audio_utils/primitives.h>
22 #include <log/log.h>
23
24 #include "BluetoothAudioSessionControl.h"
25 #include "core-impl/DevicePortProxy.h"
26
27 using aidl::android::hardware::audio::common::SinkMetadata;
28 using aidl::android::hardware::audio::common::SourceMetadata;
29 using aidl::android::hardware::bluetooth::audio::AudioConfiguration;
30 using aidl::android::hardware::bluetooth::audio::BluetoothAudioSessionControl;
31 using aidl::android::hardware::bluetooth::audio::BluetoothAudioStatus;
32 using aidl::android::hardware::bluetooth::audio::ChannelMode;
33 using aidl::android::hardware::bluetooth::audio::PcmConfiguration;
34 using aidl::android::hardware::bluetooth::audio::PortStatusCallbacks;
35 using aidl::android::hardware::bluetooth::audio::PresentationPosition;
36 using aidl::android::hardware::bluetooth::audio::SessionType;
37 using aidl::android::media::audio::common::AudioDeviceDescription;
38 using aidl::android::media::audio::common::AudioDeviceType;
39 using android::base::StringPrintf;
40
41 namespace android::bluetooth::audio::aidl {
42
43 namespace {
44
45 // The maximum time to wait in std::condition_variable::wait_for()
46 constexpr unsigned int kMaxWaitingTimeMs = 4500;
47
48 } // namespace
49
operator <<(std::ostream & os,const BluetoothStreamState & state)50 std::ostream& operator<<(std::ostream& os, const BluetoothStreamState& state) {
51 switch (state) {
52 case BluetoothStreamState::DISABLED:
53 return os << "DISABLED";
54 case BluetoothStreamState::STANDBY:
55 return os << "STANDBY";
56 case BluetoothStreamState::STARTING:
57 return os << "STARTING";
58 case BluetoothStreamState::STARTED:
59 return os << "STARTED";
60 case BluetoothStreamState::SUSPENDING:
61 return os << "SUSPENDING";
62 case BluetoothStreamState::UNKNOWN:
63 return os << "UNKNOWN";
64 default:
65 return os << android::base::StringPrintf("%#hhx", state);
66 }
67 }
68
BluetoothAudioPortAidl()69 BluetoothAudioPortAidl::BluetoothAudioPortAidl()
70 : mCookie(::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined),
71 mState(BluetoothStreamState::DISABLED),
72 mSessionType(SessionType::UNKNOWN) {}
73
~BluetoothAudioPortAidl()74 BluetoothAudioPortAidl::~BluetoothAudioPortAidl() {
75 unregisterPort();
76 }
77
registerPort(const AudioDeviceDescription & description)78 bool BluetoothAudioPortAidl::registerPort(const AudioDeviceDescription& description) {
79 if (inUse()) {
80 LOG(ERROR) << __func__ << debugMessage() << " already in use";
81 return false;
82 }
83
84 if (!initSessionType(description)) return false;
85
86 auto control_result_cb = [port = this](uint16_t cookie, bool start_resp,
87 const BluetoothAudioStatus& status) {
88 (void)start_resp;
89 port->controlResultHandler(cookie, status);
90 };
91 auto session_changed_cb = [port = this](uint16_t cookie) {
92 port->sessionChangedHandler(cookie);
93 };
94 // TODO: Add audio_config_changed_cb
95 PortStatusCallbacks cbacks = {
96 .control_result_cb_ = control_result_cb,
97 .session_changed_cb_ = session_changed_cb,
98 };
99 mCookie = BluetoothAudioSessionControl::RegisterControlResultCback(mSessionType, cbacks);
100 auto isOk = (mCookie != ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined);
101 if (isOk) {
102 std::lock_guard guard(mCvMutex);
103 mState = BluetoothStreamState::STANDBY;
104 }
105 LOG(DEBUG) << __func__ << debugMessage();
106 return isOk;
107 }
108
initSessionType(const AudioDeviceDescription & description)109 bool BluetoothAudioPortAidl::initSessionType(const AudioDeviceDescription& description) {
110 if (description.connection == AudioDeviceDescription::CONNECTION_BT_A2DP &&
111 (description.type == AudioDeviceType::OUT_DEVICE ||
112 description.type == AudioDeviceType::OUT_HEADPHONE ||
113 description.type == AudioDeviceType::OUT_SPEAKER)) {
114 LOG(VERBOSE) << __func__
115 << ": device=AUDIO_DEVICE_OUT_BLUETOOTH_A2DP (HEADPHONES/SPEAKER) ("
116 << description.toString() << ")";
117 mSessionType = SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH;
118 } else if (description.connection == AudioDeviceDescription::CONNECTION_WIRELESS &&
119 description.type == AudioDeviceType::OUT_HEARING_AID) {
120 LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_HEARING_AID (MEDIA/VOICE) ("
121 << description.toString() << ")";
122 mSessionType = SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH;
123 } else if (description.connection == AudioDeviceDescription::CONNECTION_BT_LE &&
124 description.type == AudioDeviceType::OUT_HEADSET) {
125 LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLE_HEADSET (MEDIA/VOICE) ("
126 << description.toString() << ")";
127 mSessionType = SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
128 } else if (description.connection == AudioDeviceDescription::CONNECTION_BT_LE &&
129 description.type == AudioDeviceType::OUT_SPEAKER) {
130 LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLE_SPEAKER (MEDIA) ("
131 << description.toString() << ")";
132 mSessionType = SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
133 } else if (description.connection == AudioDeviceDescription::CONNECTION_BT_LE &&
134 description.type == AudioDeviceType::IN_HEADSET) {
135 LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_IN_BLE_HEADSET (VOICE) ("
136 << description.toString() << ")";
137 mSessionType = SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH;
138 } else if (description.connection == AudioDeviceDescription::CONNECTION_BT_LE &&
139 description.type == AudioDeviceType::OUT_BROADCAST) {
140 LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLE_BROADCAST (MEDIA) ("
141 << description.toString() << ")";
142 mSessionType = SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH;
143 } else {
144 LOG(ERROR) << __func__ << ": unknown device=" << description.toString();
145 return false;
146 }
147
148 if (!BluetoothAudioSessionControl::IsSessionReady(mSessionType)) {
149 LOG(ERROR) << __func__ << ": device=" << description.toString()
150 << ", session_type=" << toString(mSessionType) << " is not ready";
151 return false;
152 }
153 return true;
154 }
155
unregisterPort()156 void BluetoothAudioPortAidl::unregisterPort() {
157 if (!inUse()) {
158 LOG(WARNING) << __func__ << ": BluetoothAudioPortAidl is not in use";
159 return;
160 }
161 BluetoothAudioSessionControl::UnregisterControlResultCback(mSessionType, mCookie);
162 mCookie = ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined;
163 LOG(VERBOSE) << __func__ << debugMessage() << " port unregistered";
164 }
165
controlResultHandler(uint16_t cookie,const BluetoothAudioStatus & status)166 void BluetoothAudioPortAidl::controlResultHandler(uint16_t cookie,
167 const BluetoothAudioStatus& status) {
168 std::lock_guard guard(mCvMutex);
169 if (!inUse()) {
170 LOG(ERROR) << "control_result_cb: BluetoothAudioPortAidl is not in use";
171 return;
172 }
173 if (mCookie != cookie) {
174 LOG(ERROR) << "control_result_cb: proxy of device port (cookie="
175 << StringPrintf("%#hx", cookie) << ") is corrupted";
176 return;
177 }
178 BluetoothStreamState previous_state = mState;
179 LOG(INFO) << "control_result_cb:" << debugMessage() << ", previous_state=" << previous_state
180 << ", status=" << toString(status);
181
182 switch (previous_state) {
183 case BluetoothStreamState::STARTED:
184 /* Only Suspend signal can be send in STARTED state*/
185 if (status == BluetoothAudioStatus::RECONFIGURATION ||
186 status == BluetoothAudioStatus::SUCCESS) {
187 mState = BluetoothStreamState::STANDBY;
188 } else {
189 LOG(WARNING) << StringPrintf(
190 "control_result_cb: status=%s failure for session_type= %s, cookie=%#hx, "
191 "previous_state=%#hhx",
192 toString(status).c_str(), toString(mSessionType).c_str(), mCookie,
193 previous_state);
194 }
195 break;
196 case BluetoothStreamState::STARTING:
197 if (status == BluetoothAudioStatus::SUCCESS) {
198 mState = BluetoothStreamState::STARTED;
199 } else {
200 // Set to standby since the stack may be busy switching between outputs
201 LOG(WARNING) << StringPrintf(
202 "control_result_cb: status=%s failure for session_type= %s, cookie=%#hx, "
203 "previous_state=%#hhx",
204 toString(status).c_str(), toString(mSessionType).c_str(), mCookie,
205 previous_state);
206 mState = BluetoothStreamState::STANDBY;
207 }
208 break;
209 case BluetoothStreamState::SUSPENDING:
210 if (status == BluetoothAudioStatus::SUCCESS) {
211 mState = BluetoothStreamState::STANDBY;
212 } else {
213 // It will be failed if the headset is disconnecting, and set to disable
214 // to wait for re-init again
215 LOG(WARNING) << StringPrintf(
216 "control_result_cb: status=%s failure for session_type= %s, cookie=%#hx, "
217 "previous_state=%#hhx",
218 toString(status).c_str(), toString(mSessionType).c_str(), mCookie,
219 previous_state);
220 mState = BluetoothStreamState::DISABLED;
221 }
222 break;
223 default:
224 LOG(ERROR) << "control_result_cb: unexpected previous_state="
225 << StringPrintf(
226 "control_result_cb: status=%s failure for session_type= %s, "
227 "cookie=%#hx, previous_state=%#hhx",
228 toString(status).c_str(), toString(mSessionType).c_str(), mCookie,
229 previous_state);
230 return;
231 }
232 mInternalCv.notify_all();
233 }
234
sessionChangedHandler(uint16_t cookie)235 void BluetoothAudioPortAidl::sessionChangedHandler(uint16_t cookie) {
236 std::lock_guard guard(mCvMutex);
237 if (!inUse()) {
238 LOG(ERROR) << "session_changed_cb: BluetoothAudioPortAidl is not in use";
239 return;
240 }
241 if (mCookie != cookie) {
242 LOG(ERROR) << "session_changed_cb: proxy of device port (cookie="
243 << StringPrintf("%#hx", cookie) << ") is corrupted";
244 return;
245 }
246 BluetoothStreamState previous_state = mState;
247 LOG(VERBOSE) << "session_changed_cb:" << debugMessage()
248 << ", previous_state=" << previous_state;
249 mState = BluetoothStreamState::DISABLED;
250 mInternalCv.notify_all();
251 }
252
inUse() const253 bool BluetoothAudioPortAidl::inUse() const {
254 return (mCookie != ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined);
255 }
256
getPreferredDataIntervalUs(size_t & interval_us) const257 bool BluetoothAudioPortAidl::getPreferredDataIntervalUs(size_t& interval_us) const {
258 if (!inUse()) {
259 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
260 return false;
261 }
262
263 const AudioConfiguration& hal_audio_cfg =
264 BluetoothAudioSessionControl::GetAudioConfig(mSessionType);
265 if (hal_audio_cfg.getTag() != AudioConfiguration::pcmConfig) {
266 LOG(ERROR) << __func__ << ": unsupported audio cfg tag";
267 return false;
268 }
269
270 interval_us = hal_audio_cfg.get<AudioConfiguration::pcmConfig>().dataIntervalUs;
271 return true;
272 }
273
loadAudioConfig(PcmConfiguration & audio_cfg)274 bool BluetoothAudioPortAidl::loadAudioConfig(PcmConfiguration& audio_cfg) {
275 if (!inUse()) {
276 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
277 return false;
278 }
279
280 const AudioConfiguration& hal_audio_cfg =
281 BluetoothAudioSessionControl::GetAudioConfig(mSessionType);
282 if (hal_audio_cfg.getTag() != AudioConfiguration::pcmConfig) {
283 LOG(ERROR) << __func__ << ": unsupported audio cfg tag";
284 return false;
285 }
286 audio_cfg = hal_audio_cfg.get<AudioConfiguration::pcmConfig>();
287 LOG(VERBOSE) << __func__ << debugMessage() << ", state*=" << getState() << ", PcmConfig=["
288 << audio_cfg.toString() << "]";
289 if (audio_cfg.channelMode == ChannelMode::UNKNOWN) {
290 return false;
291 }
292 return true;
293 }
294
loadAudioConfig(PcmConfiguration & audio_cfg)295 bool BluetoothAudioPortAidlOut::loadAudioConfig(PcmConfiguration& audio_cfg) {
296 if (!BluetoothAudioPortAidl::loadAudioConfig(audio_cfg)) return false;
297 // WAR to support Mono / 16 bits per sample as the Bluetooth stack requires
298 if (audio_cfg.channelMode == ChannelMode::MONO && audio_cfg.bitsPerSample == 16) {
299 mIsStereoToMono = true;
300 audio_cfg.channelMode = ChannelMode::STEREO;
301 LOG(INFO) << __func__ << ": force channels = to be AUDIO_CHANNEL_OUT_STEREO";
302 }
303 return true;
304 }
305
standby()306 bool BluetoothAudioPortAidl::standby() {
307 if (!inUse()) {
308 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
309 return false;
310 }
311 std::lock_guard guard(mCvMutex);
312 LOG(VERBOSE) << __func__ << debugMessage() << ", state=" << getState() << " request";
313 if (mState == BluetoothStreamState::DISABLED) {
314 mState = BluetoothStreamState::STANDBY;
315 LOG(VERBOSE) << __func__ << debugMessage() << ", state=" << getState() << " done";
316 return true;
317 }
318 return false;
319 }
320
condWaitState(BluetoothStreamState state)321 bool BluetoothAudioPortAidl::condWaitState(BluetoothStreamState state) {
322 const auto waitTime = std::chrono::milliseconds(kMaxWaitingTimeMs);
323 std::unique_lock lock(mCvMutex);
324 base::ScopedLockAssertion lock_assertion(mCvMutex);
325 switch (state) {
326 case BluetoothStreamState::STARTING: {
327 LOG(VERBOSE) << __func__ << debugMessage() << " waiting for STARTED";
328 mInternalCv.wait_for(lock, waitTime, [this] {
329 base::ScopedLockAssertion lock_assertion(mCvMutex);
330 return mState != BluetoothStreamState::STARTING;
331 });
332 return mState == BluetoothStreamState::STARTED;
333 }
334 case BluetoothStreamState::SUSPENDING: {
335 LOG(VERBOSE) << __func__ << debugMessage() << " waiting for SUSPENDED";
336 mInternalCv.wait_for(lock, waitTime, [this] {
337 base::ScopedLockAssertion lock_assertion(mCvMutex);
338 return mState != BluetoothStreamState::SUSPENDING;
339 });
340 return mState == BluetoothStreamState::STANDBY;
341 }
342 default:
343 LOG(WARNING) << __func__ << debugMessage() << " waiting for KNOWN";
344 return false;
345 }
346 return false;
347 }
348
start()349 bool BluetoothAudioPortAidl::start() {
350 if (!inUse()) {
351 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
352 return false;
353 }
354 LOG(VERBOSE) << __func__ << debugMessage() << ", state=" << getState()
355 << ", mono=" << (mIsStereoToMono ? "true" : "false") << " request";
356
357 {
358 std::unique_lock lock(mCvMutex);
359 base::ScopedLockAssertion lock_assertion(mCvMutex);
360 if (mState == BluetoothStreamState::STARTED) {
361 return true; // nop, return
362 } else if (mState == BluetoothStreamState::SUSPENDING ||
363 mState == BluetoothStreamState::STARTING) {
364 /* If port is in transient state, give some time to respond */
365 auto state_ = mState;
366 lock.unlock();
367 if (!condWaitState(state_)) {
368 LOG(ERROR) << __func__ << debugMessage() << ", state=" << getState() << " failure";
369 return false;
370 }
371 }
372 }
373
374 bool retval = false;
375 {
376 std::unique_lock lock(mCvMutex);
377 base::ScopedLockAssertion lock_assertion(mCvMutex);
378 if (mState == BluetoothStreamState::STARTED) {
379 retval = true;
380 } else if (mState == BluetoothStreamState::STANDBY) {
381 mState = BluetoothStreamState::STARTING;
382 lock.unlock();
383 if (BluetoothAudioSessionControl::StartStream(mSessionType)) {
384 retval = condWaitState(BluetoothStreamState::STARTING);
385 } else {
386 LOG(ERROR) << __func__ << debugMessage() << ", state=" << getState()
387 << " Hal fails";
388 }
389 }
390 }
391
392 if (retval) {
393 LOG(INFO) << __func__ << debugMessage() << ", state=" << getState()
394 << ", mono=" << (mIsStereoToMono ? "true" : "false") << " done";
395 } else {
396 LOG(ERROR) << __func__ << debugMessage() << ", state=" << getState() << " failure";
397 }
398
399 return retval; // false if any failure like timeout
400 }
401
suspend()402 bool BluetoothAudioPortAidl::suspend() {
403 if (!inUse()) {
404 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
405 return false;
406 }
407 LOG(VERBOSE) << __func__ << debugMessage() << ", state=" << getState() << " request";
408
409 {
410 std::unique_lock lock(mCvMutex);
411 base::ScopedLockAssertion lock_assertion(mCvMutex);
412 if (mState == BluetoothStreamState::STANDBY) {
413 return true; // nop, return
414 } else if (mState == BluetoothStreamState::SUSPENDING ||
415 mState == BluetoothStreamState::STARTING) {
416 /* If port is in transient state, give some time to respond */
417 auto state_ = mState;
418 lock.unlock();
419 if (!condWaitState(state_)) {
420 LOG(ERROR) << __func__ << debugMessage() << ", state=" << getState() << " failure";
421 return false;
422 }
423 }
424 }
425
426 bool retval = false;
427 {
428 std::unique_lock lock(mCvMutex);
429 base::ScopedLockAssertion lock_assertion(mCvMutex);
430 if (mState == BluetoothStreamState::STANDBY) {
431 retval = true;
432 } else if (mState == BluetoothStreamState::STARTED) {
433 mState = BluetoothStreamState::SUSPENDING;
434 lock.unlock();
435 if (BluetoothAudioSessionControl::SuspendStream(mSessionType)) {
436 retval = condWaitState(BluetoothStreamState::SUSPENDING);
437 } else {
438 LOG(ERROR) << __func__ << debugMessage() << ", state=" << getState()
439 << " failure to suspend stream";
440 }
441 }
442 }
443
444 if (retval) {
445 LOG(INFO) << __func__ << debugMessage() << ", state=" << getState() << " done";
446 } else {
447 LOG(ERROR) << __func__ << debugMessage() << ", state=" << getState() << " failure";
448 }
449
450 return retval; // false if any failure like timeout
451 }
452
stop()453 void BluetoothAudioPortAidl::stop() {
454 if (!inUse()) {
455 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
456 return;
457 }
458 std::lock_guard guard(mCvMutex);
459 LOG(VERBOSE) << __func__ << debugMessage() << ", state=" << getState() << " request";
460 if (mState != BluetoothStreamState::DISABLED) {
461 BluetoothAudioSessionControl::StopStream(mSessionType);
462 mState = BluetoothStreamState::DISABLED;
463 }
464 LOG(VERBOSE) << __func__ << debugMessage() << ", state=" << getState() << " done";
465 }
466
writeData(const void * buffer,size_t bytes) const467 size_t BluetoothAudioPortAidlOut::writeData(const void* buffer, size_t bytes) const {
468 if (!buffer) {
469 LOG(ERROR) << __func__ << ": bad input arg";
470 return 0;
471 }
472
473 if (!inUse()) {
474 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
475 return 0;
476 }
477
478 if (!mIsStereoToMono) {
479 return BluetoothAudioSessionControl::OutWritePcmData(mSessionType, buffer, bytes);
480 }
481
482 // WAR to mix the stereo into Mono (16 bits per sample)
483 const size_t write_frames = bytes >> 2;
484 if (write_frames == 0) return 0;
485 auto src = static_cast<const int16_t*>(buffer);
486 std::unique_ptr<int16_t[]> dst{new int16_t[write_frames]};
487 downmix_to_mono_i16_from_stereo_i16(dst.get(), src, write_frames);
488 // a frame is 16 bits, and the size of a mono frame is equal to half a stereo.
489 auto totalWrite = BluetoothAudioSessionControl::OutWritePcmData(mSessionType, dst.get(),
490 write_frames * 2);
491 return totalWrite * 2;
492 }
493
readData(void * buffer,size_t bytes) const494 size_t BluetoothAudioPortAidlIn::readData(void* buffer, size_t bytes) const {
495 if (!buffer) {
496 LOG(ERROR) << __func__ << ": bad input arg";
497 return 0;
498 }
499
500 if (!inUse()) {
501 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
502 return 0;
503 }
504
505 return BluetoothAudioSessionControl::InReadPcmData(mSessionType, buffer, bytes);
506 }
507
getPresentationPosition(PresentationPosition & presentation_position) const508 bool BluetoothAudioPortAidl::getPresentationPosition(
509 PresentationPosition& presentation_position) const {
510 if (!inUse()) {
511 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
512 return false;
513 }
514 bool retval = BluetoothAudioSessionControl::GetPresentationPosition(mSessionType,
515 presentation_position);
516 LOG(VERBOSE) << __func__ << debugMessage() << ", state=" << getState()
517 << presentation_position.toString();
518
519 return retval;
520 }
521
updateSourceMetadata(const SourceMetadata & source_metadata) const522 bool BluetoothAudioPortAidl::updateSourceMetadata(const SourceMetadata& source_metadata) const {
523 if (!inUse()) {
524 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
525 return false;
526 }
527 LOG(DEBUG) << __func__ << debugMessage() << ", state=" << getState() << ", "
528 << source_metadata.tracks.size() << " track(s)";
529 if (source_metadata.tracks.size() == 0) return true;
530 return BluetoothAudioSessionControl::UpdateSourceMetadata(mSessionType, source_metadata);
531 }
532
updateSinkMetadata(const SinkMetadata & sink_metadata) const533 bool BluetoothAudioPortAidl::updateSinkMetadata(const SinkMetadata& sink_metadata) const {
534 if (!inUse()) {
535 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
536 return false;
537 }
538 LOG(DEBUG) << __func__ << debugMessage() << ", state=" << getState() << ", "
539 << sink_metadata.tracks.size() << " track(s)";
540 if (sink_metadata.tracks.size() == 0) return true;
541 return BluetoothAudioSessionControl::UpdateSinkMetadata(mSessionType, sink_metadata);
542 }
543
getState() const544 BluetoothStreamState BluetoothAudioPortAidl::getState() const {
545 return mState;
546 }
547
setState(BluetoothStreamState state)548 bool BluetoothAudioPortAidl::setState(BluetoothStreamState state) {
549 if (!inUse()) {
550 LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
551 return false;
552 }
553 std::lock_guard guard(mCvMutex);
554 LOG(DEBUG) << __func__ << ": BluetoothAudioPortAidl old state = " << mState
555 << " new state = " << state;
556 mState = state;
557 return true;
558 }
559
isA2dp() const560 bool BluetoothAudioPortAidl::isA2dp() const {
561 return mSessionType == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
562 mSessionType == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
563 }
564
isLeAudio() const565 bool BluetoothAudioPortAidl::isLeAudio() const {
566 return mSessionType == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH ||
567 mSessionType == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH ||
568 mSessionType == SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
569 mSessionType == SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
570 mSessionType == SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH ||
571 mSessionType == SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
572 }
573
debugMessage() const574 std::string BluetoothAudioPortAidl::debugMessage() const {
575 return StringPrintf(": session_type=%s, cookie=%#hx", toString(mSessionType).c_str(), mCookie);
576 }
577
578 } // namespace android::bluetooth::audio::aidl
579