blob: 9e77007f13bd8aa85c60f61ed006723dd3277285 [file] [log] [blame]
Bailey Forrest780e29c2018-08-21 17:20:29 -07001//
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
44using bluetooth::hal::BluetoothAvInterface;
45using LockGuard = std::lock_guard<std::mutex>;
46
47namespace bluetooth {
48
49namespace {
50
51btav_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
71std::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}
81A2dpCodecConfig 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
91std::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
105const int A2dpSource::kSingletonInstanceId = 0;
106
107A2dpSource::A2dpSource(const Uuid& uuid) : app_identifier_(uuid) {
108 hal::BluetoothAvInterface::Get()->AddA2dpSourceObserver(this);
109}
110
111A2dpSource::~A2dpSource() {
112 hal::BluetoothAvInterface::Get()->RemoveA2dpSourceObserver(this);
113}
114
115const Uuid& A2dpSource::GetAppIdentifier() const { return app_identifier_; }
116
117int A2dpSource::GetInstanceId() const { return kSingletonInstanceId; }
118
119void A2dpSource::SetDelegate(Delegate* delegate) {
120 LockGuard lock(delegate_mutex_);
121 delegate_ = delegate;
122}
123
124bool 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
131void A2dpSource::Disable() {
132 LockGuard lock(mutex_);
133 hal::BluetoothAvInterface::Get()->A2dpSourceDisable();
134}
135
136bool 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
144bool 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
152bool 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
164void 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
173void 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
182void 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
202// A2dpSourceFactory implementation
203// ========================================================
204A2dpSourceFactory::A2dpSourceFactory() = default;
205A2dpSourceFactory::~A2dpSourceFactory() = default;
206
207bool A2dpSourceFactory::RegisterInstance(const Uuid& uuid,
208 const RegisterCallback& callback) {
209 VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
210
211 auto a2dp_source = base::WrapUnique(new A2dpSource(uuid));
212 callback(BLE_STATUS_SUCCESS, uuid, std::move(a2dp_source));
213 return true;
214}
215
216} // namespace bluetooth