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* tag = strtok(tags_copy, ";");
105 
106   while (tag != NULL) {
107     tags.push_back(tag);
108     tag = strtok(NULL, ";");
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 
~BluetoothAudioPortAidlOut()124 BluetoothAudioPortAidlOut::~BluetoothAudioPortAidlOut() {
125   if (in_use()) {
126     TearDown();
127   }
128 }
129 
~BluetoothAudioPortAidlIn()130 BluetoothAudioPortAidlIn::~BluetoothAudioPortAidlIn() {
131   if (in_use()) {
132     TearDown();
133   }
134 }
135 
SetUp(audio_devices_t devices)136 bool BluetoothAudioPortAidl::SetUp(audio_devices_t devices) {
137   if (!init_session_type(devices)) {
138     return false;
139   }
140 
141   state_ = BluetoothStreamState::STANDBY;
142 
143   auto control_result_cb = [port = this](uint16_t cookie, bool /*start_resp*/,
144                                          const BluetoothAudioStatus& status) {
145     if (!port->in_use()) {
146       LOG(ERROR) << "control_result_cb: BluetoothAudioPortAidl is not in use";
147       return;
148     }
149     if (port->cookie_ != cookie) {
150       LOG(ERROR) << "control_result_cb: proxy of device port (cookie="
151                  << StringPrintf("%#hx", cookie) << ") is corrupted";
152       return;
153     }
154     port->ControlResultHandler(status);
155   };
156   auto session_changed_cb = [port = this](uint16_t cookie) {
157     if (!port->in_use()) {
158       LOG(ERROR) << "session_changed_cb: BluetoothAudioPortAidl is not in use";
159       return;
160     }
161     if (port->cookie_ != cookie) {
162       LOG(ERROR) << "session_changed_cb: proxy of device port (cookie="
163                  << StringPrintf("%#hx", cookie) << ") is corrupted";
164       return;
165     }
166     port->SessionChangedHandler();
167   };
168   // TODO: Add audio_config_changed_cb
169   PortStatusCallbacks cbacks = {
170           .control_result_cb_ = control_result_cb,
171           .session_changed_cb_ = session_changed_cb,
172   };
173   cookie_ = BluetoothAudioSessionControl::RegisterControlResultCback(session_type_, cbacks);
174   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
175             << ", cookie=" << StringPrintf("%#hx", cookie_);
176 
177   return cookie_ != ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined;
178 }
179 
init_session_type(audio_devices_t device)180 bool BluetoothAudioPortAidl::init_session_type(audio_devices_t device) {
181   switch (device) {
182     case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
183     case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
184     case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
185       LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLUETOOTH_A2DP (HEADPHONES/SPEAKER) ("
186                    << StringPrintf("%#x", device) << ")";
187       session_type_ = SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH;
188       break;
189     case AUDIO_DEVICE_OUT_HEARING_AID:
190       LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_HEARING_AID (MEDIA/VOICE) ("
191                    << StringPrintf("%#x", device) << ")";
192       session_type_ = SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH;
193       break;
194     case AUDIO_DEVICE_OUT_BLE_HEADSET:
195       LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLE_HEADSET (MEDIA/VOICE) ("
196                    << StringPrintf("%#x", device) << ")";
197       session_type_ = SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
198       break;
199     case AUDIO_DEVICE_OUT_BLE_SPEAKER:
200       LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLE_SPEAKER (MEDIA) ("
201                    << StringPrintf("%#x", device) << ")";
202       session_type_ = SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
203       break;
204     case AUDIO_DEVICE_IN_BLE_HEADSET:
205       LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_IN_BLE_HEADSET (VOICE) ("
206                    << StringPrintf("%#x", device) << ")";
207       session_type_ = SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH;
208       break;
209     case AUDIO_DEVICE_OUT_BLE_BROADCAST:
210       LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLE_BROADCAST (MEDIA) ("
211                    << StringPrintf("%#x", device) << ")";
212       session_type_ = SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH;
213       break;
214     default:
215       LOG(ERROR) << __func__ << ": unknown device=" << StringPrintf("%#x", device);
216       return false;
217   }
218 
219   if (!BluetoothAudioSessionControl::IsSessionReady(session_type_)) {
220     LOG(ERROR) << __func__ << ": device=" << StringPrintf("%#x", device)
221                << ", session_type=" << toString(session_type_) << " is not ready";
222     return false;
223   }
224   return true;
225 }
226 
TearDown()227 void BluetoothAudioPortAidl::TearDown() {
228   if (!in_use()) {
229     LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
230                << ", cookie=" << StringPrintf("%#hx", cookie_) << " unknown monitor";
231     return;
232   }
233 
234   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
235             << ", cookie=" << StringPrintf("%#hx", cookie_);
236   BluetoothAudioSessionControl::UnregisterControlResultCback(session_type_, cookie_);
237   cookie_ = ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined;
238 }
239 
ControlResultHandler(const BluetoothAudioStatus & status)240 void BluetoothAudioPortAidl::ControlResultHandler(const BluetoothAudioStatus& status) {
241   if (!in_use()) {
242     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidlis 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=" << toString(session_type_)
248             << ", cookie=" << StringPrintf("%#hx", cookie_) << ", previous_state=" << previous_state
249             << ", status=" << toString(status);
250 
251   switch (previous_state) {
252     case BluetoothStreamState::STARTED:
253       /* Only Suspend signal can be send in STARTED state*/
254       if (status == BluetoothAudioStatus::RECONFIGURATION ||
255           status == BluetoothAudioStatus::SUCCESS) {
256         state_ = BluetoothStreamState::STANDBY;
257       } else {
258         // Set to standby since the stack may be busy switching between outputs
259         LOG(WARNING) << "control_result_cb: status=" << toString(status)
260                      << " failure for session_type=" << toString(session_type_)
261                      << ", cookie=" << StringPrintf("%#hx", cookie_)
262                      << ", previous_state=" << previous_state;
263       }
264       break;
265     case BluetoothStreamState::STARTING:
266       if (status == BluetoothAudioStatus::SUCCESS) {
267         state_ = BluetoothStreamState::STARTED;
268       } else {
269         // Set to standby since the stack may be busy switching between outputs
270         LOG(WARNING) << "control_result_cb: status=" << toString(status)
271                      << " failure for session_type=" << toString(session_type_)
272                      << ", cookie=" << StringPrintf("%#hx", cookie_)
273                      << ", previous_state=" << previous_state;
274         state_ = BluetoothStreamState::STANDBY;
275       }
276       break;
277     case BluetoothStreamState::SUSPENDING:
278       if (status == BluetoothAudioStatus::SUCCESS) {
279         state_ = BluetoothStreamState::STANDBY;
280       } else {
281         // It will be failed if the headset is disconnecting, and set to disable
282         // to wait for re-init again
283         LOG(WARNING) << "control_result_cb: status=" << toString(status)
284                      << " failure for session_type=" << toString(session_type_)
285                      << ", cookie=" << StringPrintf("%#hx", cookie_)
286                      << ", previous_state=" << previous_state;
287         state_ = BluetoothStreamState::DISABLED;
288       }
289       break;
290     default:
291       LOG(ERROR) << "control_result_cb: unexpected status=" << toString(status)
292                  << " for session_type=" << toString(session_type_)
293                  << ", cookie=" << StringPrintf("%#hx", cookie_)
294                  << ", previous_state=" << previous_state;
295       return;
296   }
297   port_lock.unlock();
298   internal_cv_.notify_all();
299 }
300 
SessionChangedHandler()301 void BluetoothAudioPortAidl::SessionChangedHandler() {
302   if (!in_use()) {
303     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
304     return;
305   }
306   std::unique_lock<std::mutex> port_lock(cv_mutex_);
307   BluetoothStreamState previous_state = state_;
308   LOG(INFO) << "session_changed_cb: session_type=" << toString(session_type_)
309             << ", cookie=" << StringPrintf("%#hx", cookie_)
310             << ", previous_state=" << previous_state;
311   state_ = BluetoothStreamState::DISABLED;
312   port_lock.unlock();
313   internal_cv_.notify_all();
314 }
315 
in_use() const316 bool BluetoothAudioPortAidl::in_use() const {
317   return cookie_ != ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined;
318 }
319 
GetPreferredDataIntervalUs(size_t * interval_us) const320 bool BluetoothAudioPortAidl::GetPreferredDataIntervalUs(size_t* interval_us) const {
321   if (!in_use()) {
322     return false;
323   }
324 
325   const AudioConfiguration& hal_audio_cfg =
326           BluetoothAudioSessionControl::GetAudioConfig(session_type_);
327   if (hal_audio_cfg.getTag() != AudioConfiguration::pcmConfig) {
328     return false;
329   }
330 
331   const PcmConfiguration& pcm_cfg = 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(audio_config_t* audio_cfg) const {
337   if (!in_use()) {
338     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidlOut is not in use";
339     audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
340     audio_cfg->channel_mask = kBluetoothDefaultOutputChannelModeMask;
341     audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
342     return false;
343   }
344 
345   const AudioConfiguration& hal_audio_cfg =
346           BluetoothAudioSessionControl::GetAudioConfig(session_type_);
347   if (hal_audio_cfg.getTag() != AudioConfiguration::pcmConfig) {
348     audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
349     audio_cfg->channel_mask = kBluetoothDefaultOutputChannelModeMask;
350     audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
351     return false;
352   }
353   const PcmConfiguration& pcm_cfg = hal_audio_cfg.get<AudioConfiguration::pcmConfig>();
354   LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
355                << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
356                << ", PcmConfig=[" << pcm_cfg.toString() << "]";
357   if (pcm_cfg.channelMode == ChannelMode::UNKNOWN) {
358     return false;
359   }
360   audio_cfg->sample_rate = pcm_cfg.sampleRateHz;
361   audio_cfg->channel_mask =
362           (is_stereo_to_mono_ ? AUDIO_CHANNEL_OUT_STEREO
363                               : OutputChannelModeToAudioFormat(pcm_cfg.channelMode));
364   audio_cfg->format = BitsPerSampleToAudioFormat(pcm_cfg.bitsPerSample, session_type_);
365   return true;
366 }
367 
LoadAudioConfig(audio_config_t * audio_cfg) const368 bool BluetoothAudioPortAidlIn::LoadAudioConfig(audio_config_t* audio_cfg) const {
369   if (!in_use()) {
370     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidlIn is not in use";
371     audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
372     audio_cfg->channel_mask = kBluetoothDefaultInputChannelModeMask;
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 = kBluetoothDefaultInputChannelModeMask;
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 
393   audio_cfg->sample_rate = pcm_cfg.sampleRateHz;
394   audio_cfg->channel_mask = InputChannelModeToAudioFormat(pcm_cfg.channelMode);
395   audio_cfg->format = BitsPerSampleToAudioFormat(pcm_cfg.bitsPerSample, session_type_);
396   return true;
397 }
398 
CondwaitState(BluetoothStreamState state)399 bool BluetoothAudioPortAidl::CondwaitState(BluetoothStreamState state) {
400   bool retval;
401   std::unique_lock<std::mutex> port_lock(cv_mutex_);
402   switch (state) {
403     case BluetoothStreamState::STARTING:
404       LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
405                    << ", cookie=" << StringPrintf("%#hx", cookie_) << " waiting for STARTED";
406       retval = internal_cv_.wait_for(
407               port_lock, std::chrono::milliseconds(kMaxWaitingTimeMs),
408               [this] { return this->state_ != BluetoothStreamState::STARTING; });
409       retval = retval && state_ == BluetoothStreamState::STARTED;
410       break;
411     case BluetoothStreamState::SUSPENDING:
412       LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
413                    << ", cookie=" << StringPrintf("%#hx", cookie_) << " waiting for SUSPENDED";
414       retval = internal_cv_.wait_for(
415               port_lock, std::chrono::milliseconds(kMaxWaitingTimeMs),
416               [this] { return this->state_ != BluetoothStreamState::SUSPENDING; });
417       retval = retval && state_ == BluetoothStreamState::STANDBY;
418       break;
419     default:
420       LOG(WARNING) << __func__ << ": session_type=" << toString(session_type_)
421                    << ", cookie=" << StringPrintf("%#hx", cookie_) << " waiting for KNOWN";
422       return false;
423   }
424 
425   return retval;  // false if any failure like timeout
426 }
427 
Start()428 bool BluetoothAudioPortAidl::Start() {
429   if (!in_use()) {
430     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
431     return false;
432   }
433 
434   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
435             << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
436             << ", mono=" << (is_stereo_to_mono_ ? "true" : "false") << " request";
437   bool retval = false;
438   if (state_ == BluetoothStreamState::STANDBY) {
439     state_ = BluetoothStreamState::STARTING;
440     if (BluetoothAudioSessionControl::StartStream(session_type_)) {
441       retval = CondwaitState(BluetoothStreamState::STARTING);
442     } else {
443       LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
444                  << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
445                  << " Hal fails";
446     }
447   }
448 
449   if (retval) {
450     LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
451               << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
452               << ", mono=" << (is_stereo_to_mono_ ? "true" : "false") << " done";
453   } else {
454     LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
455                << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
456                << " failure";
457   }
458 
459   return retval;  // false if any failure like timeout
460 }
461 
Suspend()462 bool BluetoothAudioPortAidl::Suspend() {
463   if (!in_use()) {
464     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
465     return false;
466   }
467 
468   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
469             << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " request";
470   bool retval = false;
471   if (state_ == BluetoothStreamState::STARTED) {
472     state_ = BluetoothStreamState::SUSPENDING;
473     if (BluetoothAudioSessionControl::SuspendStream(session_type_)) {
474       retval = CondwaitState(BluetoothStreamState::SUSPENDING);
475     } else {
476       LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
477                  << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
478                  << " Hal fails";
479     }
480   }
481 
482   if (retval) {
483     LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
484               << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " 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 
Stop()494 void BluetoothAudioPortAidl::Stop() {
495   if (!in_use()) {
496     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
497     return;
498   }
499   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
500             << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " request";
501   state_ = BluetoothStreamState::DISABLED;
502   BluetoothAudioSessionControl::StopStream(session_type_);
503   LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
504             << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " done";
505 }
506 
WriteData(const void * buffer,size_t bytes) const507 size_t BluetoothAudioPortAidlOut::WriteData(const void* buffer, size_t bytes) const {
508   if (!in_use()) {
509     return 0;
510   }
511   if (!is_stereo_to_mono_) {
512     return BluetoothAudioSessionControl::OutWritePcmData(session_type_, buffer, bytes);
513   }
514 
515   // WAR to mix the stereo into Mono (16 bits per sample)
516   const size_t write_frames = bytes >> 2;
517   if (write_frames == 0) {
518     return 0;
519   }
520   auto src = static_cast<const int16_t*>(buffer);
521   std::unique_ptr<int16_t[]> dst{new int16_t[write_frames]};
522   downmix_to_mono_i16_from_stereo_i16(dst.get(), src, write_frames);
523   // a frame is 16 bits, and the size of a mono frame is equal to half a stereo.
524   return BluetoothAudioSessionControl::OutWritePcmData(session_type_, dst.get(), write_frames * 2) *
525          2;
526 }
527 
ReadData(void * buffer,size_t bytes) const528 size_t BluetoothAudioPortAidlIn::ReadData(void* buffer, size_t bytes) const {
529   if (!in_use()) {
530     return 0;
531   }
532   return BluetoothAudioSessionControl::InReadPcmData(session_type_, buffer, bytes);
533 }
534 
GetPresentationPosition(uint64_t * delay_ns,uint64_t * bytes,timespec * timestamp) const535 bool BluetoothAudioPortAidl::GetPresentationPosition(uint64_t* delay_ns, uint64_t* bytes,
536                                                      timespec* timestamp) const {
537   if (!in_use()) {
538     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
539     return false;
540   }
541   PresentationPosition presentation_position;
542   bool retval = BluetoothAudioSessionControl::GetPresentationPosition(session_type_,
543                                                                       presentation_position);
544   *delay_ns = presentation_position.remoteDeviceAudioDelayNanos;
545   *bytes = presentation_position.transmittedOctets;
546   *timestamp = {
547           .tv_sec = static_cast<__kernel_old_time_t>(
548                   presentation_position.transmittedOctetsTimestamp.tvSec),
549           .tv_nsec = static_cast<long>(presentation_position.transmittedOctetsTimestamp.tvNSec)};
550   LOG(VERBOSE) << __func__
551                << ": session_type=" << StringPrintf("%#x", static_cast<unsigned>(session_type_))
552                << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
553                << ", delay=" << *delay_ns << "ns, data=" << *bytes
554                << " bytes, timestamp=" << timestamp->tv_sec << "."
555                << StringPrintf("%09ld", timestamp->tv_nsec) << "s";
556 
557   return retval;
558 }
559 
UpdateSourceMetadata(const source_metadata_v7 * source_metadata) const560 void BluetoothAudioPortAidl::UpdateSourceMetadata(const source_metadata_v7* source_metadata) const {
561   if (!in_use()) {
562     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
563     return;
564   }
565   LOG(DEBUG) << __func__ << ": session_type=" << toString(session_type_)
566              << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << ", "
567              << source_metadata->track_count << " track(s)";
568   ssize_t track_count = source_metadata->track_count;
569   if (track_count == 0) {
570     return;
571   }
572   SourceMetadata hal_source_metadata;
573   hal_source_metadata.tracks.resize(track_count);
574   for (int i = 0; i < track_count; i++) {
575     hal_source_metadata.tracks[i].usage =
576             static_cast<AudioUsage>(source_metadata->tracks[i].base.usage);
577     hal_source_metadata.tracks[i].contentType =
578             static_cast<AudioContentType>(source_metadata->tracks[i].base.content_type);
579     hal_source_metadata.tracks[i].tags = CovertAudioTagFromV7(source_metadata->tracks[i].tags);
580   }
581 
582   BluetoothAudioSessionControl::UpdateSourceMetadata(session_type_, hal_source_metadata);
583 }
584 
UpdateSinkMetadata(const sink_metadata_v7 * sink_metadata) const585 void BluetoothAudioPortAidl::UpdateSinkMetadata(const sink_metadata_v7* sink_metadata) const {
586   if (!in_use()) {
587     LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
588     return;
589   }
590   LOG(DEBUG) << __func__ << ": session_type=" << toString(session_type_)
591              << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << ", "
592              << sink_metadata->track_count << " track(s)";
593   ssize_t track_count = sink_metadata->track_count;
594   if (track_count == 0) {
595     return;
596   }
597   SinkMetadata hal_sink_metadata;
598   hal_sink_metadata.tracks.resize(track_count);
599   for (int i = 0; i < track_count; i++) {
600     hal_sink_metadata.tracks[i].source =
601             static_cast<AudioSource>(sink_metadata->tracks[i].base.source);
602     hal_sink_metadata.tracks[i].gain = sink_metadata->tracks[i].base.gain;
603     hal_sink_metadata.tracks[i].tags = CovertAudioTagFromV7(sink_metadata->tracks[i].tags);
604   }
605 
606   BluetoothAudioSessionControl::UpdateSinkMetadata(session_type_, hal_sink_metadata);
607 }
608 
GetState() const609 BluetoothStreamState BluetoothAudioPortAidl::GetState() const { return state_; }
610 
SetState(BluetoothStreamState state)611 void BluetoothAudioPortAidl::SetState(BluetoothStreamState state) { state_ = state; }
612 
613 }  // namespace aidl
614 }  // namespace audio
615 }  // namespace bluetooth
616 }  // namespace android
617