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 <bluetooth/log.h>
20 #include <com_android_bluetooth_flags.h>
21 
22 #include <vector>
23 
24 #include "android/binder_ibinder_platform.h"
25 #include "btif/include/btif_common.h"
26 #include "common/stop_watch_legacy.h"
27 
28 namespace bluetooth {
29 namespace audio {
30 namespace aidl {
31 
32 using ::bluetooth::common::StopWatchLegacy;
33 
BluetoothAudioPortImpl(IBluetoothTransportInstance * transport_instance,const std::shared_ptr<IBluetoothAudioProvider> & provider)34 BluetoothAudioPortImpl::BluetoothAudioPortImpl(
35     IBluetoothTransportInstance* transport_instance,
36     const std::shared_ptr<IBluetoothAudioProvider>& provider)
37     : transport_instance_(transport_instance), provider_(provider) {}
38 
~BluetoothAudioPortImpl()39 BluetoothAudioPortImpl::~BluetoothAudioPortImpl() {}
40 
startStream(bool is_low_latency)41 ndk::ScopedAStatus BluetoothAudioPortImpl::startStream(bool is_low_latency) {
42   StopWatchLegacy stop_watch(__func__);
43   BluetoothAudioCtrlAck ack = transport_instance_->StartRequest(is_low_latency);
44   if (ack != BluetoothAudioCtrlAck::PENDING) {
45     auto aidl_retval =
46         provider_->streamStarted(BluetoothAudioCtrlAckToHalStatus(ack));
47     if (!aidl_retval.isOk()) {
48       log::error("BluetoothAudioHal failure: {}", aidl_retval.getDescription());
49     }
50   }
51   return ndk::ScopedAStatus::ok();
52 }
53 
suspendStream()54 ndk::ScopedAStatus BluetoothAudioPortImpl::suspendStream() {
55   StopWatchLegacy stop_watch(__func__);
56   BluetoothAudioCtrlAck ack = transport_instance_->SuspendRequest();
57   if (ack != BluetoothAudioCtrlAck::PENDING) {
58     auto aidl_retval =
59         provider_->streamSuspended(BluetoothAudioCtrlAckToHalStatus(ack));
60     if (!aidl_retval.isOk()) {
61       log::error("BluetoothAudioHal failure: {}", aidl_retval.getDescription());
62     }
63   }
64   return ndk::ScopedAStatus::ok();
65 }
66 
stopStream()67 ndk::ScopedAStatus BluetoothAudioPortImpl::stopStream() {
68   StopWatchLegacy stop_watch(__func__);
69   transport_instance_->StopRequest();
70   return ndk::ScopedAStatus::ok();
71 }
72 
getPresentationPosition(PresentationPosition * _aidl_return)73 ndk::ScopedAStatus BluetoothAudioPortImpl::getPresentationPosition(
74     PresentationPosition* _aidl_return) {
75   StopWatchLegacy stop_watch(__func__);
76   uint64_t remote_delay_report_ns;
77   uint64_t total_bytes_read;
78   timespec data_position;
79   bool retval = transport_instance_->GetPresentationPosition(
80       &remote_delay_report_ns, &total_bytes_read, &data_position);
81 
82   PresentationPosition::TimeSpec transmittedOctetsTimeStamp;
83   if (retval) {
84     transmittedOctetsTimeStamp = timespec_convert_to_hal(data_position);
85   } else {
86     remote_delay_report_ns = 0;
87     total_bytes_read = 0;
88     transmittedOctetsTimeStamp = {};
89   }
90   log::verbose("result={}, delay={}, data={} byte(s), timestamp={}", retval,
91                remote_delay_report_ns, total_bytes_read,
92                transmittedOctetsTimeStamp.toString());
93   _aidl_return->remoteDeviceAudioDelayNanos =
94       static_cast<int64_t>(remote_delay_report_ns);
95   _aidl_return->transmittedOctets = static_cast<int64_t>(total_bytes_read);
96   _aidl_return->transmittedOctetsTimestamp = transmittedOctetsTimeStamp;
97   return ndk::ScopedAStatus::ok();
98 }
99 
updateSourceMetadata(const SourceMetadata & source_metadata)100 ndk::ScopedAStatus BluetoothAudioPortImpl::updateSourceMetadata(
101     const SourceMetadata& source_metadata) {
102   StopWatchLegacy stop_watch(__func__);
103   log::info("{} track(s)", source_metadata.tracks.size());
104 
105   std::vector<playback_track_metadata_v7> tracks_vec;
106   tracks_vec.reserve(source_metadata.tracks.size());
107   for (const auto& track : source_metadata.tracks) {
108     auto num_of_tags = track.tags.size();
109     log::info("metadata tags size: {}", num_of_tags);
110 
111     playback_track_metadata_v7 desc_track = {
112         .base = {.usage = static_cast<audio_usage_t>(track.usage),
113                  .content_type =
114                      static_cast<audio_content_type_t>(track.contentType),
115                  .gain = track.gain},
116     };
117 
118     if (num_of_tags != 0) {
119       int copied_size = 0;
120       int max_tags_size = sizeof(desc_track.tags);
121       std::string separator(1, AUDIO_ATTRIBUTES_TAGS_SEPARATOR);
122       for (size_t i = 0; i < num_of_tags - 1; i++) {
123         int string_len = track.tags[i].length();
124 
125         if ((copied_size >= max_tags_size) ||
126             (copied_size + string_len >= max_tags_size)) {
127           log::error("Too many tags, copied size: {}", copied_size);
128           break;
129         }
130 
131         track.tags[i].copy(desc_track.tags + copied_size, string_len, 0);
132         copied_size += string_len;
133         separator.copy(desc_track.tags + copied_size, 1, 0);
134         copied_size += 1;
135       }
136 
137       int string_len = track.tags[num_of_tags - 1].length();
138       if ((copied_size >= max_tags_size) ||
139           (copied_size + string_len >= max_tags_size)) {
140         log::error("Too many tags, copied size: {}", copied_size);
141       } else {
142         track.tags[num_of_tags - 1].copy(desc_track.tags + copied_size,
143                                          string_len, 0);
144       }
145     } else {
146       memset(desc_track.tags, 0, sizeof(desc_track.tags));
147     }
148 
149     tracks_vec.push_back(desc_track);
150   }
151 
152   const source_metadata_v7_t legacy_source_metadata = {
153       .track_count = tracks_vec.size(), .tracks = tracks_vec.data()};
154   transport_instance_->SourceMetadataChanged(legacy_source_metadata);
155   return ndk::ScopedAStatus::ok();
156 }
157 
updateSinkMetadata(const SinkMetadata & sink_metadata)158 ndk::ScopedAStatus BluetoothAudioPortImpl::updateSinkMetadata(
159     const SinkMetadata& sink_metadata) {
160   StopWatchLegacy stop_watch(__func__);
161   log::info("{} track(s)", sink_metadata.tracks.size());
162 
163   std::vector<record_track_metadata_v7> tracks_vec;
164   tracks_vec.reserve(sink_metadata.tracks.size());
165   for (const auto& track : sink_metadata.tracks) {
166     auto num_of_tags = track.tags.size();
167     log::info("metadata tags size: {}", num_of_tags);
168 
169     record_track_metadata_v7 desc_track = {
170         .base =
171             {
172                 .source = static_cast<audio_source_t>(track.source),
173                 .gain = track.gain,
174             },
175     };
176 
177     if (num_of_tags != 0) {
178       int copied_size = 0;
179       int max_tags_size = sizeof(desc_track.tags);
180       std::string separator(1, AUDIO_ATTRIBUTES_TAGS_SEPARATOR);
181       for (size_t i = 0; i < num_of_tags - 1; i++) {
182         int string_len = track.tags[i].length();
183 
184         if ((copied_size >= max_tags_size) ||
185             (copied_size + string_len >= max_tags_size)) {
186           log::error("Too many tags, copied size: {}", copied_size);
187           break;
188         }
189 
190         track.tags[i].copy(desc_track.tags + copied_size, string_len, 0);
191         copied_size += string_len;
192         separator.copy(desc_track.tags + copied_size, 1, 0);
193         copied_size += 1;
194       }
195 
196       int string_len = track.tags[num_of_tags - 1].length();
197       if ((copied_size >= max_tags_size) ||
198           (copied_size + string_len >= max_tags_size)) {
199         log::error("Too many tags, copied size: {}", copied_size);
200       } else {
201         track.tags[num_of_tags - 1].copy(desc_track.tags + copied_size,
202                                          string_len, 0);
203       }
204     } else {
205       memset(desc_track.tags, 0, sizeof(desc_track.tags));
206     }
207 
208     tracks_vec.push_back(desc_track);
209   }
210 
211   const sink_metadata_v7_t legacy_sink_metadata = {
212       .track_count = tracks_vec.size(), .tracks = tracks_vec.data()};
213   transport_instance_->SinkMetadataChanged(legacy_sink_metadata);
214   return ndk::ScopedAStatus::ok();
215 }
216 
setLatencyMode(LatencyMode latency_mode)217 ndk::ScopedAStatus BluetoothAudioPortImpl::setLatencyMode(
218     LatencyMode latency_mode) {
219   bool is_low_latency = latency_mode == LatencyMode::LOW_LATENCY ? true : false;
220   invoke_switch_buffer_size_cb(is_low_latency);
221   transport_instance_->SetLatencyMode(latency_mode);
222   return ndk::ScopedAStatus::ok();
223 }
224 
timespec_convert_to_hal(const timespec & ts)225 PresentationPosition::TimeSpec BluetoothAudioPortImpl::timespec_convert_to_hal(
226     const timespec& ts) {
227   return {.tvSec = static_cast<int64_t>(ts.tv_sec),
228           .tvNSec = static_cast<int64_t>(ts.tv_nsec)};
229 }
230 
231 // Overriding create binder and inherit RT from caller.
232 // In our case, the caller is the AIDL session control, so we match the priority
233 // of the AIDL session / AudioFlinger writer thread.
createBinder()234 ndk::SpAIBinder BluetoothAudioPortImpl::createBinder() {
235   auto binder = BnBluetoothAudioPort::createBinder();
236   if (com::android::bluetooth::flags::audio_port_binder_inherit_rt()) {
237     AIBinder_setInheritRt(binder.get(), true);
238   }
239   return binder;
240 }
241 
242 }  // namespace aidl
243 }  // namespace audio
244 }  // namespace bluetooth
245