• 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 #include "bluetooth_audio_port_impl.h"
18 
19 #include "btif/include/btif_common.h"
20 #include "common/stop_watch_legacy.h"
21 
22 namespace bluetooth {
23 namespace audio {
24 namespace aidl {
25 
26 using ::bluetooth::common::StopWatchLegacy;
27 
BluetoothAudioPortImpl(IBluetoothTransportInstance * transport_instance,const std::shared_ptr<IBluetoothAudioProvider> & provider)28 BluetoothAudioPortImpl::BluetoothAudioPortImpl(
29     IBluetoothTransportInstance* transport_instance,
30     const std::shared_ptr<IBluetoothAudioProvider>& provider)
31     : transport_instance_(transport_instance), provider_(provider) {}
32 
~BluetoothAudioPortImpl()33 BluetoothAudioPortImpl::~BluetoothAudioPortImpl() {}
34 
startStream(bool is_low_latency)35 ndk::ScopedAStatus BluetoothAudioPortImpl::startStream(bool is_low_latency) {
36   StopWatchLegacy stop_watch(__func__);
37   BluetoothAudioCtrlAck ack = transport_instance_->StartRequest(is_low_latency);
38   if (ack != BluetoothAudioCtrlAck::PENDING) {
39     auto aidl_retval =
40         provider_->streamStarted(BluetoothAudioCtrlAckToHalStatus(ack));
41     if (!aidl_retval.isOk()) {
42       LOG(ERROR) << __func__ << ": BluetoothAudioHal failure: "
43                  << aidl_retval.getDescription();
44     }
45   }
46   return ndk::ScopedAStatus::ok();
47 }
48 
suspendStream()49 ndk::ScopedAStatus BluetoothAudioPortImpl::suspendStream() {
50   StopWatchLegacy stop_watch(__func__);
51   BluetoothAudioCtrlAck ack = transport_instance_->SuspendRequest();
52   if (ack != BluetoothAudioCtrlAck::PENDING) {
53     auto aidl_retval =
54         provider_->streamSuspended(BluetoothAudioCtrlAckToHalStatus(ack));
55     if (!aidl_retval.isOk()) {
56       LOG(ERROR) << __func__ << ": BluetoothAudioHal failure: "
57                  << aidl_retval.getDescription();
58     }
59   }
60   return ndk::ScopedAStatus::ok();
61 }
62 
stopStream()63 ndk::ScopedAStatus BluetoothAudioPortImpl::stopStream() {
64   StopWatchLegacy stop_watch(__func__);
65   transport_instance_->StopRequest();
66   return ndk::ScopedAStatus::ok();
67 }
68 
getPresentationPosition(PresentationPosition * _aidl_return)69 ndk::ScopedAStatus BluetoothAudioPortImpl::getPresentationPosition(
70     PresentationPosition* _aidl_return) {
71   StopWatchLegacy stop_watch(__func__);
72   uint64_t remote_delay_report_ns;
73   uint64_t total_bytes_read;
74   timespec data_position;
75   bool retval = transport_instance_->GetPresentationPosition(
76       &remote_delay_report_ns, &total_bytes_read, &data_position);
77 
78   PresentationPosition::TimeSpec transmittedOctetsTimeStamp;
79   if (retval) {
80     transmittedOctetsTimeStamp = timespec_convert_to_hal(data_position);
81   } else {
82     remote_delay_report_ns = 0;
83     total_bytes_read = 0;
84     transmittedOctetsTimeStamp = {};
85   }
86   VLOG(2) << __func__ << ": result=" << retval
87           << ", delay=" << remote_delay_report_ns
88           << ", data=" << total_bytes_read
89           << " byte(s), timestamp=" << transmittedOctetsTimeStamp.toString();
90   _aidl_return->remoteDeviceAudioDelayNanos =
91       static_cast<int64_t>(remote_delay_report_ns);
92   _aidl_return->transmittedOctets = static_cast<int64_t>(total_bytes_read);
93   _aidl_return->transmittedOctetsTimestamp = transmittedOctetsTimeStamp;
94   return ndk::ScopedAStatus::ok();
95 }
96 
updateSourceMetadata(const SourceMetadata & source_metadata)97 ndk::ScopedAStatus BluetoothAudioPortImpl::updateSourceMetadata(
98     const SourceMetadata& source_metadata) {
99   StopWatchLegacy stop_watch(__func__);
100   LOG(INFO) << __func__ << ": " << source_metadata.tracks.size() << "track(s)";
101 
102   std::vector<playback_track_metadata> metadata_vec;
103   metadata_vec.reserve(source_metadata.tracks.size());
104   for (const auto& metadata : source_metadata.tracks) {
105     metadata_vec.push_back({
106         .usage = static_cast<audio_usage_t>(metadata.usage),
107         .content_type = static_cast<audio_content_type_t>(metadata.contentType),
108         .gain = metadata.gain,
109     });
110   }
111   const source_metadata_t legacy_source_metadata = {
112       .track_count = metadata_vec.size(), .tracks = metadata_vec.data()};
113   transport_instance_->SourceMetadataChanged(legacy_source_metadata);
114   return ndk::ScopedAStatus::ok();
115 }
116 
updateSinkMetadata(const SinkMetadata & sink_metadata)117 ndk::ScopedAStatus BluetoothAudioPortImpl::updateSinkMetadata(
118     const SinkMetadata& sink_metadata) {
119   StopWatchLegacy stop_watch(__func__);
120   LOG(INFO) << __func__ << ": " << sink_metadata.tracks.size() << " track(s)";
121 
122   std::vector<record_track_metadata> metadata_vec;
123   metadata_vec.reserve(sink_metadata.tracks.size());
124   for (const auto& metadata : sink_metadata.tracks) {
125     metadata_vec.push_back({
126         .source = static_cast<audio_source_t>(metadata.source),
127         .gain = metadata.gain,
128     });
129   }
130   const sink_metadata_t legacy_sink_metadata = {
131       .track_count = metadata_vec.size(), .tracks = metadata_vec.data()};
132   transport_instance_->SinkMetadataChanged(legacy_sink_metadata);
133   return ndk::ScopedAStatus::ok();
134 }
135 
setLatencyMode(LatencyMode latency_mode)136 ndk::ScopedAStatus BluetoothAudioPortImpl::setLatencyMode(
137     LatencyMode latency_mode) {
138   bool is_low_latency = latency_mode == LatencyMode::LOW_LATENCY ? true : false;
139   invoke_switch_buffer_size_cb(is_low_latency);
140   transport_instance_->SetLowLatency(is_low_latency);
141   return ndk::ScopedAStatus::ok();
142 }
143 
timespec_convert_to_hal(const timespec & ts)144 PresentationPosition::TimeSpec BluetoothAudioPortImpl::timespec_convert_to_hal(
145     const timespec& ts) {
146   return {.tvSec = static_cast<int64_t>(ts.tv_sec),
147           .tvNSec = static_cast<int64_t>(ts.tv_nsec)};
148 }
149 
150 }  // namespace aidl
151 }  // namespace audio
152 }  // namespace bluetooth
153