1 /*
2  * Copyright 2019 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 "BTAudioHalDeviceProxy"
18 
19 #include <android-base/logging.h>
20 #include <android-base/stringprintf.h>
21 #include <audio_utils/primitives.h>
22 #include <inttypes.h>
23 #include <log/log.h>
24 #include <stdlib.h>
25 
26 #include "BluetoothAudioSessionControl_2_1.h"
27 #include "device_port_proxy.h"
28 #include "stream_apis.h"
29 #include "utils.h"
30 
31 namespace android {
32 namespace bluetooth {
33 namespace audio {
34 
35 using ::android::base::StringPrintf;
36 using ::android::bluetooth::audio::BluetoothAudioSessionControl_2_1;
37 using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
38 using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
39 using ::android::hardware::bluetooth::audio::V2_0::PcmParameters;
40 using SampleRate = ::android::hardware::bluetooth::audio::V2_0::SampleRate;
41 using SampleRate_2_1 = ::android::hardware::bluetooth::audio::V2_1::SampleRate;
42 using BluetoothAudioStatus =
43     ::android::hardware::bluetooth::audio::V2_0::Status;
44 using ControlResultCallback = std::function<void(
45     uint16_t cookie, bool start_resp, const BluetoothAudioStatus& status)>;
46 using SessionChangedCallback = std::function<void(uint16_t cookie)>;
47 
48 namespace {
49 
SampleRateToAudioFormat(SampleRate_2_1 sample_rate)50 unsigned int SampleRateToAudioFormat(SampleRate_2_1 sample_rate) {
51   switch (sample_rate) {
52     case SampleRate_2_1::RATE_8000:
53       return 8000;
54     case SampleRate_2_1::RATE_16000:
55       return 16000;
56     case SampleRate_2_1::RATE_24000:
57       return 24000;
58     case SampleRate_2_1::RATE_32000:
59       return 32000;
60     case SampleRate_2_1::RATE_44100:
61       return 44100;
62     case SampleRate_2_1::RATE_48000:
63       return 48000;
64     case SampleRate_2_1::RATE_88200:
65       return 88200;
66     case SampleRate_2_1::RATE_96000:
67       return 96000;
68     case SampleRate_2_1::RATE_176400:
69       return 176400;
70     case SampleRate_2_1::RATE_192000:
71       return 192000;
72     default:
73       return kBluetoothDefaultSampleRate;
74   }
75 }
OutputChannelModeToAudioFormat(ChannelMode channel_mode)76 audio_channel_mask_t OutputChannelModeToAudioFormat(ChannelMode channel_mode) {
77   switch (channel_mode) {
78     case ChannelMode::MONO:
79       return AUDIO_CHANNEL_OUT_MONO;
80     case ChannelMode::STEREO:
81       return AUDIO_CHANNEL_OUT_STEREO;
82     default:
83       return kBluetoothDefaultOutputChannelModeMask;
84   }
85 }
86 
InputChannelModeToAudioFormat(ChannelMode channel_mode)87 audio_channel_mask_t InputChannelModeToAudioFormat(ChannelMode channel_mode) {
88   switch (channel_mode) {
89     case ChannelMode::MONO:
90       return AUDIO_CHANNEL_IN_MONO;
91     case ChannelMode::STEREO:
92       return AUDIO_CHANNEL_IN_STEREO;
93     default:
94       return kBluetoothDefaultInputChannelModeMask;
95   }
96 }
97 
BitsPerSampleToAudioFormat(BitsPerSample bits_per_sample)98 audio_format_t BitsPerSampleToAudioFormat(BitsPerSample bits_per_sample) {
99   switch (bits_per_sample) {
100     case BitsPerSample::BITS_16:
101       return AUDIO_FORMAT_PCM_16_BIT;
102     case BitsPerSample::BITS_24:
103       return AUDIO_FORMAT_PCM_24_BIT_PACKED;
104     case BitsPerSample::BITS_32:
105       return AUDIO_FORMAT_PCM_32_BIT;
106     default:
107       return kBluetoothDefaultAudioFormatBitsPerSample;
108   }
109 }
110 
111 // The maximum time to wait in std::condition_variable::wait_for()
112 constexpr unsigned int kMaxWaitingTimeMs = 4500;
113 
114 }  // namespace
115 
BluetoothAudioPort()116 BluetoothAudioPort::BluetoothAudioPort()
117     : cookie_(android::bluetooth::audio::kObserversCookieUndefined),
118       state_(BluetoothStreamState::DISABLED),
119       session_type_(SessionType_2_1::UNKNOWN) {}
120 
SetUp(audio_devices_t devices)121 bool BluetoothAudioPort::SetUp(audio_devices_t devices) {
122   if (!init_session_type(devices)) return false;
123 
124   state_ = BluetoothStreamState::STANDBY;
125 
126   auto control_result_cb = [port = this](uint16_t cookie, bool start_resp,
127                                          const BluetoothAudioStatus& status) {
128     if (!port->in_use()) {
129       LOG(ERROR) << "control_result_cb: BluetoothAudioPort is not in use";
130       return;
131     }
132     if (port->cookie_ != cookie) {
133       LOG(ERROR) << "control_result_cb: proxy of device port (cookie=" << StringPrintf("%#hx", cookie)
134                  << ") is corrupted";
135       return;
136     }
137     port->ControlResultHandler(status);
138   };
139   auto session_changed_cb = [port = this](uint16_t cookie) {
140     if (!port->in_use()) {
141       LOG(ERROR) << "session_changed_cb: BluetoothAudioPort is not in use";
142       return;
143     }
144     if (port->cookie_ != cookie) {
145       LOG(ERROR) << "session_changed_cb: proxy of device port (cookie=" << StringPrintf("%#hx", cookie)
146                  << ") is corrupted";
147       return;
148     }
149     port->SessionChangedHandler();
150   };
151   ::android::bluetooth::audio::PortStatusCallbacks cbacks = {
152       .control_result_cb_ = control_result_cb,
153       .session_changed_cb_ = session_changed_cb};
154   cookie_ = BluetoothAudioSessionControl_2_1::RegisterControlResultCback(
155       session_type_, cbacks);
156   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_);
157 
158   return (cookie_ != android::bluetooth::audio::kObserversCookieUndefined);
159 }
160 
init_session_type(audio_devices_t device)161 bool BluetoothAudioPort::init_session_type(audio_devices_t device) {
162   switch (device) {
163     case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
164     case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
165     case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
166       LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLUETOOTH_A2DP (HEADPHONES/SPEAKER) ("
167                    << StringPrintf("%#x", device) << ")";
168       session_type_ = SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH;
169       break;
170     case AUDIO_DEVICE_OUT_HEARING_AID:
171       LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_HEARING_AID (MEDIA/VOICE) (" << StringPrintf("%#x", device)
172                    << ")";
173       session_type_ = SessionType_2_1::HEARING_AID_SOFTWARE_ENCODING_DATAPATH;
174       break;
175     case AUDIO_DEVICE_OUT_BLE_HEADSET:
176       LOG(VERBOSE) << __func__
177                    << ": device=AUDIO_DEVICE_OUT_BLE_HEADSET (MEDIA/VOICE) ("
178                    << StringPrintf("%#x", device) << ")";
179       session_type_ = SessionType_2_1::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
180       break;
181     case AUDIO_DEVICE_OUT_BLE_SPEAKER:
182       LOG(VERBOSE) << __func__
183                    << ": device=AUDIO_DEVICE_OUT_BLE_SPEAKER (MEDIA) ("
184                    << StringPrintf("%#x", device) << ")";
185       session_type_ = SessionType_2_1::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
186       break;
187     case AUDIO_DEVICE_IN_BLE_HEADSET:
188       LOG(VERBOSE) << __func__
189                    << ": device=AUDIO_DEVICE_IN_BLE_HEADSET (VOICE) ("
190                    << StringPrintf("%#x", device) << ")";
191       session_type_ = SessionType_2_1::LE_AUDIO_SOFTWARE_DECODED_DATAPATH;
192       break;
193     default:
194       LOG(ERROR) << __func__ << ": unknown device=" << StringPrintf("%#x", device);
195       return false;
196   }
197 
198   if (!BluetoothAudioSessionControl_2_1::IsSessionReady(session_type_)) {
199     LOG(ERROR) << __func__ << ": device=" << StringPrintf("%#x", device) << ", session_type=" << toString(session_type_)
200                << " is not ready";
201     return false;
202   }
203   return true;
204 }
205 
TearDown()206 void BluetoothAudioPort::TearDown() {
207   if (!in_use()) {
208     LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
209                << ", cookie=" << StringPrintf("%#hx", cookie_) << " unknown monitor";
210     return;
211   }
212 
213   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_);
214   BluetoothAudioSessionControl_2_1::UnregisterControlResultCback(session_type_,
215                                                                  cookie_);
216   cookie_ = android::bluetooth::audio::kObserversCookieUndefined;
217 }
218 
ControlResultHandler(const BluetoothAudioStatus & status)219 void BluetoothAudioPort::ControlResultHandler(
220     const BluetoothAudioStatus& status) {
221   if (!in_use()) {
222     LOG(ERROR) << __func__ << ": BluetoothAudioPortis not in use";
223     return;
224   }
225   std::unique_lock<std::mutex> port_lock(cv_mutex_);
226   BluetoothStreamState previous_state = state_;
227   LOG(INFO) << "control_result_cb: session_type=" << toString(session_type_)
228             << ", cookie=" << StringPrintf("%#hx", cookie_) << ", previous_state=" << previous_state
229             << ", status=" << toString(status);
230 
231   switch (previous_state) {
232     case BluetoothStreamState::STARTING:
233       if (status == BluetoothAudioStatus::SUCCESS) {
234         state_ = BluetoothStreamState::STARTED;
235       } else {
236         // Set to standby since the stack may be busy switching between outputs
237         LOG(WARNING) << "control_result_cb: status=" << toString(status)
238                      << " failure for session_type=" << toString(session_type_)
239                      << ", cookie=" << StringPrintf("%#hx", cookie_) << ", previous_state=" << previous_state;
240         state_ = BluetoothStreamState::STANDBY;
241       }
242       break;
243     case BluetoothStreamState::SUSPENDING:
244       if (status == BluetoothAudioStatus::SUCCESS) {
245         state_ = BluetoothStreamState::STANDBY;
246       } else {
247         // It will be failed if the headset is disconnecting, and set to disable
248         // to wait for re-init again
249         LOG(WARNING) << "control_result_cb: status=" << toString(status)
250                      << " failure for session_type=" << toString(session_type_)
251                      << ", cookie=" << StringPrintf("%#hx", cookie_) << ", previous_state=" << previous_state;
252         state_ = BluetoothStreamState::DISABLED;
253       }
254       break;
255     default:
256       LOG(ERROR) << "control_result_cb: unexpected status=" << toString(status)
257                  << " for session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_)
258                  << ", previous_state=" << previous_state;
259       return;
260   }
261   port_lock.unlock();
262   internal_cv_.notify_all();
263 }
264 
SessionChangedHandler()265 void BluetoothAudioPort::SessionChangedHandler() {
266   if (!in_use()) {
267     LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use";
268     return;
269   }
270   std::unique_lock<std::mutex> port_lock(cv_mutex_);
271   BluetoothStreamState previous_state = state_;
272   LOG(INFO) << "session_changed_cb: session_type=" << toString(session_type_)
273             << ", cookie=" << StringPrintf("%#hx", cookie_) << ", previous_state=" << previous_state;
274   if (previous_state != BluetoothStreamState::DISABLED) {
275     state_ = BluetoothStreamState::DISABLED;
276   } else {
277     state_ = BluetoothStreamState::STANDBY;
278   }
279   port_lock.unlock();
280   internal_cv_.notify_all();
281 }
282 
in_use() const283 bool BluetoothAudioPort::in_use() const {
284   return (cookie_ != android::bluetooth::audio::kObserversCookieUndefined);
285 }
286 
LoadAudioConfig(audio_config_t * audio_cfg) const287 bool BluetoothAudioPortOut::LoadAudioConfig(audio_config_t* audio_cfg) const {
288   if (!in_use()) {
289     LOG(ERROR) << __func__ << ": BluetoothAudioPortOut is not in use";
290     audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
291     audio_cfg->channel_mask = kBluetoothDefaultOutputChannelModeMask;
292     audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
293     return false;
294   }
295 
296   const ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration&
297       hal_audio_cfg =
298           BluetoothAudioSessionControl_2_1::GetAudioConfig(session_type_);
299   if (hal_audio_cfg.getDiscriminator() !=
300       ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration::
301           hidl_discriminator::pcmConfig) {
302     audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
303     audio_cfg->channel_mask = kBluetoothDefaultOutputChannelModeMask;
304     audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
305     return false;
306   }
307   const ::android::hardware::bluetooth::audio::V2_1::PcmParameters& pcm_cfg =
308       hal_audio_cfg.pcmConfig();
309   LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
310                << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << ", PcmConfig=["
311                << toString(pcm_cfg) << "]";
312   if (pcm_cfg.sampleRate == SampleRate_2_1::RATE_UNKNOWN ||
313       pcm_cfg.channelMode == ChannelMode::UNKNOWN ||
314       pcm_cfg.bitsPerSample == BitsPerSample::BITS_UNKNOWN) {
315     return false;
316   }
317   audio_cfg->sample_rate = SampleRateToAudioFormat(pcm_cfg.sampleRate);
318   audio_cfg->channel_mask =
319       (is_stereo_to_mono_
320            ? AUDIO_CHANNEL_OUT_STEREO
321            : OutputChannelModeToAudioFormat(pcm_cfg.channelMode));
322   audio_cfg->format = BitsPerSampleToAudioFormat(pcm_cfg.bitsPerSample);
323   return true;
324 }
325 
LoadAudioConfig(audio_config_t * audio_cfg) const326 bool BluetoothAudioPortIn::LoadAudioConfig(audio_config_t* audio_cfg) const {
327   if (!in_use()) {
328     LOG(ERROR) << __func__ << ": BluetoothAudioPortIn is not in use";
329     audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
330     audio_cfg->channel_mask = kBluetoothDefaultInputChannelModeMask;
331     audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
332     return false;
333   }
334 
335   const ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration&
336       hal_audio_cfg =
337           BluetoothAudioSessionControl_2_1::GetAudioConfig(session_type_);
338   if (hal_audio_cfg.getDiscriminator() !=
339       ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration::
340           hidl_discriminator::pcmConfig) {
341     audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
342     audio_cfg->channel_mask = kBluetoothDefaultInputChannelModeMask;
343     audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
344     return false;
345   }
346   const ::android::hardware::bluetooth::audio::V2_1::PcmParameters& pcm_cfg =
347       hal_audio_cfg.pcmConfig();
348   LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
349                << ", cookie=" << StringPrintf("%#hx", cookie_)
350                << ", state=" << state_ << ", PcmConfig=[" << toString(pcm_cfg)
351                << "]";
352   if (pcm_cfg.sampleRate == SampleRate_2_1::RATE_UNKNOWN ||
353       pcm_cfg.channelMode == ChannelMode::UNKNOWN ||
354       pcm_cfg.bitsPerSample == BitsPerSample::BITS_UNKNOWN) {
355     return false;
356   }
357 
358   audio_cfg->sample_rate = SampleRateToAudioFormat(pcm_cfg.sampleRate);
359   audio_cfg->channel_mask = InputChannelModeToAudioFormat(pcm_cfg.channelMode);
360   audio_cfg->format = BitsPerSampleToAudioFormat(pcm_cfg.bitsPerSample);
361   return true;
362 }
363 
CondwaitState(BluetoothStreamState state)364 bool BluetoothAudioPort::CondwaitState(BluetoothStreamState state) {
365   bool retval;
366   std::unique_lock<std::mutex> port_lock(cv_mutex_);
367   switch (state) {
368     case BluetoothStreamState::STARTING:
369       LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
370                    << ", cookie=" << StringPrintf("%#hx", cookie_) << " waiting for STARTED";
371       retval = internal_cv_.wait_for(
372           port_lock, std::chrono::milliseconds(kMaxWaitingTimeMs),
373           [this] { return this->state_ != BluetoothStreamState::STARTING; });
374       retval = retval && state_ == BluetoothStreamState::STARTED;
375       break;
376     case BluetoothStreamState::SUSPENDING:
377       LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
378                    << ", cookie=" << StringPrintf("%#hx", cookie_) << " waiting for SUSPENDED";
379       retval = internal_cv_.wait_for(
380           port_lock, std::chrono::milliseconds(kMaxWaitingTimeMs),
381           [this] { return this->state_ != BluetoothStreamState::SUSPENDING; });
382       retval = retval && state_ == BluetoothStreamState::STANDBY;
383       break;
384     default:
385       LOG(WARNING) << __func__ << ": session_type=" << toString(session_type_)
386                    << ", cookie=" << StringPrintf("%#hx", cookie_) << " waiting for KNOWN";
387       return false;
388   }
389 
390   return retval;  // false if any failure like timeout
391 }
392 
Start()393 bool BluetoothAudioPort::Start() {
394   if (!in_use()) {
395     LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use";
396     return false;
397   }
398 
399   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_)
400             << ", state=" << state_ << ", mono=" << (is_stereo_to_mono_ ? "true" : "false") << " request";
401   bool retval = false;
402   if (state_ == BluetoothStreamState::STANDBY) {
403     state_ = BluetoothStreamState::STARTING;
404     if (BluetoothAudioSessionControl_2_1::StartStream(session_type_)) {
405       retval = CondwaitState(BluetoothStreamState::STARTING);
406     } else {
407       LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
408                  << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " Hal fails";
409     }
410   }
411 
412   if (retval) {
413     LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
414               << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
415               << ", mono=" << (is_stereo_to_mono_ ? "true" : "false") << " done";
416   } else {
417     LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
418                << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " failure";
419   }
420 
421   return retval;  // false if any failure like timeout
422 }
423 
Suspend()424 bool BluetoothAudioPort::Suspend() {
425   if (!in_use()) {
426     LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use";
427     return false;
428   }
429 
430   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_)
431             << ", state=" << state_ << " request";
432   bool retval = false;
433   if (state_ == BluetoothStreamState::STARTED) {
434     state_ = BluetoothStreamState::SUSPENDING;
435     if (BluetoothAudioSessionControl_2_1::SuspendStream(session_type_)) {
436       retval = CondwaitState(BluetoothStreamState::SUSPENDING);
437     } else {
438       LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
439                  << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " Hal fails";
440     }
441   }
442 
443   if (retval) {
444     LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
445               << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " done";
446   } else {
447     LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
448                << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " failure";
449   }
450 
451   return retval;  // false if any failure like timeout
452 }
453 
Stop()454 void BluetoothAudioPort::Stop() {
455   if (!in_use()) {
456     LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use";
457     return;
458   }
459   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_)
460             << ", state=" << state_ << " request";
461   state_ = BluetoothStreamState::DISABLED;
462   BluetoothAudioSessionControl_2_1::StopStream(session_type_);
463   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_)
464             << ", state=" << state_ << " done";
465 }
466 
WriteData(const void * buffer,size_t bytes) const467 size_t BluetoothAudioPortOut::WriteData(const void* buffer, size_t bytes) const {
468   if (!in_use()) return 0;
469   if (!is_stereo_to_mono_) {
470     return BluetoothAudioSessionControl_2_1::OutWritePcmData(session_type_,
471                                                              buffer, bytes);
472   }
473 
474   // WAR to mix the stereo into Mono (16 bits per sample)
475   const size_t write_frames = bytes >> 2;
476   if (write_frames == 0) return 0;
477   auto src = static_cast<const int16_t*>(buffer);
478   std::unique_ptr<int16_t[]> dst{new int16_t[write_frames]};
479   downmix_to_mono_i16_from_stereo_i16(dst.get(), src, write_frames);
480   // a frame is 16 bits, and the size of a mono frame is equal to half a stereo.
481   return BluetoothAudioSessionControl_2_1::OutWritePcmData(
482              session_type_, dst.get(), write_frames * 2) *
483          2;
484 }
485 
ReadData(void * buffer,size_t bytes) const486 size_t BluetoothAudioPortIn::ReadData(void* buffer, size_t bytes) const {
487   if (!in_use()) return 0;
488   return BluetoothAudioSessionControl_2_1::InReadPcmData(session_type_, buffer,
489                                                          bytes);
490 }
491 
GetPresentationPosition(uint64_t * delay_ns,uint64_t * bytes,timespec * timestamp) const492 bool BluetoothAudioPort::GetPresentationPosition(uint64_t* delay_ns,
493                                                  uint64_t* bytes,
494                                                  timespec* timestamp) const {
495   if (!in_use()) {
496     LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use";
497     return false;
498   }
499   bool retval = BluetoothAudioSessionControl_2_1::GetPresentationPosition(
500       session_type_, delay_ns, bytes, timestamp);
501   LOG(VERBOSE) << __func__ << ": session_type=" << StringPrintf("%#hhx", session_type_)
502                << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << ", delay=" << *delay_ns
503                << "ns, data=" << *bytes << " bytes, timestamp=" << timestamp->tv_sec << "."
504                << StringPrintf("%09ld", timestamp->tv_nsec) << "s";
505 
506   return retval;
507 }
508 
UpdateMetadata(const source_metadata * source_metadata) const509 void BluetoothAudioPort::UpdateMetadata(
510     const source_metadata* source_metadata) const {
511   if (!in_use()) {
512     LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use";
513     return;
514   }
515   LOG(DEBUG) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_)
516              << ", state=" << state_ << ", " << source_metadata->track_count << " track(s)";
517   if (source_metadata->track_count == 0) return;
518   BluetoothAudioSessionControl_2_1::UpdateTracksMetadata(session_type_,
519                                                          source_metadata);
520 }
521 
GetState() const522 BluetoothStreamState BluetoothAudioPort::GetState() const { return state_; }
523 
SetState(BluetoothStreamState state)524 void BluetoothAudioPort::SetState(BluetoothStreamState state) {
525   state_ = state;
526 }
527 
528 }  // namespace audio
529 }  // namespace bluetooth
530 }  // namespace android
531