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