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 #include "types/raw_address.h"
23
24 #define PARSE_ADDR(str) \
25 ({ \
26 RawAddress tmp; \
27 if (!RawAddress::FromString((str), tmp)) { \
28 LOG(ERROR) << "Invalid device address given: " << (str); \
29 return false; \
30 } \
31 tmp; \
32 })
33
34 #define TRY_RET(expr, err_msg) \
35 do { \
36 if (!(expr)) { \
37 LOG(ERROR) << err_msg; \
38 return false; \
39 } \
40 return true; \
41 } while (0)
42
43 #define TRY_RET_FUNC(expr) TRY_RET(expr, __func__ << " failed")
44
45 using bluetooth::hal::BluetoothAvInterface;
46 using LockGuard = std::lock_guard<std::mutex>;
47
48 namespace bluetooth {
49
50 namespace {
51
CodecConfigToFluoride(const A2dpCodecConfig & config)52 btav_a2dp_codec_config_t CodecConfigToFluoride(const A2dpCodecConfig& config) {
53 btav_a2dp_codec_config_t ret = {
54 .codec_type = static_cast<btav_a2dp_codec_index_t>(config.codec_type()),
55 .codec_priority =
56 static_cast<btav_a2dp_codec_priority_t>(config.codec_priority()),
57 .sample_rate =
58 static_cast<btav_a2dp_codec_sample_rate_t>(config.sample_rate()),
59 .bits_per_sample = static_cast<btav_a2dp_codec_bits_per_sample_t>(
60 config.bits_per_sample()),
61 .channel_mode =
62 static_cast<btav_a2dp_codec_channel_mode_t>(config.channel_mode()),
63 .codec_specific_1 = config.codec_specific_1(),
64 .codec_specific_2 = config.codec_specific_2(),
65 .codec_specific_3 = config.codec_specific_3(),
66 .codec_specific_4 = config.codec_specific_4(),
67 };
68
69 return ret;
70 }
71
CodecConfigsToFluoride(const std::vector<A2dpCodecConfig> & configs)72 std::vector<btav_a2dp_codec_config_t> CodecConfigsToFluoride(
73 const std::vector<A2dpCodecConfig>& configs) {
74 std::vector<btav_a2dp_codec_config_t> ret;
75 ret.reserve(configs.size());
76 for (const auto& config : configs) {
77 ret.push_back(CodecConfigToFluoride(config));
78 }
79
80 return ret;
81 }
FluorideCodecToCodec(const btav_a2dp_codec_config_t & config)82 A2dpCodecConfig FluorideCodecToCodec(const btav_a2dp_codec_config_t& config) {
83 A2dpCodecConfig ret(config.codec_type, config.codec_priority,
84 config.sample_rate, config.bits_per_sample,
85 config.channel_mode, config.codec_specific_1,
86 config.codec_specific_2, config.codec_specific_3,
87 config.codec_specific_4);
88
89 return ret;
90 }
91
FluorideCodecsToCodec(const std::vector<btav_a2dp_codec_config_t> & configs)92 std::vector<A2dpCodecConfig> FluorideCodecsToCodec(
93 const std::vector<btav_a2dp_codec_config_t>& configs) {
94 std::vector<A2dpCodecConfig> ret;
95 ret.reserve(configs.size());
96 for (const auto& config : configs) {
97 ret.push_back(FluorideCodecToCodec(config));
98 }
99
100 return ret;
101 }
102
103 } // namespace
104
105 // static
106 const int A2dpSource::kSingletonInstanceId = 0;
107
A2dpSource(const Uuid & uuid)108 A2dpSource::A2dpSource(const Uuid& uuid) : app_identifier_(uuid) {
109 hal::BluetoothAvInterface::Get()->AddA2dpSourceObserver(this);
110 }
111
~A2dpSource()112 A2dpSource::~A2dpSource() {
113 hal::BluetoothAvInterface::Get()->RemoveA2dpSourceObserver(this);
114 }
115
GetAppIdentifier() const116 const Uuid& A2dpSource::GetAppIdentifier() const { return app_identifier_; }
117
GetInstanceId() const118 int A2dpSource::GetInstanceId() const { return kSingletonInstanceId; }
119
SetDelegate(Delegate * delegate)120 void A2dpSource::SetDelegate(Delegate* delegate) {
121 LockGuard lock(delegate_mutex_);
122 delegate_ = delegate;
123 }
124
Enable(const std::vector<A2dpCodecConfig> & codec_priorities)125 bool A2dpSource::Enable(const std::vector<A2dpCodecConfig>& codec_priorities) {
126 auto fluoride_priorities = CodecConfigsToFluoride(codec_priorities);
127 LockGuard lock(mutex_);
128 return hal::BluetoothAvInterface::Get()->A2dpSourceEnable(
129 fluoride_priorities);
130 }
131
Disable()132 void A2dpSource::Disable() {
133 LockGuard lock(mutex_);
134 hal::BluetoothAvInterface::Get()->A2dpSourceDisable();
135 }
136
Connect(const std::string & device_address)137 bool A2dpSource::Connect(const std::string& device_address) {
138 RawAddress addr = PARSE_ADDR(device_address);
139 LockGuard lock(mutex_);
140 TRY_RET_FUNC(
141 hal::BluetoothAvInterface::Get()->GetA2dpSourceHALInterface()->connect(
142 addr) == BT_STATUS_SUCCESS);
143 }
144
Disconnect(const std::string & device_address)145 bool A2dpSource::Disconnect(const std::string& device_address) {
146 RawAddress addr = PARSE_ADDR(device_address);
147 LockGuard lock(mutex_);
148 TRY_RET_FUNC(
149 hal::BluetoothAvInterface::Get()->GetA2dpSourceHALInterface()->disconnect(
150 addr) == BT_STATUS_SUCCESS);
151 }
152
ConfigCodec(const std::string & device_address,const std::vector<A2dpCodecConfig> & codec_preferences)153 bool A2dpSource::ConfigCodec(
154 const std::string& device_address,
155 const std::vector<A2dpCodecConfig>& codec_preferences) {
156 RawAddress addr = PARSE_ADDR(device_address);
157 auto fluoride_preferences = CodecConfigsToFluoride(codec_preferences);
158 LockGuard lock(mutex_);
159 TRY_RET_FUNC(hal::BluetoothAvInterface::Get()
160 ->GetA2dpSourceHALInterface()
161 ->config_codec(addr, fluoride_preferences) ==
162 BT_STATUS_SUCCESS);
163 }
164
ConnectionStateCallback(BluetoothAvInterface * iface,const RawAddress & bd_addr,btav_connection_state_t state)165 void A2dpSource::ConnectionStateCallback(BluetoothAvInterface* iface,
166 const RawAddress& bd_addr,
167 btav_connection_state_t state) {
168 auto device_address = BtAddrString(&bd_addr);
169 LockGuard lock(delegate_mutex_);
170 if (delegate_)
171 delegate_->OnConnectionState(device_address, static_cast<int>(state));
172 }
173
AudioStateCallback(BluetoothAvInterface * iface,const RawAddress & bd_addr,btav_audio_state_t state)174 void A2dpSource::AudioStateCallback(BluetoothAvInterface* iface,
175 const RawAddress& bd_addr,
176 btav_audio_state_t state) {
177 auto device_address = BtAddrString(&bd_addr);
178 LockGuard lock(delegate_mutex_);
179 if (delegate_)
180 delegate_->OnAudioState(device_address, static_cast<int>(state));
181 }
182
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)183 void A2dpSource::AudioConfigCallback(
184 BluetoothAvInterface* iface, const RawAddress& bd_addr,
185 const btav_a2dp_codec_config_t& codec_config_fluoride,
186 const std::vector<btav_a2dp_codec_config_t>
187 codecs_local_capabilities_fluoride,
188 const std::vector<btav_a2dp_codec_config_t>
189 codecs_selectable_capabilities_fluoride) {
190 auto device_address = BtAddrString(&bd_addr);
191 auto codec_config = FluorideCodecToCodec(codec_config_fluoride);
192 auto codecs_local_capabilities =
193 FluorideCodecsToCodec(codecs_local_capabilities_fluoride);
194 auto codecs_selectable_capabilities =
195 FluorideCodecsToCodec(codecs_selectable_capabilities_fluoride);
196 LockGuard lock(delegate_mutex_);
197 if (delegate_)
198 delegate_->OnAudioConfig(device_address, codec_config,
199 codecs_local_capabilities,
200 codecs_selectable_capabilities);
201 }
202
MandatoryCodecPreferredCallback(BluetoothAvInterface * iface,const RawAddress & bd_addr)203 bool A2dpSource::MandatoryCodecPreferredCallback(BluetoothAvInterface* iface,
204 const RawAddress& bd_addr) {
205 LockGuard lock(delegate_mutex_);
206 // Do nothing. Optional codecs are preferred by default.
207 return false;
208 }
209
210 // A2dpSourceFactory implementation
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