2 // Copyright (C) 2017 Google, Inc.
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:
8 // http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "service/a2dp_source.h"
19 #include "base/logging.h"
20 #include "base/memory/ptr_util.h"
21 #include "service/logging_helpers.h"
23 #define PARSE_ADDR(str) \
26 if (!RawAddress::FromString((str), tmp)) { \
27 LOG(ERROR) << "Invalid device address given: " << (str); \
33 #define TRY_RET(expr, err_msg) \
36 LOG(ERROR) << err_msg; \
42 #define TRY_RET_FUNC(expr) TRY_RET(expr, __func__ << " failed")
44 using bluetooth::hal::BluetoothAvInterface;
45 using LockGuard = std::lock_guard<std::mutex>;
51 btav_a2dp_codec_config_t CodecConfigToFluoride(const A2dpCodecConfig& config) {
52 btav_a2dp_codec_config_t ret = {
53 .codec_type = static_cast<btav_a2dp_codec_index_t>(config.codec_type()),
55 static_cast<btav_a2dp_codec_priority_t>(config.codec_priority()),
57 static_cast<btav_a2dp_codec_sample_rate_t>(config.sample_rate()),
58 .bits_per_sample = static_cast<btav_a2dp_codec_bits_per_sample_t>(
59 config.bits_per_sample()),
61 static_cast<btav_a2dp_codec_channel_mode_t>(config.channel_mode()),
62 .codec_specific_1 = config.codec_specific_1(),
63 .codec_specific_2 = config.codec_specific_2(),
64 .codec_specific_3 = config.codec_specific_3(),
65 .codec_specific_4 = config.codec_specific_4(),
71 std::vector<btav_a2dp_codec_config_t> CodecConfigsToFluoride(
72 const std::vector<A2dpCodecConfig>& configs) {
73 std::vector<btav_a2dp_codec_config_t> ret;
74 ret.reserve(configs.size());
75 for (const auto& config : configs) {
76 ret.push_back(CodecConfigToFluoride(config));
81 A2dpCodecConfig FluorideCodecToCodec(const btav_a2dp_codec_config_t& config) {
82 A2dpCodecConfig ret(config.codec_type, config.codec_priority,
83 config.sample_rate, config.bits_per_sample,
84 config.channel_mode, config.codec_specific_1,
85 config.codec_specific_2, config.codec_specific_3,
86 config.codec_specific_4);
91 std::vector<A2dpCodecConfig> FluorideCodecsToCodec(
92 const std::vector<btav_a2dp_codec_config_t>& configs) {
93 std::vector<A2dpCodecConfig> ret;
94 ret.reserve(configs.size());
95 for (const auto& config : configs) {
96 ret.push_back(FluorideCodecToCodec(config));
105 const int A2dpSource::kSingletonInstanceId = 0;
107 A2dpSource::A2dpSource(const Uuid& uuid) : app_identifier_(uuid) {
108 hal::BluetoothAvInterface::Get()->AddA2dpSourceObserver(this);
111 A2dpSource::~A2dpSource() {
112 hal::BluetoothAvInterface::Get()->RemoveA2dpSourceObserver(this);
115 const Uuid& A2dpSource::GetAppIdentifier() const { return app_identifier_; }
117 int A2dpSource::GetInstanceId() const { return kSingletonInstanceId; }
119 void A2dpSource::SetDelegate(Delegate* delegate) {
120 LockGuard lock(delegate_mutex_);
121 delegate_ = delegate;
124 bool A2dpSource::Enable(const std::vector<A2dpCodecConfig>& codec_priorities) {
125 auto fluoride_priorities = CodecConfigsToFluoride(codec_priorities);
126 LockGuard lock(mutex_);
127 return hal::BluetoothAvInterface::Get()->A2dpSourceEnable(
128 fluoride_priorities);
131 void A2dpSource::Disable() {
132 LockGuard lock(mutex_);
133 hal::BluetoothAvInterface::Get()->A2dpSourceDisable();
136 bool A2dpSource::Connect(const std::string& device_address) {
137 RawAddress addr = PARSE_ADDR(device_address);
138 LockGuard lock(mutex_);
140 hal::BluetoothAvInterface::Get()->GetA2dpSourceHALInterface()->connect(
141 addr) == BT_STATUS_SUCCESS);
144 bool A2dpSource::Disconnect(const std::string& device_address) {
145 RawAddress addr = PARSE_ADDR(device_address);
146 LockGuard lock(mutex_);
148 hal::BluetoothAvInterface::Get()->GetA2dpSourceHALInterface()->disconnect(
149 addr) == BT_STATUS_SUCCESS);
152 bool A2dpSource::ConfigCodec(
153 const std::string& device_address,
154 const std::vector<A2dpCodecConfig>& codec_preferences) {
155 RawAddress addr = PARSE_ADDR(device_address);
156 auto fluoride_preferences = CodecConfigsToFluoride(codec_preferences);
157 LockGuard lock(mutex_);
158 TRY_RET_FUNC(hal::BluetoothAvInterface::Get()
159 ->GetA2dpSourceHALInterface()
160 ->config_codec(addr, fluoride_preferences) ==
164 void A2dpSource::ConnectionStateCallback(BluetoothAvInterface* iface,
165 const RawAddress& bd_addr,
166 btav_connection_state_t state) {
167 auto device_address = BtAddrString(&bd_addr);
168 LockGuard lock(delegate_mutex_);
170 delegate_->OnConnectionState(device_address, static_cast<int>(state));
173 void A2dpSource::AudioStateCallback(BluetoothAvInterface* iface,
174 const RawAddress& bd_addr,
175 btav_audio_state_t state) {
176 auto device_address = BtAddrString(&bd_addr);
177 LockGuard lock(delegate_mutex_);
179 delegate_->OnAudioState(device_address, static_cast<int>(state));
182 void A2dpSource::AudioConfigCallback(
183 BluetoothAvInterface* iface, const RawAddress& bd_addr,
184 const btav_a2dp_codec_config_t& codec_config_fluoride,
185 const std::vector<btav_a2dp_codec_config_t>
186 codecs_local_capabilities_fluoride,
187 const std::vector<btav_a2dp_codec_config_t>
188 codecs_selectable_capabilities_fluoride) {
189 auto device_address = BtAddrString(&bd_addr);
190 auto codec_config = FluorideCodecToCodec(codec_config_fluoride);
191 auto codecs_local_capabilities =
192 FluorideCodecsToCodec(codecs_local_capabilities_fluoride);
193 auto codecs_selectable_capabilities =
194 FluorideCodecsToCodec(codecs_selectable_capabilities_fluoride);
195 LockGuard lock(delegate_mutex_);
197 delegate_->OnAudioConfig(device_address, codec_config,
198 codecs_local_capabilities,
199 codecs_selectable_capabilities);
202 // A2dpSourceFactory implementation
203 // ========================================================
204 A2dpSourceFactory::A2dpSourceFactory() = default;
205 A2dpSourceFactory::~A2dpSourceFactory() = default;
207 bool A2dpSourceFactory::RegisterInstance(const Uuid& uuid,
208 const RegisterCallback& callback) {
209 VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
211 auto a2dp_source = base::WrapUnique(new A2dpSource(uuid));
212 callback(BLE_STATUS_SUCCESS, uuid, std::move(a2dp_source));
216 } // namespace bluetooth