/* * Copyright 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "bluetooth_audio_port_impl.h" #include "btif/include/btif_common.h" #include "common/stop_watch_legacy.h" namespace bluetooth { namespace audio { namespace aidl { using ::bluetooth::common::StopWatchLegacy; BluetoothAudioPortImpl::BluetoothAudioPortImpl( IBluetoothTransportInstance* transport_instance, const std::shared_ptr& provider) : transport_instance_(transport_instance), provider_(provider) {} BluetoothAudioPortImpl::~BluetoothAudioPortImpl() {} ndk::ScopedAStatus BluetoothAudioPortImpl::startStream(bool is_low_latency) { StopWatchLegacy stop_watch(__func__); BluetoothAudioCtrlAck ack = transport_instance_->StartRequest(is_low_latency); if (ack != BluetoothAudioCtrlAck::PENDING) { auto aidl_retval = provider_->streamStarted(BluetoothAudioCtrlAckToHalStatus(ack)); if (!aidl_retval.isOk()) { LOG(ERROR) << __func__ << ": BluetoothAudioHal failure: " << aidl_retval.getDescription(); } } return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus BluetoothAudioPortImpl::suspendStream() { StopWatchLegacy stop_watch(__func__); BluetoothAudioCtrlAck ack = transport_instance_->SuspendRequest(); if (ack != BluetoothAudioCtrlAck::PENDING) { auto aidl_retval = provider_->streamSuspended(BluetoothAudioCtrlAckToHalStatus(ack)); if (!aidl_retval.isOk()) { LOG(ERROR) << __func__ << ": BluetoothAudioHal failure: " << aidl_retval.getDescription(); } } return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus BluetoothAudioPortImpl::stopStream() { StopWatchLegacy stop_watch(__func__); transport_instance_->StopRequest(); return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus BluetoothAudioPortImpl::getPresentationPosition( PresentationPosition* _aidl_return) { StopWatchLegacy stop_watch(__func__); uint64_t remote_delay_report_ns; uint64_t total_bytes_read; timespec data_position; bool retval = transport_instance_->GetPresentationPosition( &remote_delay_report_ns, &total_bytes_read, &data_position); PresentationPosition::TimeSpec transmittedOctetsTimeStamp; if (retval) { transmittedOctetsTimeStamp = timespec_convert_to_hal(data_position); } else { remote_delay_report_ns = 0; total_bytes_read = 0; transmittedOctetsTimeStamp = {}; } VLOG(2) << __func__ << ": result=" << retval << ", delay=" << remote_delay_report_ns << ", data=" << total_bytes_read << " byte(s), timestamp=" << transmittedOctetsTimeStamp.toString(); _aidl_return->remoteDeviceAudioDelayNanos = static_cast(remote_delay_report_ns); _aidl_return->transmittedOctets = static_cast(total_bytes_read); _aidl_return->transmittedOctetsTimestamp = transmittedOctetsTimeStamp; return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus BluetoothAudioPortImpl::updateSourceMetadata( const SourceMetadata& source_metadata) { StopWatchLegacy stop_watch(__func__); LOG(INFO) << __func__ << ": " << source_metadata.tracks.size() << "track(s)"; std::vector metadata_vec; metadata_vec.reserve(source_metadata.tracks.size()); for (const auto& metadata : source_metadata.tracks) { metadata_vec.push_back({ .usage = static_cast(metadata.usage), .content_type = static_cast(metadata.contentType), .gain = metadata.gain, }); } const source_metadata_t legacy_source_metadata = { .track_count = metadata_vec.size(), .tracks = metadata_vec.data()}; transport_instance_->SourceMetadataChanged(legacy_source_metadata); return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus BluetoothAudioPortImpl::updateSinkMetadata( const SinkMetadata& sink_metadata) { StopWatchLegacy stop_watch(__func__); LOG(INFO) << __func__ << ": " << sink_metadata.tracks.size() << " track(s)"; std::vector metadata_vec; metadata_vec.reserve(sink_metadata.tracks.size()); for (const auto& metadata : sink_metadata.tracks) { metadata_vec.push_back({ .source = static_cast(metadata.source), .gain = metadata.gain, }); } const sink_metadata_t legacy_sink_metadata = { .track_count = metadata_vec.size(), .tracks = metadata_vec.data()}; transport_instance_->SinkMetadataChanged(legacy_sink_metadata); return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus BluetoothAudioPortImpl::setLatencyMode( LatencyMode latency_mode) { bool is_low_latency = latency_mode == LatencyMode::LOW_LATENCY ? true : false; invoke_switch_buffer_size_cb(is_low_latency); transport_instance_->SetLowLatency(is_low_latency); return ndk::ScopedAStatus::ok(); } PresentationPosition::TimeSpec BluetoothAudioPortImpl::timespec_convert_to_hal( const timespec& ts) { return {.tvSec = static_cast(ts.tv_sec), .tvNSec = static_cast(ts.tv_nsec)}; } } // namespace aidl } // namespace audio } // namespace bluetooth