1 //
2 // Copyright (C) 2017 Google, Inc.
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 "service/a2dp_source.h"
18
19 #include "base/logging.h"
20 #include "base/memory/ptr_util.h"
21 #include "service/logging_helpers.h"
22
23 #define PARSE_ADDR(str) \
24 ({ \
25 RawAddress tmp; \
26 if (!RawAddress::FromString((str), tmp)) { \
27 LOG(ERROR) << "Invalid device address given: " << (str); \
28 return false; \
29 } \
30 tmp; \
31 })
32
33 #define TRY_RET(expr, err_msg) \
34 do { \
35 if (!(expr)) { \
36 LOG(ERROR) << err_msg; \
37 return false; \
38 } \
39 return true; \
40 } while (0)
41
42 #define TRY_RET_FUNC(expr) TRY_RET(expr, __func__ << " failed")
43
44 using bluetooth::hal::BluetoothAvInterface;
45 using LockGuard = std::lock_guard<std::mutex>;
46
47 namespace bluetooth {
48
49 namespace {
50
CodecConfigToFluoride(const A2dpCodecConfig & config)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()),
54 .codec_priority =
55 static_cast<btav_a2dp_codec_priority_t>(config.codec_priority()),
56 .sample_rate =
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()),
60 .channel_mode =
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(),
66 };
67
68 return ret;
69 }
70
CodecConfigsToFluoride(const std::vector<A2dpCodecConfig> & configs)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));
77 }
78
79 return ret;
80 }
FluorideCodecToCodec(const btav_a2dp_codec_config_t & 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);
87
88 return ret;
89 }
90
FluorideCodecsToCodec(const std::vector<btav_a2dp_codec_config_t> & configs)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));
97 }
98
99 return ret;
100 }
101
102 } // namespace
103
104 // static
105 const int A2dpSource::kSingletonInstanceId = 0;
106
A2dpSource(const Uuid & uuid)107 A2dpSource::A2dpSource(const Uuid& uuid) : app_identifier_(uuid) {
108 hal::BluetoothAvInterface::Get()->AddA2dpSourceObserver(this);
109 }
110
~A2dpSource()111 A2dpSource::~A2dpSource() {
112 hal::BluetoothAvInterface::Get()->RemoveA2dpSourceObserver(this);
113 }
114
GetAppIdentifier() const115 const Uuid& A2dpSource::GetAppIdentifier() const { return app_identifier_; }
116
GetInstanceId() const117 int A2dpSource::GetInstanceId() const { return kSingletonInstanceId; }
118
SetDelegate(Delegate * delegate)119 void A2dpSource::SetDelegate(Delegate* delegate) {
120 LockGuard lock(delegate_mutex_);
121 delegate_ = delegate;
122 }
123
Enable(const std::vector<A2dpCodecConfig> & codec_priorities)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);
129 }
130
Disable()131 void A2dpSource::Disable() {
132 LockGuard lock(mutex_);
133 hal::BluetoothAvInterface::Get()->A2dpSourceDisable();
134 }
135
Connect(const std::string & device_address)136 bool A2dpSource::Connect(const std::string& device_address) {
137 RawAddress addr = PARSE_ADDR(device_address);
138 LockGuard lock(mutex_);
139 TRY_RET_FUNC(
140 hal::BluetoothAvInterface::Get()->GetA2dpSourceHALInterface()->connect(
141 addr) == BT_STATUS_SUCCESS);
142 }
143
Disconnect(const std::string & device_address)144 bool A2dpSource::Disconnect(const std::string& device_address) {
145 RawAddress addr = PARSE_ADDR(device_address);
146 LockGuard lock(mutex_);
147 TRY_RET_FUNC(
148 hal::BluetoothAvInterface::Get()->GetA2dpSourceHALInterface()->disconnect(
149 addr) == BT_STATUS_SUCCESS);
150 }
151
ConfigCodec(const std::string & device_address,const std::vector<A2dpCodecConfig> & codec_preferences)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) ==
161 BT_STATUS_SUCCESS);
162 }
163
ConnectionStateCallback(BluetoothAvInterface * iface,const RawAddress & bd_addr,btav_connection_state_t state)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_);
169 if (delegate_)
170 delegate_->OnConnectionState(device_address, static_cast<int>(state));
171 }
172
AudioStateCallback(BluetoothAvInterface * iface,const RawAddress & bd_addr,btav_audio_state_t 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_);
178 if (delegate_)
179 delegate_->OnAudioState(device_address, static_cast<int>(state));
180 }
181
AudioConfigCallback(BluetoothAvInterface * iface,const RawAddress & bd_addr,const btav_a2dp_codec_config_t & codec_config_fluoride,const std::vector<btav_a2dp_codec_config_t> codecs_local_capabilities_fluoride,const std::vector<btav_a2dp_codec_config_t> codecs_selectable_capabilities_fluoride)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_);
196 if (delegate_)
197 delegate_->OnAudioConfig(device_address, codec_config,
198 codecs_local_capabilities,
199 codecs_selectable_capabilities);
200 }
201
MandatoryCodecPreferredCallback(BluetoothAvInterface * iface,const RawAddress & bd_addr)202 bool A2dpSource::MandatoryCodecPreferredCallback(BluetoothAvInterface* iface,
203 const RawAddress& bd_addr) {
204 LockGuard lock(delegate_mutex_);
205 // Do nothing. Optional codecs are preferred by default.
206 return false;
207 }
208
209 // A2dpSourceFactory implementation
210 // ========================================================
211 A2dpSourceFactory::A2dpSourceFactory() = default;
212 A2dpSourceFactory::~A2dpSourceFactory() = default;
213
RegisterInstance(const Uuid & uuid,const RegisterCallback & callback)214 bool A2dpSourceFactory::RegisterInstance(const Uuid& uuid,
215 const RegisterCallback& callback) {
216 VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
217
218 auto a2dp_source = base::WrapUnique(new A2dpSource(uuid));
219 callback(BLE_STATUS_SUCCESS, uuid, std::move(a2dp_source));
220 return true;
221 }
222
223 } // namespace bluetooth
224