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