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