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