• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 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 "BTAudioClientIf"
18 
19 #include "client_interface.h"
20 
21 #include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioPort.h>
22 #include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioProvidersFactory.h>
23 #include <android/hidl/manager/1.2/IServiceManager.h>
24 #include <base/logging.h>
25 #include <hidl/MQDescriptor.h>
26 #include <hidl/ServiceManagement.h>
27 #include <future>
28 
29 #include "osi/include/log.h"
30 
31 namespace bluetooth {
32 namespace audio {
33 
34 using ::android::hardware::hidl_vec;
35 using ::android::hardware::Return;
36 using ::android::hardware::Void;
37 using ::android::hardware::audio::common::V5_0::SourceMetadata;
38 using ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioPort;
39 using ::android::hardware::bluetooth::audio::V2_0::
40     IBluetoothAudioProvidersFactory;
41 using DataMQ = ::android::hardware::MessageQueue<
42     uint8_t, ::android::hardware::kSynchronizedReadWrite>;
43 
44 static constexpr int kDefaultDataReadTimeoutMs = 10;      // 10 ms
45 static constexpr int kDefaultDataReadPollIntervalMs = 1;  // non-blocking poll
46 static constexpr char kFullyQualifiedInterfaceName[] =
47     "android.hardware.bluetooth.audio@2.0::IBluetoothAudioProvidersFactory";
48 
operator <<(std::ostream & os,const BluetoothAudioCtrlAck & ack)49 std::ostream& operator<<(std::ostream& os, const BluetoothAudioCtrlAck& ack) {
50   switch (ack) {
51     case BluetoothAudioCtrlAck::SUCCESS_FINISHED:
52       return os << "SUCCESS_FINISHED";
53     case BluetoothAudioCtrlAck::PENDING:
54       return os << "PENDING";
55     case BluetoothAudioCtrlAck::FAILURE_UNSUPPORTED:
56       return os << "FAILURE_UNSUPPORTED";
57     case BluetoothAudioCtrlAck::FAILURE_BUSY:
58       return os << "FAILURE_BUSY";
59     case BluetoothAudioCtrlAck::FAILURE_DISCONNECTING:
60       return os << "FAILURE_DISCONNECTING";
61     case BluetoothAudioCtrlAck::FAILURE:
62       return os << "FAILURE";
63     default:
64       return os << "UNDEFINED " << static_cast<int8_t>(ack);
65   }
66 }
67 
68 // Internal class within BluetoothAudioClientInterfaceace to implement
69 // IBluetoothAudioPort (control interface used by Bluetooth Audio HAL)
70 class BluetoothAudioPortImpl : public IBluetoothAudioPort {
71  public:
BluetoothAudioPortImpl(IBluetoothTransportInstance * sink,const android::sp<IBluetoothAudioProvider> & provider)72   BluetoothAudioPortImpl(IBluetoothTransportInstance* sink,
73                          const android::sp<IBluetoothAudioProvider>& provider)
74       : sink_(sink), provider_(provider){};
75 
startStream()76   Return<void> startStream() {
77     BluetoothAudioCtrlAck ack = sink_->StartRequest();
78     if (ack != BluetoothAudioCtrlAck::PENDING) {
79       auto hidl_retval =
80           provider_->streamStarted(BluetoothAudioCtrlAckToHalStatus(ack));
81       if (!hidl_retval.isOk()) {
82         LOG(ERROR) << __func__ << ": BluetoothAudioHal failure: " << hidl_retval.description();
83       }
84     }
85     return Void();
86   }
87 
suspendStream()88   Return<void> suspendStream() {
89     BluetoothAudioCtrlAck ack = sink_->SuspendRequest();
90     if (ack != BluetoothAudioCtrlAck::PENDING) {
91       auto hidl_retval =
92           provider_->streamSuspended(BluetoothAudioCtrlAckToHalStatus(ack));
93       if (!hidl_retval.isOk()) {
94         LOG(ERROR) << __func__ << ": BluetoothAudioHal failure: " << hidl_retval.description();
95       }
96     }
97     return Void();
98   }
99 
stopStream()100   Return<void> stopStream() {
101     sink_->StopRequest();
102     return Void();
103   }
104 
getPresentationPosition(getPresentationPosition_cb _hidl_cb)105   Return<void> getPresentationPosition(getPresentationPosition_cb _hidl_cb) {
106     uint64_t remote_delay_report_ns;
107     uint64_t total_bytes_read;
108     timespec data_position;
109     bool retval = sink_->GetPresentationPosition(
110         &remote_delay_report_ns, &total_bytes_read, &data_position);
111 
112     TimeSpec transmittedOctetsTimeStamp;
113     if (retval) {
114       transmittedOctetsTimeStamp = timespec_convert_to_hal(data_position);
115     } else {
116       remote_delay_report_ns = 0;
117       total_bytes_read = 0;
118       transmittedOctetsTimeStamp = {};
119     }
120     VLOG(2) << __func__ << ": result=" << retval
121             << ", delay=" << remote_delay_report_ns
122             << ", data=" << total_bytes_read
123             << " byte(s), timestamp=" << toString(transmittedOctetsTimeStamp);
124     _hidl_cb((retval ? BluetoothAudioStatus::SUCCESS
125                      : BluetoothAudioStatus::FAILURE),
126              remote_delay_report_ns, total_bytes_read,
127              transmittedOctetsTimeStamp);
128     return Void();
129   }
130 
updateMetadata(const SourceMetadata & sourceMetadata)131   Return<void> updateMetadata(const SourceMetadata& sourceMetadata) {
132     LOG(INFO) << __func__ << ": " << sourceMetadata.tracks.size()
133               << " track(s)";
134     // refer to StreamOut.impl.h within Audio HAL (AUDIO_HAL_VERSION_5_0)
135     std::vector<playback_track_metadata> metadata_vec;
136     metadata_vec.reserve(sourceMetadata.tracks.size());
137     for (const auto& metadata : sourceMetadata.tracks) {
138       metadata_vec.push_back({
139           .usage = static_cast<audio_usage_t>(metadata.usage),
140           .content_type =
141               static_cast<audio_content_type_t>(metadata.contentType),
142           .gain = metadata.gain,
143       });
144     }
145     const source_metadata_t source_metadata = {
146         .track_count = metadata_vec.size(), .tracks = metadata_vec.data()};
147     sink_->MetadataChanged(source_metadata);
148     return Void();
149   }
150 
151  private:
152   IBluetoothTransportInstance* sink_;
153   const android::sp<IBluetoothAudioProvider> provider_;
timespec_convert_to_hal(const timespec & ts)154   TimeSpec timespec_convert_to_hal(const timespec& ts) {
155     return {.tvSec = static_cast<uint64_t>(ts.tv_sec),
156             .tvNSec = static_cast<uint64_t>(ts.tv_nsec)};
157   }
158 };
159 
160 class BluetoothAudioDeathRecipient
161     : public ::android::hardware::hidl_death_recipient {
162  public:
BluetoothAudioDeathRecipient(BluetoothAudioClientInterface * clientif,bluetooth::common::MessageLoopThread * message_loop)163   BluetoothAudioDeathRecipient(
164       BluetoothAudioClientInterface* clientif,
165       bluetooth::common::MessageLoopThread* message_loop)
166       : bluetooth_audio_clientif_(clientif), message_loop_(message_loop) {}
serviceDied(uint64_t,const::android::wp<::android::hidl::base::V1_0::IBase> &)167   void serviceDied(
168       uint64_t /*cookie*/,
169       const ::android::wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
170     LOG(WARNING) << __func__ << ": restarting connection with new Audio Hal";
171     if (bluetooth_audio_clientif_ != nullptr && message_loop_ != nullptr) {
172       // restart the session on the correct thread
173       message_loop_->DoInThread(
174           FROM_HERE,
175           base::BindOnce(
176               &BluetoothAudioClientInterface::RenewAudioProviderAndSession,
177               base::Unretained(bluetooth_audio_clientif_)));
178     } else {
179       LOG(ERROR) << __func__ << ": BluetoothAudioClientInterface corrupted";
180     }
181   }
182 
183  private:
184   BluetoothAudioClientInterface* bluetooth_audio_clientif_;
185   bluetooth::common::MessageLoopThread* message_loop_;
186 };
187 
BluetoothAudioClientInterface(IBluetoothTransportInstance * sink,bluetooth::common::MessageLoopThread * message_loop)188 BluetoothAudioClientInterface::BluetoothAudioClientInterface(IBluetoothTransportInstance* sink,
189                                                              bluetooth::common::MessageLoopThread* message_loop)
190     : sink_(sink), provider_(nullptr), session_started_(false), mDataMQ(nullptr),
191       death_recipient_(new BluetoothAudioDeathRecipient(this, message_loop)) {
192   auto service_manager = android::hardware::defaultServiceManager1_2();
193   CHECK(service_manager != nullptr);
194   size_t instance_count = 0;
195   auto listManifestByInterface_cb = [&instance_count](const hidl_vec<android::hardware::hidl_string>& instanceNames) {
196     instance_count = instanceNames.size();
197     LOG(INFO) << "listManifestByInterface_cb returns " << instance_count << " instance(s)";
198   };
199   auto hidl_retval = service_manager->listManifestByInterface(kFullyQualifiedInterfaceName, listManifestByInterface_cb);
200   if (!hidl_retval.isOk()) {
201     LOG(FATAL) << __func__ << ": IServiceManager::listByInterface failure: " << hidl_retval.description();
202   }
203   if (instance_count > 0) {
204     fetch_audio_provider();
205   } else {
206     LOG(WARNING) << "IBluetoothAudioProvidersFactory not declared";
207   }
208 }
209 
~BluetoothAudioClientInterface()210 BluetoothAudioClientInterface::~BluetoothAudioClientInterface() {
211   if (provider_ != nullptr) {
212     auto hidl_retval = provider_->unlinkToDeath(death_recipient_);
213     if (!hidl_retval.isOk()) {
214       LOG(FATAL) << __func__ << ": BluetoothAudioDeathRecipient failure: " << hidl_retval.description();
215     }
216   }
217 }
218 
219 std::vector<AudioCapabilities>
GetAudioCapabilities() const220 BluetoothAudioClientInterface::GetAudioCapabilities() const {
221   return capabilities_;
222 }
223 
fetch_audio_provider()224 void BluetoothAudioClientInterface::fetch_audio_provider() {
225   if (provider_ != nullptr) {
226     LOG(WARNING) << __func__ << ": reflash";
227   }
228 
229   android::sp<IBluetoothAudioProvidersFactory> providersFactory =
230       IBluetoothAudioProvidersFactory::getService();
231   CHECK(providersFactory != nullptr) << "IBluetoothAudioProvidersFactory::getService() failed";
232   LOG(INFO) << "IBluetoothAudioProvidersFactory::getService() returned "
233             << providersFactory.get()
234             << (providersFactory->isRemote() ? " (remote)" : " (local)");
235 
236   std::promise<void> getProviderCapabilities_promise;
237   auto getProviderCapabilities_future =
238       getProviderCapabilities_promise.get_future();
239   auto getProviderCapabilities_cb =
240       [& capabilities = this->capabilities_, &getProviderCapabilities_promise](
241           const hidl_vec<AudioCapabilities>& audioCapabilities) {
242         for (auto capability : audioCapabilities) {
243           capabilities.push_back(capability);
244         }
245         getProviderCapabilities_promise.set_value();
246       };
247   auto hidl_retval = providersFactory->getProviderCapabilities(
248       sink_->GetSessionType(), getProviderCapabilities_cb);
249   getProviderCapabilities_future.get();
250   if (!hidl_retval.isOk()) {
251     LOG(FATAL) << __func__ << ": BluetoothAudioHal::getProviderCapabilities failure: " << hidl_retval.description();
252     return;
253   }
254   if (capabilities_.empty()) {
255     LOG(WARNING) << __func__
256                  << ": SessionType=" << toString(sink_->GetSessionType())
257                  << " Not supported by BluetoothAudioHal";
258     return;
259   }
260   LOG(INFO) << __func__ << ": BluetoothAudioHal SessionType="
261             << toString(sink_->GetSessionType()) << " has "
262             << capabilities_.size() << " AudioCapabilities";
263 
264   std::promise<void> openProvider_promise;
265   auto openProvider_future = openProvider_promise.get_future();
266   auto openProvider_cb =
267       [& provider_ = this->provider_, &openProvider_promise](
268           BluetoothAudioStatus status,
269           const android::sp<IBluetoothAudioProvider>& provider) {
270         LOG(INFO) << "openProvider_cb(" << toString(status) << ")";
271         if (status == BluetoothAudioStatus::SUCCESS) {
272           provider_ = provider;
273         }
274         ALOGE_IF(!provider_, "Failed to open BluetoothAudio provider");
275         openProvider_promise.set_value();
276       };
277   hidl_retval =
278       providersFactory->openProvider(sink_->GetSessionType(), openProvider_cb);
279   openProvider_future.get();
280   if (!hidl_retval.isOk()) {
281     LOG(FATAL) << __func__ << ": BluetoothAudioHal::openProvider failure: " << hidl_retval.description();
282   }
283   CHECK(provider_ != nullptr);
284 
285   if (!provider_->linkToDeath(death_recipient_, 0).isOk()) {
286     LOG(FATAL) << __func__ << ": BluetoothAudioDeathRecipient failure: " << hidl_retval.description();
287   }
288 
289   LOG(INFO) << "IBluetoothAudioProvidersFactory::openProvider() returned "
290             << provider_.get()
291             << (provider_->isRemote() ? " (remote)" : " (local)");
292 }
293 
UpdateAudioConfig(const AudioConfiguration & audio_config)294 bool BluetoothAudioClientInterface::UpdateAudioConfig(
295     const AudioConfiguration& audio_config) {
296   bool is_software_session =
297       (sink_->GetSessionType() ==
298            SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
299        sink_->GetSessionType() ==
300            SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH);
301   bool is_offload_session =
302       (sink_->GetSessionType() == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
303   auto audio_config_discriminator = audio_config.getDiscriminator();
304   bool is_software_audio_config =
305       (is_software_session &&
306        audio_config_discriminator ==
307            AudioConfiguration::hidl_discriminator::pcmConfig);
308   bool is_offload_audio_config =
309       (is_offload_session &&
310        audio_config_discriminator ==
311            AudioConfiguration::hidl_discriminator::codecConfig);
312   if (!is_software_audio_config && !is_offload_audio_config) {
313     return false;
314   }
315   sink_->UpdateAudioConfiguration(audio_config);
316   return true;
317 }
318 
StartSession()319 int BluetoothAudioClientInterface::StartSession() {
320   std::lock_guard<std::mutex> guard(internal_mutex_);
321   if (provider_ == nullptr) {
322     LOG(ERROR) << __func__ << ": BluetoothAudioHal nullptr";
323     session_started_ = false;
324     return -EINVAL;
325   }
326   if (session_started_) {
327     LOG(ERROR) << __func__ << ": session started already";
328     return -EBUSY;
329   }
330 
331   android::sp<IBluetoothAudioPort> stack_if =
332       new BluetoothAudioPortImpl(sink_, provider_);
333   std::unique_ptr<DataMQ> tempDataMQ;
334   BluetoothAudioStatus session_status;
335 
336   std::promise<void> hidl_startSession_promise;
337   auto hidl_startSession_future = hidl_startSession_promise.get_future();
338   auto hidl_cb = [&session_status, &tempDataMQ, &hidl_startSession_promise](
339                      BluetoothAudioStatus status,
340                      const DataMQ::Descriptor& dataMQ) {
341     LOG(INFO) << "startSession_cb(" << toString(status) << ")";
342     session_status = status;
343     if (status == BluetoothAudioStatus::SUCCESS && dataMQ.isHandleValid()) {
344       tempDataMQ.reset(new DataMQ(dataMQ));
345     }
346     hidl_startSession_promise.set_value();
347   };
348   auto hidl_retval = provider_->startSession(
349       stack_if, sink_->GetAudioConfiguration(), hidl_cb);
350   hidl_startSession_future.get();
351   if (!hidl_retval.isOk()) {
352     LOG(FATAL) << __func__ << ": BluetoothAudioHal failure: " << hidl_retval.description();
353     return -EPROTO;
354   }
355 
356   if (tempDataMQ && tempDataMQ->isValid()) {
357     mDataMQ = std::move(tempDataMQ);
358   } else if (sink_->GetSessionType() ==
359                  SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH &&
360              session_status == BluetoothAudioStatus::SUCCESS) {
361     sink_->ResetPresentationPosition();
362     session_started_ = true;
363     return 0;
364   }
365   if (mDataMQ && mDataMQ->isValid()) {
366     sink_->ResetPresentationPosition();
367     session_started_ = true;
368     return 0;
369   } else {
370     ALOGE_IF(!mDataMQ, "Failed to obtain audio data path");
371     ALOGE_IF(mDataMQ && !mDataMQ->isValid(), "Audio data path is invalid");
372     session_started_ = false;
373     return -EIO;
374   }
375 }
376 
StreamStarted(const BluetoothAudioCtrlAck & ack)377 void BluetoothAudioClientInterface::StreamStarted(
378     const BluetoothAudioCtrlAck& ack) {
379   if (provider_ == nullptr) {
380     LOG(ERROR) << __func__ << ": BluetoothAudioHal nullptr";
381     return;
382   }
383   if (ack == BluetoothAudioCtrlAck::PENDING) {
384     LOG(INFO) << __func__ << ": " << ack << " ignored";
385     return;
386   }
387   BluetoothAudioStatus status = BluetoothAudioCtrlAckToHalStatus(ack);
388   auto hidl_retval = provider_->streamStarted(status);
389   if (!hidl_retval.isOk()) {
390     LOG(ERROR) << __func__ << ": BluetoothAudioHal failure: " << hidl_retval.description();
391   }
392 }
393 
StreamSuspended(const BluetoothAudioCtrlAck & ack)394 void BluetoothAudioClientInterface::StreamSuspended(
395     const BluetoothAudioCtrlAck& ack) {
396   if (provider_ == nullptr) {
397     LOG(ERROR) << __func__ << ": BluetoothAudioHal nullptr";
398     return;
399   }
400   if (ack == BluetoothAudioCtrlAck::PENDING) {
401     LOG(INFO) << __func__ << ": " << ack << " ignored";
402     return;
403   }
404   BluetoothAudioStatus status = BluetoothAudioCtrlAckToHalStatus(ack);
405   auto hidl_retval = provider_->streamSuspended(status);
406   if (!hidl_retval.isOk()) {
407     LOG(ERROR) << __func__ << ": BluetoothAudioHal failure: " << hidl_retval.description();
408   }
409 }
410 
EndSession()411 int BluetoothAudioClientInterface::EndSession() {
412   std::lock_guard<std::mutex> guard(internal_mutex_);
413   if (!session_started_) {
414     LOG(INFO) << __func__ << ": sessoin ended already";
415     return 0;
416   }
417 
418   session_started_ = false;
419   if (provider_ == nullptr) {
420     LOG(ERROR) << __func__ << ": BluetoothAudioHal nullptr";
421     return -EINVAL;
422   }
423   mDataMQ = nullptr;
424   auto hidl_retval = provider_->endSession();
425   if (!hidl_retval.isOk()) {
426     LOG(ERROR) << __func__ << ": BluetoothAudioHal failure: " << hidl_retval.description();
427     return -EPROTO;
428   }
429   return 0;
430 }
431 
ReadAudioData(uint8_t * p_buf,uint32_t len)432 size_t BluetoothAudioClientInterface::ReadAudioData(uint8_t* p_buf,
433                                                     uint32_t len) {
434   if (provider_ == nullptr) {
435     LOG(ERROR) << __func__ << ": BluetoothAudioHal nullptr";
436     return 0;
437   }
438   if (p_buf == nullptr || len == 0) return 0;
439 
440   std::lock_guard<std::mutex> guard(internal_mutex_);
441 
442   size_t total_read = 0;
443   int timeout_ms = kDefaultDataReadTimeoutMs;
444   do {
445     if (mDataMQ == nullptr || !mDataMQ->isValid()) break;
446 
447     size_t avail_to_read = mDataMQ->availableToRead();
448     if (avail_to_read) {
449       if (avail_to_read > len - total_read) {
450         avail_to_read = len - total_read;
451       }
452       if (mDataMQ->read(p_buf + total_read, avail_to_read) == 0) {
453         LOG(WARNING) << __func__ << ": len=" << len
454                      << " total_read=" << total_read << " failed";
455         break;
456       }
457       total_read += avail_to_read;
458     } else if (timeout_ms >= kDefaultDataReadPollIntervalMs) {
459       std::this_thread::sleep_for(
460           std::chrono::milliseconds(kDefaultDataReadPollIntervalMs));
461       timeout_ms -= kDefaultDataReadPollIntervalMs;
462       continue;
463     } else {
464       LOG(WARNING) << __func__ << ": " << (len - total_read) << "/" << len
465                    << " no data " << (kDefaultDataReadTimeoutMs - timeout_ms)
466                    << " ms";
467       break;
468     }
469   } while (total_read < len);
470 
471   if (timeout_ms <
472           (kDefaultDataReadTimeoutMs - kDefaultDataReadPollIntervalMs) &&
473       timeout_ms >= kDefaultDataReadPollIntervalMs) {
474     VLOG(1) << __func__ << ": underflow " << len << " -> " << total_read
475             << " read " << (kDefaultDataReadTimeoutMs - timeout_ms) << " ms";
476   } else {
477     VLOG(2) << __func__ << ": " << len << " -> " << total_read << " read";
478   }
479 
480   sink_->LogBytesRead(total_read);
481   return total_read;
482 }
483 
WriteAudioData(uint8_t * p_buf,uint32_t len)484 size_t BluetoothAudioClientInterface::WriteAudioData(uint8_t* p_buf,
485                                                      uint32_t len) {
486   // Not implemented!
487   return 0;
488 }
489 
RenewAudioProviderAndSession()490 void BluetoothAudioClientInterface::RenewAudioProviderAndSession() {
491   // NOTE: must be invoked on the same thread where this
492   // BluetoothAudioClientInterface is running
493   fetch_audio_provider();
494   session_started_ = false;
495   StartSession();
496 }
497 
498 }  // namespace audio
499 }  // namespace bluetooth
500