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 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 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 } 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 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 107 A2dpSource::A2dpSource(const Uuid& uuid) : app_identifier_(uuid) { 108 hal::BluetoothAvInterface::Get()->AddA2dpSourceObserver(this); 109 } 110 111 A2dpSource::~A2dpSource() { 112 hal::BluetoothAvInterface::Get()->RemoveA2dpSourceObserver(this); 113 } 114 115 const Uuid& A2dpSource::GetAppIdentifier() const { return app_identifier_; } 116 117 int A2dpSource::GetInstanceId() const { return kSingletonInstanceId; } 118 119 void A2dpSource::SetDelegate(Delegate* delegate) { 120 LockGuard lock(delegate_mutex_); 121 delegate_ = delegate; 122 } 123 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 131 void A2dpSource::Disable() { 132 LockGuard lock(mutex_); 133 hal::BluetoothAvInterface::Get()->A2dpSourceDisable(); 134 } 135 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 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 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 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 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 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 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 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