• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 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 #define LOG_TAG "BTAudioHalDeviceProxyAIDL"
18 
19 #include "device_port_proxy.h"
20 
21 #include <android-base/logging.h>
22 #include <android-base/stringprintf.h>
23 #include <audio_utils/primitives.h>
24 #include <inttypes.h>
25 #include <log/log.h>
26 #include <stdlib.h>
27 
28 #include "BluetoothAudioSessionControl.h"
29 #include "stream_apis.h"
30 #include "utils.h"
31 
32 namespace android {
33 namespace bluetooth {
34 namespace audio {
35 namespace aidl {
36 
37 using ::aidl::android::hardware::bluetooth::audio::AudioConfiguration;
38 using ::aidl::android::hardware::bluetooth::audio::BluetoothAudioSessionControl;
39 using ::aidl::android::hardware::bluetooth::audio::ChannelMode;
40 using ::aidl::android::hardware::bluetooth::audio::PcmConfiguration;
41 using ::aidl::android::hardware::bluetooth::audio::PortStatusCallbacks;
42 using ::aidl::android::hardware::bluetooth::audio::PresentationPosition;
43 
44 using ::android::base::StringPrintf;
45 using ControlResultCallback = std::function<void(
46     uint16_t cookie, bool start_resp, const BluetoothAudioStatus& status)>;
47 using SessionChangedCallback = std::function<void(uint16_t cookie)>;
48 
49 namespace {
50 
OutputChannelModeToAudioFormat(ChannelMode channel_mode)51 audio_channel_mask_t OutputChannelModeToAudioFormat(ChannelMode channel_mode) {
52   switch (channel_mode) {
53     case ChannelMode::MONO:
54       return AUDIO_CHANNEL_OUT_MONO;
55     case ChannelMode::STEREO:
56       return AUDIO_CHANNEL_OUT_STEREO;
57     default:
58       return kBluetoothDefaultOutputChannelModeMask;
59   }
60 }
61 
InputChannelModeToAudioFormat(ChannelMode channel_mode)62 audio_channel_mask_t InputChannelModeToAudioFormat(ChannelMode channel_mode) {
63   switch (channel_mode) {
64     case ChannelMode::MONO:
65       return AUDIO_CHANNEL_IN_MONO;
66     case ChannelMode::STEREO:
67       return AUDIO_CHANNEL_IN_STEREO;
68     default:
69       return kBluetoothDefaultInputChannelModeMask;
70   }
71 }
72 
BitsPerSampleToAudioFormat(uint8_t bits_per_sample,const SessionType & session_type)73 audio_format_t BitsPerSampleToAudioFormat(uint8_t bits_per_sample,
74                                           const SessionType& session_type) {
75   switch (bits_per_sample) {
76     case 16:
77       return AUDIO_FORMAT_PCM_16_BIT;
78     case 24:
79       /* Now we use knowledge that Classic sessions used packed, and LE Audio
80        * LC3 encoder uses unpacked as input. This should be passed as parameter
81        * from BT stack through AIDL, but it would require new interface version,
82        * so sticking with this workaround for now. */
83       if (session_type ==
84               SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
85           session_type == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH) {
86         return AUDIO_FORMAT_PCM_24_BIT_PACKED;
87       } else {
88         return AUDIO_FORMAT_PCM_8_24_BIT;
89       }
90     case 32:
91       return AUDIO_FORMAT_PCM_32_BIT;
92     default:
93       return kBluetoothDefaultAudioFormatBitsPerSample;
94   }
95 }
96 
97 // The maximum time to wait in std::condition_variable::wait_for()
98 constexpr unsigned int kMaxWaitingTimeMs = 4500;
99 
100 }  // namespace
101 
BluetoothAudioPortAidl()102 BluetoothAudioPortAidl::BluetoothAudioPortAidl()
103     : cookie_(::aidl::android::hardware::bluetooth::audio::
104                   kObserversCookieUndefined),
105       state_(BluetoothStreamState::DISABLED),
106       session_type_(SessionType::UNKNOWN) {}
107 
~BluetoothAudioPortAidlOut()108 BluetoothAudioPortAidlOut::~BluetoothAudioPortAidlOut() {
109   if (in_use()) TearDown();
110 }
111 
~BluetoothAudioPortAidlIn()112 BluetoothAudioPortAidlIn::~BluetoothAudioPortAidlIn() {
113   if (in_use()) TearDown();
114 }
115 
SetUp(audio_devices_t devices)116 bool BluetoothAudioPortAidl::SetUp(audio_devices_t devices) {
117   if (!init_session_type(devices)) return false;
118 
119   state_ = BluetoothStreamState::STANDBY;
120 
121   auto control_result_cb = [port = this](uint16_t cookie, bool start_resp,
122                                          const BluetoothAudioStatus& status) {
123     if (!port->in_use()) {
124       LOG(ERROR) << "control_result_cb: BluetoothAudioPortAidl is not in use";
125       return;
126     }
127     if (port->cookie_ != cookie) {
128       LOG(ERROR) << "control_result_cb: proxy of device port (cookie="
129                  << StringPrintf("%#hx", cookie) << ") is corrupted";
130       return;
131     }
132     port->ControlResultHandler(status);
133   };
134   auto session_changed_cb = [port = this](uint16_t cookie) {
135     if (!port->in_use()) {
136       LOG(ERROR) << "session_changed_cb: BluetoothAudioPortAidl is not in use";
137       return;
138     }
139     if (port->cookie_ != cookie) {
140       LOG(ERROR) << "session_changed_cb: proxy of device port (cookie="
141                  << StringPrintf("%#hx", cookie) << ") is corrupted";
142       return;
143     }
144     port->SessionChangedHandler();
145   };
146   // TODO: Add audio_config_changed_cb
147   PortStatusCallbacks cbacks = {
148       .control_result_cb_ = control_result_cb,
149       .session_changed_cb_ = session_changed_cb,
150   };
151   cookie_ = BluetoothAudioSessionControl::RegisterControlResultCback(
152       session_type_, cbacks);
153   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
154             << ", cookie=" << StringPrintf("%#hx", cookie_);
155 
156   return (
157       cookie_ !=
158       ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined);
159 }
160 
init_session_type(audio_devices_t device)161 bool BluetoothAudioPortAidl::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)
167           << __func__
168           << ": device=AUDIO_DEVICE_OUT_BLUETOOTH_A2DP (HEADPHONES/SPEAKER) ("
169           << StringPrintf("%#x", device) << ")";
170       session_type_ = SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH;
171       break;
172     case AUDIO_DEVICE_OUT_HEARING_AID:
173       LOG(VERBOSE) << __func__
174                    << ": device=AUDIO_DEVICE_OUT_HEARING_AID (MEDIA/VOICE) ("
175                    << StringPrintf("%#x", device) << ")";
176       session_type_ = SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH;
177       break;
178     case AUDIO_DEVICE_OUT_BLE_HEADSET:
179       LOG(VERBOSE) << __func__
180                    << ": device=AUDIO_DEVICE_OUT_BLE_HEADSET (MEDIA/VOICE) ("
181                    << StringPrintf("%#x", device) << ")";
182       session_type_ = SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
183       break;
184     case AUDIO_DEVICE_OUT_BLE_SPEAKER:
185       LOG(VERBOSE) << __func__
186                    << ": device=AUDIO_DEVICE_OUT_BLE_SPEAKER (MEDIA) ("
187                    << StringPrintf("%#x", device) << ")";
188       session_type_ = SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
189       break;
190     case AUDIO_DEVICE_IN_BLE_HEADSET:
191       LOG(VERBOSE) << __func__
192                    << ": device=AUDIO_DEVICE_IN_BLE_HEADSET (VOICE) ("
193                    << StringPrintf("%#x", device) << ")";
194       session_type_ = SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH;
195       break;
196     case AUDIO_DEVICE_OUT_BLE_BROADCAST:
197       LOG(VERBOSE) << __func__
198                    << ": device=AUDIO_DEVICE_OUT_BLE_BROADCAST (MEDIA) ("
199                    << StringPrintf("%#x", device) << ")";
200       session_type_ =
201           SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH;
202       break;
203     default:
204       LOG(ERROR) << __func__
205                  << ": unknown device=" << StringPrintf("%#x", device);
206       return false;
207   }
208 
209   if (!BluetoothAudioSessionControl::IsSessionReady(session_type_)) {
210     LOG(ERROR) << __func__ << ": device=" << StringPrintf("%#x", device)
211                << ", session_type=" << toString(session_type_)
212                << " is not ready";
213     return false;
214   }
215   return true;
216 }
217 
TearDown()218 void BluetoothAudioPortAidl::TearDown() {
219   if (!in_use()) {
220     LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
221                << ", cookie=" << StringPrintf("%#hx", cookie_)
222                << " unknown monitor";
223     return;
224   }
225 
226   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
227             << ", cookie=" << StringPrintf("%#hx", cookie_);
228   BluetoothAudioSessionControl::UnregisterControlResultCback(session_type_,
229                                                              cookie_);
230   cookie_ =
231       ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined;
232 }
233 
ControlResultHandler(const BluetoothAudioStatus & status)234 void BluetoothAudioPortAidl::ControlResultHandler(
235     const BluetoothAudioStatus& status) {
236   if (!in_use()) {
237     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidlis not in use";
238     return;
239   }
240   std::unique_lock<std::mutex> port_lock(cv_mutex_);
241   BluetoothStreamState previous_state = state_;
242   LOG(INFO) << "control_result_cb: session_type=" << toString(session_type_)
243             << ", cookie=" << StringPrintf("%#hx", cookie_)
244             << ", previous_state=" << previous_state
245             << ", status=" << toString(status);
246 
247   switch (previous_state) {
248     case BluetoothStreamState::STARTED:
249       /* Only Suspend signal can be send in STARTED state*/
250       if (status == BluetoothAudioStatus::RECONFIGURATION ||
251           status == BluetoothAudioStatus::SUCCESS) {
252         state_ = BluetoothStreamState::STANDBY;
253       } else {
254         // Set to standby since the stack may be busy switching between outputs
255         LOG(WARNING) << "control_result_cb: status=" << toString(status)
256                      << " failure for session_type=" << toString(session_type_)
257                      << ", cookie=" << StringPrintf("%#hx", cookie_)
258                      << ", previous_state=" << previous_state;
259       }
260       break;
261     case BluetoothStreamState::STARTING:
262       if (status == BluetoothAudioStatus::SUCCESS) {
263         state_ = BluetoothStreamState::STARTED;
264       } else {
265         // Set to standby since the stack may be busy switching between outputs
266         LOG(WARNING) << "control_result_cb: status=" << toString(status)
267                      << " failure for session_type=" << toString(session_type_)
268                      << ", cookie=" << StringPrintf("%#hx", cookie_)
269                      << ", previous_state=" << previous_state;
270         state_ = BluetoothStreamState::STANDBY;
271       }
272       break;
273     case BluetoothStreamState::SUSPENDING:
274       if (status == BluetoothAudioStatus::SUCCESS) {
275         state_ = BluetoothStreamState::STANDBY;
276       } else {
277         // It will be failed if the headset is disconnecting, and set to disable
278         // to wait for re-init again
279         LOG(WARNING) << "control_result_cb: status=" << toString(status)
280                      << " failure for session_type=" << toString(session_type_)
281                      << ", cookie=" << StringPrintf("%#hx", cookie_)
282                      << ", previous_state=" << previous_state;
283         state_ = BluetoothStreamState::DISABLED;
284       }
285       break;
286     default:
287       LOG(ERROR) << "control_result_cb: unexpected status=" << toString(status)
288                  << " for session_type=" << toString(session_type_)
289                  << ", cookie=" << StringPrintf("%#hx", cookie_)
290                  << ", previous_state=" << previous_state;
291       return;
292   }
293   port_lock.unlock();
294   internal_cv_.notify_all();
295 }
296 
SessionChangedHandler()297 void BluetoothAudioPortAidl::SessionChangedHandler() {
298   if (!in_use()) {
299     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
300     return;
301   }
302   std::unique_lock<std::mutex> port_lock(cv_mutex_);
303   BluetoothStreamState previous_state = state_;
304   LOG(INFO) << "session_changed_cb: session_type=" << toString(session_type_)
305             << ", cookie=" << StringPrintf("%#hx", cookie_)
306             << ", previous_state=" << previous_state;
307   state_ = BluetoothStreamState::DISABLED;
308   port_lock.unlock();
309   internal_cv_.notify_all();
310 }
311 
in_use() const312 bool BluetoothAudioPortAidl::in_use() const {
313   return (
314       cookie_ !=
315       ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined);
316 }
317 
GetPreferredDataIntervalUs(size_t * interval_us) const318 bool BluetoothAudioPortAidl::GetPreferredDataIntervalUs(
319     size_t* interval_us) const {
320   if (!in_use()) {
321     return false;
322   }
323 
324   const AudioConfiguration& hal_audio_cfg =
325       BluetoothAudioSessionControl::GetAudioConfig(session_type_);
326   if (hal_audio_cfg.getTag() != AudioConfiguration::pcmConfig) {
327     return false;
328   }
329 
330   const PcmConfiguration& pcm_cfg =
331       hal_audio_cfg.get<AudioConfiguration::pcmConfig>();
332   *interval_us = pcm_cfg.dataIntervalUs;
333   return true;
334 }
335 
LoadAudioConfig(audio_config_t * audio_cfg) const336 bool BluetoothAudioPortAidlOut::LoadAudioConfig(
337     audio_config_t* audio_cfg) const {
338   if (!in_use()) {
339     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidlOut is not in use";
340     audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
341     audio_cfg->channel_mask = kBluetoothDefaultOutputChannelModeMask;
342     audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
343     return false;
344   }
345 
346   const AudioConfiguration& hal_audio_cfg =
347       BluetoothAudioSessionControl::GetAudioConfig(session_type_);
348   if (hal_audio_cfg.getTag() != AudioConfiguration::pcmConfig) {
349     audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
350     audio_cfg->channel_mask = kBluetoothDefaultOutputChannelModeMask;
351     audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
352     return false;
353   }
354   const PcmConfiguration& pcm_cfg =
355       hal_audio_cfg.get<AudioConfiguration::pcmConfig>();
356   LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
357                << ", cookie=" << StringPrintf("%#hx", cookie_)
358                << ", state=" << state_ << ", PcmConfig=[" << pcm_cfg.toString()
359                << "]";
360   if (pcm_cfg.channelMode == ChannelMode::UNKNOWN) {
361     return false;
362   }
363   audio_cfg->sample_rate = pcm_cfg.sampleRateHz;
364   audio_cfg->channel_mask =
365       (is_stereo_to_mono_
366            ? AUDIO_CHANNEL_OUT_STEREO
367            : OutputChannelModeToAudioFormat(pcm_cfg.channelMode));
368   audio_cfg->format =
369       BitsPerSampleToAudioFormat(pcm_cfg.bitsPerSample, session_type_);
370   return true;
371 }
372 
LoadAudioConfig(audio_config_t * audio_cfg) const373 bool BluetoothAudioPortAidlIn::LoadAudioConfig(
374     audio_config_t* audio_cfg) const {
375   if (!in_use()) {
376     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidlIn is not in use";
377     audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
378     audio_cfg->channel_mask = kBluetoothDefaultInputChannelModeMask;
379     audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
380     return false;
381   }
382 
383   const AudioConfiguration& hal_audio_cfg =
384       BluetoothAudioSessionControl::GetAudioConfig(session_type_);
385   if (hal_audio_cfg.getTag() != AudioConfiguration::pcmConfig) {
386     audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
387     audio_cfg->channel_mask = kBluetoothDefaultInputChannelModeMask;
388     audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
389     return false;
390   }
391   const PcmConfiguration& pcm_cfg =
392       hal_audio_cfg.get<AudioConfiguration::pcmConfig>();
393   LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
394                << ", cookie=" << StringPrintf("%#hx", cookie_)
395                << ", state=" << state_ << ", PcmConfig=[" << pcm_cfg.toString()
396                << "]";
397   if (pcm_cfg.channelMode == ChannelMode::UNKNOWN) {
398     return false;
399   }
400 
401   audio_cfg->sample_rate = pcm_cfg.sampleRateHz;
402   audio_cfg->channel_mask = InputChannelModeToAudioFormat(pcm_cfg.channelMode);
403   audio_cfg->format =
404       BitsPerSampleToAudioFormat(pcm_cfg.bitsPerSample, session_type_);
405   return true;
406 }
407 
CondwaitState(BluetoothStreamState state)408 bool BluetoothAudioPortAidl::CondwaitState(BluetoothStreamState state) {
409   bool retval;
410   std::unique_lock<std::mutex> port_lock(cv_mutex_);
411   switch (state) {
412     case BluetoothStreamState::STARTING:
413       LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
414                    << ", cookie=" << StringPrintf("%#hx", cookie_)
415                    << " waiting for STARTED";
416       retval = internal_cv_.wait_for(
417           port_lock, std::chrono::milliseconds(kMaxWaitingTimeMs),
418           [this] { return this->state_ != BluetoothStreamState::STARTING; });
419       retval = retval && state_ == BluetoothStreamState::STARTED;
420       break;
421     case BluetoothStreamState::SUSPENDING:
422       LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
423                    << ", cookie=" << StringPrintf("%#hx", cookie_)
424                    << " waiting for SUSPENDED";
425       retval = internal_cv_.wait_for(
426           port_lock, std::chrono::milliseconds(kMaxWaitingTimeMs),
427           [this] { return this->state_ != BluetoothStreamState::SUSPENDING; });
428       retval = retval && state_ == BluetoothStreamState::STANDBY;
429       break;
430     default:
431       LOG(WARNING) << __func__ << ": session_type=" << toString(session_type_)
432                    << ", cookie=" << StringPrintf("%#hx", cookie_)
433                    << " waiting for KNOWN";
434       return false;
435   }
436 
437   return retval;  // false if any failure like timeout
438 }
439 
Start()440 bool BluetoothAudioPortAidl::Start() {
441   if (!in_use()) {
442     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
443     return false;
444   }
445 
446   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
447             << ", cookie=" << StringPrintf("%#hx", cookie_)
448             << ", state=" << state_
449             << ", mono=" << (is_stereo_to_mono_ ? "true" : "false")
450             << " request";
451   bool retval = false;
452   if (state_ == BluetoothStreamState::STANDBY) {
453     state_ = BluetoothStreamState::STARTING;
454     if (BluetoothAudioSessionControl::StartStream(session_type_)) {
455       retval = CondwaitState(BluetoothStreamState::STARTING);
456     } else {
457       LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
458                  << ", cookie=" << StringPrintf("%#hx", cookie_)
459                  << ", state=" << state_ << " Hal fails";
460     }
461   }
462 
463   if (retval) {
464     LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
465               << ", cookie=" << StringPrintf("%#hx", cookie_)
466               << ", state=" << state_
467               << ", mono=" << (is_stereo_to_mono_ ? "true" : "false")
468               << " done";
469   } else {
470     LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
471                << ", cookie=" << StringPrintf("%#hx", cookie_)
472                << ", state=" << state_ << " failure";
473   }
474 
475   return retval;  // false if any failure like timeout
476 }
477 
Suspend()478 bool BluetoothAudioPortAidl::Suspend() {
479   if (!in_use()) {
480     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
481     return false;
482   }
483 
484   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
485             << ", cookie=" << StringPrintf("%#hx", cookie_)
486             << ", state=" << state_ << " request";
487   bool retval = false;
488   if (state_ == BluetoothStreamState::STARTED) {
489     state_ = BluetoothStreamState::SUSPENDING;
490     if (BluetoothAudioSessionControl::SuspendStream(session_type_)) {
491       retval = CondwaitState(BluetoothStreamState::SUSPENDING);
492     } else {
493       LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
494                  << ", cookie=" << StringPrintf("%#hx", cookie_)
495                  << ", state=" << state_ << " Hal fails";
496     }
497   }
498 
499   if (retval) {
500     LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
501               << ", cookie=" << StringPrintf("%#hx", cookie_)
502               << ", state=" << state_ << " done";
503   } else {
504     LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
505                << ", cookie=" << StringPrintf("%#hx", cookie_)
506                << ", state=" << state_ << " failure";
507   }
508 
509   return retval;  // false if any failure like timeout
510 }
511 
Stop()512 void BluetoothAudioPortAidl::Stop() {
513   if (!in_use()) {
514     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
515     return;
516   }
517   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
518             << ", cookie=" << StringPrintf("%#hx", cookie_)
519             << ", state=" << state_ << " request";
520   state_ = BluetoothStreamState::DISABLED;
521   BluetoothAudioSessionControl::StopStream(session_type_);
522   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
523             << ", cookie=" << StringPrintf("%#hx", cookie_)
524             << ", state=" << state_ << " done";
525 }
526 
WriteData(const void * buffer,size_t bytes) const527 size_t BluetoothAudioPortAidlOut::WriteData(const void* buffer,
528                                             size_t bytes) const {
529   if (!in_use()) return 0;
530   if (!is_stereo_to_mono_) {
531     return BluetoothAudioSessionControl::OutWritePcmData(session_type_, buffer,
532                                                          bytes);
533   }
534 
535   // WAR to mix the stereo into Mono (16 bits per sample)
536   const size_t write_frames = bytes >> 2;
537   if (write_frames == 0) return 0;
538   auto src = static_cast<const int16_t*>(buffer);
539   std::unique_ptr<int16_t[]> dst{new int16_t[write_frames]};
540   downmix_to_mono_i16_from_stereo_i16(dst.get(), src, write_frames);
541   // a frame is 16 bits, and the size of a mono frame is equal to half a stereo.
542   return BluetoothAudioSessionControl::OutWritePcmData(session_type_, dst.get(),
543                                                        write_frames * 2) *
544          2;
545 }
546 
ReadData(void * buffer,size_t bytes) const547 size_t BluetoothAudioPortAidlIn::ReadData(void* buffer, size_t bytes) const {
548   if (!in_use()) return 0;
549   return BluetoothAudioSessionControl::InReadPcmData(session_type_, buffer,
550                                                      bytes);
551 }
552 
GetPresentationPosition(uint64_t * delay_ns,uint64_t * bytes,timespec * timestamp) const553 bool BluetoothAudioPortAidl::GetPresentationPosition(
554     uint64_t* delay_ns, uint64_t* bytes, timespec* timestamp) const {
555   if (!in_use()) {
556     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
557     return false;
558   }
559   PresentationPosition presentation_position;
560   bool retval = BluetoothAudioSessionControl::GetPresentationPosition(
561       session_type_, presentation_position);
562   *delay_ns = presentation_position.remoteDeviceAudioDelayNanos;
563   *bytes = presentation_position.transmittedOctets;
564   *timestamp = {.tv_sec = static_cast<__kernel_old_time_t>(
565                     presentation_position.transmittedOctetsTimestamp.tvSec),
566                 .tv_nsec = static_cast<long>(
567                     presentation_position.transmittedOctetsTimestamp.tvNSec)};
568   LOG(VERBOSE) << __func__
569                << ": session_type=" << StringPrintf("%#hhx", session_type_)
570                << ", cookie=" << StringPrintf("%#hx", cookie_)
571                << ", state=" << state_ << ", delay=" << *delay_ns
572                << "ns, data=" << *bytes
573                << " bytes, timestamp=" << timestamp->tv_sec << "."
574                << StringPrintf("%09ld", timestamp->tv_nsec) << "s";
575 
576   return retval;
577 }
578 
UpdateSourceMetadata(const source_metadata * source_metadata) const579 void BluetoothAudioPortAidl::UpdateSourceMetadata(
580     const source_metadata* source_metadata) const {
581   if (!in_use()) {
582     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
583     return;
584   }
585   LOG(DEBUG) << __func__ << ": session_type=" << toString(session_type_)
586              << ", cookie=" << StringPrintf("%#hx", cookie_)
587              << ", state=" << state_ << ", " << source_metadata->track_count
588              << " track(s)";
589   if (source_metadata->track_count == 0) return;
590   BluetoothAudioSessionControl::UpdateSourceMetadata(session_type_,
591                                                      *source_metadata);
592 }
593 
UpdateSinkMetadata(const sink_metadata * sink_metadata) const594 void BluetoothAudioPortAidl::UpdateSinkMetadata(
595     const sink_metadata* sink_metadata) const {
596   if (!in_use()) {
597     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
598     return;
599   }
600   LOG(DEBUG) << __func__ << ": session_type=" << toString(session_type_)
601              << ", cookie=" << StringPrintf("%#hx", cookie_)
602              << ", state=" << state_ << ", " << sink_metadata->track_count
603              << " track(s)";
604   if (sink_metadata->track_count == 0) return;
605   BluetoothAudioSessionControl::UpdateSinkMetadata(session_type_,
606                                                    *sink_metadata);
607 }
608 
GetState() const609 BluetoothStreamState BluetoothAudioPortAidl::GetState() const { return state_; }
610 
SetState(BluetoothStreamState state)611 void BluetoothAudioPortAidl::SetState(BluetoothStreamState state) {
612   state_ = state;
613 }
614 
615 }  // namespace aidl
616 }  // namespace audio
617 }  // namespace bluetooth
618 }  // namespace android