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