• 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 <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 =
50         std::function<void(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 == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
88           session_type == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH) {
89         return AUDIO_FORMAT_PCM_24_BIT_PACKED;
90       } else {
91         return AUDIO_FORMAT_PCM_8_24_BIT;
92       }
93     case 32:
94       return AUDIO_FORMAT_PCM_32_BIT;
95     default:
96       return kBluetoothDefaultAudioFormatBitsPerSample;
97   }
98 }
99 
CovertAudioTagFromV7(char * tags_v7)100 std::vector<std::string> CovertAudioTagFromV7(char* tags_v7) {
101   std::vector<std::string> tags;
102   char tags_copy[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE];
103   strlcpy(tags_copy, tags_v7, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
104   char* tmpstr;
105   char* tag = strtok_r(tags_copy, ";", &tmpstr);
106   while (tag != NULL) {
107     tags.push_back(tag);
108     tag = strtok_r(NULL, ";", &tmpstr);
109   }
110 
111   return tags;
112 }
113 
114 // The maximum time to wait in std::condition_variable::wait_for()
115 constexpr unsigned int kMaxWaitingTimeMs = 4500;
116 
117 }  // namespace
118 
BluetoothAudioPortAidl()119 BluetoothAudioPortAidl::BluetoothAudioPortAidl()
120     : cookie_(::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined),
121       state_(BluetoothStreamState::DISABLED),
122       session_type_(SessionType::UNKNOWN),
123       latency_mode_callback_(NULL) {}
124 
~BluetoothAudioPortAidlOut()125 BluetoothAudioPortAidlOut::~BluetoothAudioPortAidlOut() {
126   if (in_use()) {
127     TearDown();
128   }
129 }
130 
~BluetoothAudioPortAidlIn()131 BluetoothAudioPortAidlIn::~BluetoothAudioPortAidlIn() {
132   if (in_use()) {
133     TearDown();
134   }
135 }
136 
SetUp(audio_devices_t devices)137 bool BluetoothAudioPortAidl::SetUp(audio_devices_t devices) {
138   if (!init_session_type(devices)) {
139     return false;
140   }
141 
142   state_ = BluetoothStreamState::STANDBY;
143 
144   auto control_result_cb = [port = this](uint16_t cookie, bool /*start_resp*/,
145                                          const BluetoothAudioStatus& status) {
146     if (!port->in_use()) {
147       LOG(ERROR) << "control_result_cb: BluetoothAudioPortAidl is not in use";
148       return;
149     }
150     if (port->cookie_ != cookie) {
151       LOG(ERROR) << "control_result_cb: proxy of device port (cookie="
152                  << StringPrintf("%#hx", cookie) << ") is corrupted";
153       return;
154     }
155     port->ControlResultHandler(status);
156   };
157   auto session_changed_cb = [port = this](uint16_t cookie) {
158     if (!port->in_use()) {
159       LOG(ERROR) << "session_changed_cb: BluetoothAudioPortAidl is not in use";
160       return;
161     }
162     if (port->cookie_ != cookie) {
163       LOG(ERROR) << "session_changed_cb: proxy of device port (cookie="
164                  << StringPrintf("%#hx", cookie) << ") is corrupted";
165       return;
166     }
167     port->SessionChangedHandler();
168   };
169 
170   auto low_latency_allowed_cb = [port = this](uint16_t cookie, bool allowed) {
171     if (!port->in_use()) {
172       LOG(ERROR) << "low_latency_allowed_cb: BluetoothAudioPortAidl is not in use";
173       return;
174     }
175     if (port->cookie_ != cookie) {
176       LOG(ERROR) << "low_latency_allowed_cb: proxy of device port (cookie="
177                  << StringPrintf("%#hx", cookie) << ") is corrupted";
178       return;
179     }
180     port->LowLatencyAllowedHander(allowed);
181   };
182 
183   // TODO: Add audio_config_changed_cb
184   PortStatusCallbacks cbacks = {
185           .control_result_cb_ = control_result_cb,
186           .session_changed_cb_ = session_changed_cb,
187           .low_latency_mode_allowed_cb_ = low_latency_allowed_cb,
188   };
189   cookie_ = BluetoothAudioSessionControl::RegisterControlResultCback(session_type_, cbacks);
190   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
191             << ", cookie=" << StringPrintf("%#hx", cookie_);
192 
193   return cookie_ != ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined;
194 }
195 
init_session_type(audio_devices_t device)196 bool BluetoothAudioPortAidl::init_session_type(audio_devices_t device) {
197   switch (device) {
198     case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
199     case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
200     case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
201       LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLUETOOTH_A2DP (HEADPHONES/SPEAKER) ("
202                    << StringPrintf("%#x", device) << ")";
203       session_type_ = SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH;
204       break;
205     case AUDIO_DEVICE_OUT_HEARING_AID:
206       LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_HEARING_AID (MEDIA/VOICE) ("
207                    << StringPrintf("%#x", device) << ")";
208       session_type_ = SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH;
209       break;
210     case AUDIO_DEVICE_OUT_BLE_HEADSET:
211       LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLE_HEADSET (MEDIA/VOICE) ("
212                    << StringPrintf("%#x", device) << ")";
213       session_type_ = SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
214       break;
215     case AUDIO_DEVICE_OUT_BLE_SPEAKER:
216       LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLE_SPEAKER (MEDIA) ("
217                    << StringPrintf("%#x", device) << ")";
218       session_type_ = SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
219       break;
220     case AUDIO_DEVICE_IN_BLE_HEADSET:
221       LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_IN_BLE_HEADSET (VOICE) ("
222                    << StringPrintf("%#x", device) << ")";
223       session_type_ = SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH;
224       break;
225     case AUDIO_DEVICE_OUT_BLE_BROADCAST:
226       LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLE_BROADCAST (MEDIA) ("
227                    << StringPrintf("%#x", device) << ")";
228       session_type_ = SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH;
229       break;
230     default:
231       LOG(ERROR) << __func__ << ": unknown device=" << StringPrintf("%#x", device);
232       return false;
233   }
234 
235   if (!BluetoothAudioSessionControl::IsSessionReady(session_type_)) {
236     LOG(ERROR) << __func__ << ": device=" << StringPrintf("%#x", device)
237                << ", session_type=" << toString(session_type_) << " is not ready";
238     return false;
239   }
240   return true;
241 }
242 
TearDown()243 void BluetoothAudioPortAidl::TearDown() {
244   if (!in_use()) {
245     LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
246                << ", cookie=" << StringPrintf("%#hx", cookie_) << " unknown monitor";
247     return;
248   }
249 
250   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
251             << ", cookie=" << StringPrintf("%#hx", cookie_);
252   BluetoothAudioSessionControl::UnregisterControlResultCback(session_type_, cookie_);
253   cookie_ = ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined;
254 }
255 
ControlResultHandler(const BluetoothAudioStatus & status)256 void BluetoothAudioPortAidl::ControlResultHandler(const BluetoothAudioStatus& status) {
257   if (!in_use()) {
258     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidlis not in use";
259     return;
260   }
261   std::unique_lock<std::mutex> port_lock(cv_mutex_);
262   BluetoothStreamState previous_state = state_;
263   LOG(INFO) << "control_result_cb: session_type=" << toString(session_type_)
264             << ", cookie=" << StringPrintf("%#hx", cookie_) << ", previous_state=" << previous_state
265             << ", status=" << toString(status);
266 
267   switch (previous_state) {
268     case BluetoothStreamState::STARTED:
269       /* Only Suspend signal can be send in STARTED state*/
270       if (status == BluetoothAudioStatus::RECONFIGURATION ||
271           status == BluetoothAudioStatus::SUCCESS) {
272         state_ = BluetoothStreamState::STANDBY;
273       } else {
274         // Set to standby since the stack may be busy switching between outputs
275         LOG(WARNING) << "control_result_cb: status=" << toString(status)
276                      << " failure for session_type=" << toString(session_type_)
277                      << ", cookie=" << StringPrintf("%#hx", cookie_)
278                      << ", previous_state=" << previous_state;
279       }
280       break;
281     case BluetoothStreamState::STARTING:
282       if (status == BluetoothAudioStatus::SUCCESS) {
283         state_ = BluetoothStreamState::STARTED;
284       } else {
285         // Set to standby since the stack may be busy switching between outputs
286         LOG(WARNING) << "control_result_cb: status=" << toString(status)
287                      << " failure for session_type=" << toString(session_type_)
288                      << ", cookie=" << StringPrintf("%#hx", cookie_)
289                      << ", previous_state=" << previous_state;
290         state_ = BluetoothStreamState::STANDBY;
291       }
292       break;
293     case BluetoothStreamState::SUSPENDING:
294       if (status == BluetoothAudioStatus::SUCCESS) {
295         state_ = BluetoothStreamState::STANDBY;
296       } else {
297         // It will be failed if the headset is disconnecting, and set to disable
298         // to wait for re-init again
299         LOG(WARNING) << "control_result_cb: status=" << toString(status)
300                      << " failure for session_type=" << toString(session_type_)
301                      << ", cookie=" << StringPrintf("%#hx", cookie_)
302                      << ", previous_state=" << previous_state;
303         state_ = BluetoothStreamState::DISABLED;
304       }
305       break;
306     default:
307       LOG(ERROR) << "control_result_cb: unexpected status=" << toString(status)
308                  << " for session_type=" << toString(session_type_)
309                  << ", cookie=" << StringPrintf("%#hx", cookie_)
310                  << ", previous_state=" << previous_state;
311       return;
312   }
313   port_lock.unlock();
314   internal_cv_.notify_all();
315 }
316 
SessionChangedHandler()317 void BluetoothAudioPortAidl::SessionChangedHandler() {
318   if (!in_use()) {
319     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
320     return;
321   }
322   std::unique_lock<std::mutex> port_lock(cv_mutex_);
323   BluetoothStreamState previous_state = state_;
324   LOG(INFO) << "session_changed_cb: session_type=" << toString(session_type_)
325             << ", cookie=" << StringPrintf("%#hx", cookie_)
326             << ", previous_state=" << previous_state;
327   state_ = BluetoothStreamState::DISABLED;
328   port_lock.unlock();
329   internal_cv_.notify_all();
330 }
331 
LowLatencyAllowedHander(bool allowed)332 void BluetoothAudioPortAidl::LowLatencyAllowedHander(bool allowed) {
333   if (!in_use()) {
334     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
335     return;
336   }
337   LOG(INFO) << __func__ << ": allowed=" << allowed;
338   std::unique_lock<std::mutex> port_lock(cv_mutex_);
339   if (latency_mode_callback_) {
340     audio_latency_mode_t modes[2];
341     size_t num_modes = 2;
342     GetRecommendedLatencyModes(modes, &num_modes);
343     latency_mode_callback_(modes, num_modes, latency_mode_callback_cookie_);
344   }
345   port_lock.unlock();
346 }
347 
in_use() const348 bool BluetoothAudioPortAidl::in_use() const {
349   return cookie_ != ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined;
350 }
351 
GetPreferredDataIntervalUs(size_t * interval_us) const352 bool BluetoothAudioPortAidl::GetPreferredDataIntervalUs(size_t* interval_us) const {
353   if (!in_use()) {
354     return false;
355   }
356 
357   const AudioConfiguration& hal_audio_cfg =
358           BluetoothAudioSessionControl::GetAudioConfig(session_type_);
359   if (hal_audio_cfg.getTag() != AudioConfiguration::pcmConfig) {
360     return false;
361   }
362 
363   const PcmConfiguration& pcm_cfg = hal_audio_cfg.get<AudioConfiguration::pcmConfig>();
364   *interval_us = pcm_cfg.dataIntervalUs;
365   return true;
366 }
367 
LoadAudioConfig(audio_config_t * audio_cfg) const368 bool BluetoothAudioPortAidlOut::LoadAudioConfig(audio_config_t* audio_cfg) const {
369   if (!in_use()) {
370     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidlOut is not in use";
371     audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
372     audio_cfg->channel_mask = kBluetoothDefaultOutputChannelModeMask;
373     audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
374     return false;
375   }
376 
377   const AudioConfiguration& hal_audio_cfg =
378           BluetoothAudioSessionControl::GetAudioConfig(session_type_);
379   if (hal_audio_cfg.getTag() != AudioConfiguration::pcmConfig) {
380     audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
381     audio_cfg->channel_mask = kBluetoothDefaultOutputChannelModeMask;
382     audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
383     return false;
384   }
385   const PcmConfiguration& pcm_cfg = hal_audio_cfg.get<AudioConfiguration::pcmConfig>();
386   LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
387                << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
388                << ", PcmConfig=[" << pcm_cfg.toString() << "]";
389   if (pcm_cfg.channelMode == ChannelMode::UNKNOWN) {
390     return false;
391   }
392   audio_cfg->sample_rate = pcm_cfg.sampleRateHz;
393   audio_cfg->channel_mask =
394           (is_stereo_to_mono_ ? AUDIO_CHANNEL_OUT_STEREO
395                               : OutputChannelModeToAudioFormat(pcm_cfg.channelMode));
396   audio_cfg->format = BitsPerSampleToAudioFormat(pcm_cfg.bitsPerSample, session_type_);
397   return true;
398 }
399 
LoadAudioConfig(audio_config_t * audio_cfg) const400 bool BluetoothAudioPortAidlIn::LoadAudioConfig(audio_config_t* audio_cfg) const {
401   if (!in_use()) {
402     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidlIn is not in use";
403     audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
404     audio_cfg->channel_mask = kBluetoothDefaultInputChannelModeMask;
405     audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
406     return false;
407   }
408 
409   const AudioConfiguration& hal_audio_cfg =
410           BluetoothAudioSessionControl::GetAudioConfig(session_type_);
411   if (hal_audio_cfg.getTag() != AudioConfiguration::pcmConfig) {
412     audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
413     audio_cfg->channel_mask = kBluetoothDefaultInputChannelModeMask;
414     audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
415     return false;
416   }
417   const PcmConfiguration& pcm_cfg = hal_audio_cfg.get<AudioConfiguration::pcmConfig>();
418   LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
419                << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
420                << ", PcmConfig=[" << pcm_cfg.toString() << "]";
421   if (pcm_cfg.channelMode == ChannelMode::UNKNOWN) {
422     return false;
423   }
424 
425   audio_cfg->sample_rate = pcm_cfg.sampleRateHz;
426   audio_cfg->channel_mask = InputChannelModeToAudioFormat(pcm_cfg.channelMode);
427   audio_cfg->format = BitsPerSampleToAudioFormat(pcm_cfg.bitsPerSample, session_type_);
428   return true;
429 }
430 
CondwaitState(BluetoothStreamState state)431 bool BluetoothAudioPortAidl::CondwaitState(BluetoothStreamState state) {
432   bool retval;
433   std::unique_lock<std::mutex> port_lock(cv_mutex_);
434   switch (state) {
435     case BluetoothStreamState::STARTING:
436       LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
437                    << ", cookie=" << StringPrintf("%#hx", cookie_) << " waiting for STARTED";
438       retval = internal_cv_.wait_for(
439               port_lock, std::chrono::milliseconds(kMaxWaitingTimeMs),
440               [this] { return this->state_ != BluetoothStreamState::STARTING; });
441       retval = retval && state_ == BluetoothStreamState::STARTED;
442       break;
443     case BluetoothStreamState::SUSPENDING:
444       LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
445                    << ", cookie=" << StringPrintf("%#hx", cookie_) << " waiting for SUSPENDED";
446       retval = internal_cv_.wait_for(
447               port_lock, std::chrono::milliseconds(kMaxWaitingTimeMs),
448               [this] { return this->state_ != BluetoothStreamState::SUSPENDING; });
449       retval = retval && state_ == BluetoothStreamState::STANDBY;
450       break;
451     default:
452       LOG(WARNING) << __func__ << ": session_type=" << toString(session_type_)
453                    << ", cookie=" << StringPrintf("%#hx", cookie_) << " waiting for KNOWN";
454       return false;
455   }
456 
457   return retval;  // false if any failure like timeout
458 }
459 
Start(bool low_latency)460 bool BluetoothAudioPortAidl::Start(bool low_latency) {
461   if (!in_use()) {
462     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
463     return false;
464   }
465 
466   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
467             << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
468             << ", mono=" << (is_stereo_to_mono_ ? "true" : "false") << " request";
469   bool retval = false;
470   if (state_ == BluetoothStreamState::STANDBY) {
471     state_ = BluetoothStreamState::STARTING;
472     if (BluetoothAudioSessionControl::StartStream(session_type_, low_latency)) {
473       retval = CondwaitState(BluetoothStreamState::STARTING);
474     } else {
475       LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
476                  << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
477                  << " Hal fails";
478     }
479   }
480 
481   if (retval) {
482     LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
483               << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
484               << ", mono=" << (is_stereo_to_mono_ ? "true" : "false") << " done";
485   } else {
486     LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
487                << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
488                << " failure";
489   }
490 
491   return retval;  // false if any failure like timeout
492 }
493 
Suspend()494 bool BluetoothAudioPortAidl::Suspend() {
495   if (!in_use()) {
496     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
497     return false;
498   }
499 
500   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
501             << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " request";
502   bool retval = false;
503   if (state_ == BluetoothStreamState::STARTED) {
504     state_ = BluetoothStreamState::SUSPENDING;
505     if (BluetoothAudioSessionControl::SuspendStream(session_type_)) {
506       retval = CondwaitState(BluetoothStreamState::SUSPENDING);
507     } else {
508       LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
509                  << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
510                  << " Hal fails";
511     }
512   }
513 
514   if (retval) {
515     LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
516               << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " done";
517   } else {
518     LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
519                << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
520                << " failure";
521   }
522 
523   return retval;  // false if any failure like timeout
524 }
525 
Stop()526 void BluetoothAudioPortAidl::Stop() {
527   if (!in_use()) {
528     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
529     return;
530   }
531   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
532             << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " request";
533   state_ = BluetoothStreamState::DISABLED;
534   BluetoothAudioSessionControl::StopStream(session_type_);
535   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
536             << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " done";
537 }
538 
539 using ::aidl::android::hardware::bluetooth::audio::LatencyMode;
540 
hidl_latency_mode_to_aidl(audio_latency_mode_t mode)541 static LatencyMode hidl_latency_mode_to_aidl(audio_latency_mode_t mode) {
542   LatencyMode a2dp_latency_mode = LatencyMode::UNKNOWN;
543   switch (mode) {
544     case AUDIO_LATENCY_MODE_FREE:
545       a2dp_latency_mode = LatencyMode::FREE;
546       break;
547     case AUDIO_LATENCY_MODE_LOW:
548       a2dp_latency_mode = LatencyMode::LOW_LATENCY;
549       break;
550     default:
551       a2dp_latency_mode = LatencyMode::UNKNOWN;
552       break;
553   }
554   return a2dp_latency_mode;
555 }
556 
SetLatencyMode(audio_latency_mode_t mode)557 bool BluetoothAudioPortAidl::SetLatencyMode(audio_latency_mode_t mode) {
558   if (!in_use()) {
559     return false;
560   }
561 
562   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", mode=" << mode;
563 
564   BluetoothAudioSessionControl::SetLatencyMode(session_type_, hidl_latency_mode_to_aidl(mode));
565 
566   return true;
567 }
568 
GetRecommendedLatencyModes(audio_latency_mode_t * modes,size_t * num_modes)569 int BluetoothAudioPortAidl::GetRecommendedLatencyModes(audio_latency_mode_t* modes,
570                                                        size_t* num_modes) {
571   if (!in_use()) {
572     return -ENOSYS;
573   }
574 
575   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_);
576 
577   std::vector<LatencyMode> a2dp_modes =
578           BluetoothAudioSessionControl::GetSupportedLatencyModes(session_type_);
579 
580   size_t num_buffer = *num_modes;
581   if (num_buffer < a2dp_modes.size()) {
582     LOG(WARNING) << __func__ << ": audio buffer size " << num_buffer << " <  " << a2dp_modes.size()
583                  << "  A2DP latency modes";
584   } else {
585     num_buffer = a2dp_modes.size();
586     LOG(DEBUG) << __func__ << ": get " << num_buffer << " A2DP latency modes";
587   }
588   *num_modes = 0;
589   for (int i = 0; i < num_buffer; i++) {
590     switch (a2dp_modes[i]) {
591       case LatencyMode::FREE:
592         *(modes + *num_modes) = AUDIO_LATENCY_MODE_FREE;
593         ++(*num_modes);
594         break;
595       case LatencyMode::LOW_LATENCY:
596         *(modes + *num_modes) = AUDIO_LATENCY_MODE_LOW;
597         ++(*num_modes);
598         break;
599       case LatencyMode::UNKNOWN:
600       default:
601         LOG(WARNING) << __func__ << ": ignore the " << i << "-th mode "
602                      << toString(a2dp_modes[i]).c_str() << "%s unknown";
603     }
604   }
605   if (*num_modes != num_buffer) {
606     LOG(WARNING) << __func__ << ": correct num_modes " << num_buffer << " to " << *num_modes;
607   }
608   return 0;
609 }
610 
SetLatencyModeCallback(stream_latency_mode_callback_t callback,void * cookie)611 int BluetoothAudioPortAidl::SetLatencyModeCallback(stream_latency_mode_callback_t callback,
612                                                    void* cookie) {
613   if (!in_use()) {
614     return -ENOSYS;
615   }
616 
617   if (callback != NULL && cookie == NULL) {
618     return -EINVAL;
619   }
620 
621   std::unique_lock<std::mutex> port_lock(cv_mutex_);
622   latency_mode_callback_ = callback;
623   latency_mode_callback_cookie_ = cookie;
624   port_lock.unlock();
625 
626   return 0;
627 }
628 
WriteData(const void * buffer,size_t bytes) const629 size_t BluetoothAudioPortAidlOut::WriteData(const void* buffer, size_t bytes) const {
630   if (!in_use()) {
631     return 0;
632   }
633   if (!is_stereo_to_mono_) {
634     return BluetoothAudioSessionControl::OutWritePcmData(session_type_, buffer, bytes);
635   }
636 
637   // WAR to mix the stereo into Mono (16 bits per sample)
638   const size_t write_frames = bytes >> 2;
639   if (write_frames == 0) {
640     return 0;
641   }
642   auto src = static_cast<const int16_t*>(buffer);
643   std::unique_ptr<int16_t[]> dst{new int16_t[write_frames]};
644   downmix_to_mono_i16_from_stereo_i16(dst.get(), src, write_frames);
645   // a frame is 16 bits, and the size of a mono frame is equal to half a stereo.
646   return BluetoothAudioSessionControl::OutWritePcmData(session_type_, dst.get(), write_frames * 2) *
647          2;
648 }
649 
ReadData(void * buffer,size_t bytes) const650 size_t BluetoothAudioPortAidlIn::ReadData(void* buffer, size_t bytes) const {
651   if (!in_use()) {
652     return 0;
653   }
654   return BluetoothAudioSessionControl::InReadPcmData(session_type_, buffer, bytes);
655 }
656 
GetPresentationPosition(uint64_t * delay_ns,uint64_t * bytes,timespec * timestamp) const657 bool BluetoothAudioPortAidl::GetPresentationPosition(uint64_t* delay_ns, uint64_t* bytes,
658                                                      timespec* timestamp) const {
659   if (!in_use()) {
660     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
661     return false;
662   }
663   PresentationPosition presentation_position;
664   bool retval = BluetoothAudioSessionControl::GetPresentationPosition(session_type_,
665                                                                       presentation_position);
666   *delay_ns = presentation_position.remoteDeviceAudioDelayNanos;
667   *bytes = presentation_position.transmittedOctets;
668   *timestamp = {
669           .tv_sec = static_cast<__kernel_old_time_t>(
670                   presentation_position.transmittedOctetsTimestamp.tvSec),
671           .tv_nsec = static_cast<long>(presentation_position.transmittedOctetsTimestamp.tvNSec)};
672   LOG(VERBOSE) << __func__
673                << ": session_type=" << StringPrintf("%#x", static_cast<unsigned>(session_type_))
674                << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
675                << ", delay=" << *delay_ns << "ns, data=" << *bytes
676                << " bytes, timestamp=" << timestamp->tv_sec << "."
677                << StringPrintf("%09ld", timestamp->tv_nsec) << "s";
678 
679   return retval;
680 }
681 
UpdateSourceMetadata(const source_metadata_v7 * source_metadata) const682 void BluetoothAudioPortAidl::UpdateSourceMetadata(const source_metadata_v7* source_metadata) const {
683   if (!in_use()) {
684     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
685     return;
686   }
687   LOG(DEBUG) << __func__ << ": session_type=" << toString(session_type_)
688              << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << ", "
689              << source_metadata->track_count << " track(s)";
690   ssize_t track_count = source_metadata->track_count;
691   SourceMetadata hal_source_metadata;
692 
693   if (track_count != 0) {
694     hal_source_metadata.tracks.resize(track_count);
695     for (int i = 0; i < track_count; i++) {
696       hal_source_metadata.tracks[i].usage =
697               static_cast<AudioUsage>(source_metadata->tracks[i].base.usage);
698       hal_source_metadata.tracks[i].contentType =
699               static_cast<AudioContentType>(source_metadata->tracks[i].base.content_type);
700       hal_source_metadata.tracks[i].tags = CovertAudioTagFromV7(source_metadata->tracks[i].tags);
701     }
702   }
703 
704   BluetoothAudioSessionControl::UpdateSourceMetadata(session_type_, hal_source_metadata);
705 }
706 
UpdateSinkMetadata(const sink_metadata_v7 * sink_metadata) const707 void BluetoothAudioPortAidl::UpdateSinkMetadata(const sink_metadata_v7* sink_metadata) const {
708   if (!in_use()) {
709     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
710     return;
711   }
712   LOG(DEBUG) << __func__ << ": session_type=" << toString(session_type_)
713              << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << ", "
714              << sink_metadata->track_count << " track(s)";
715   ssize_t track_count = sink_metadata->track_count;
716   SinkMetadata hal_sink_metadata;
717 
718   if (track_count != 0) {
719     hal_sink_metadata.tracks.resize(track_count);
720     for (int i = 0; i < track_count; i++) {
721       hal_sink_metadata.tracks[i].source =
722               static_cast<AudioSource>(sink_metadata->tracks[i].base.source);
723       hal_sink_metadata.tracks[i].gain = sink_metadata->tracks[i].base.gain;
724       hal_sink_metadata.tracks[i].tags = CovertAudioTagFromV7(sink_metadata->tracks[i].tags);
725     }
726   }
727 
728   BluetoothAudioSessionControl::UpdateSinkMetadata(session_type_, hal_sink_metadata);
729 }
730 
GetState() const731 BluetoothStreamState BluetoothAudioPortAidl::GetState() const { return state_; }
732 
SetState(BluetoothStreamState state)733 void BluetoothAudioPortAidl::SetState(BluetoothStreamState state) { state_ = state; }
734 
735 }  // namespace aidl
736 }  // namespace audio
737 }  // namespace bluetooth
738 }  // namespace android
739