/* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "BTAudioProviderFactoryAIDL" #include "BluetoothAudioProviderFactory.h" #include #include #include "A2dpOffloadAudioProvider.h" #include "A2dpSoftwareAudioProvider.h" #include "BluetoothAudioProvider.h" #include "HearingAidAudioProvider.h" #include "HfpOffloadAudioProvider.h" #include "HfpSoftwareAudioProvider.h" #include "LeAudioOffloadAudioProvider.h" #include "LeAudioSoftwareAudioProvider.h" namespace aidl { namespace android { namespace hardware { namespace bluetooth { namespace audio { static const std::string kLeAudioOffloadProviderName = "LE_AUDIO_OFFLOAD_HARDWARE_OFFLOAD_PROVIDER"; static const std::string kHfpOffloadProviderName = "HFP_OFFLOAD_HARDWARE_OFFLOAD_PROVIDER"; BluetoothAudioProviderFactory::BluetoothAudioProviderFactory() {} ndk::ScopedAStatus BluetoothAudioProviderFactory::openProvider( const SessionType session_type, std::shared_ptr* _aidl_return) { LOG(INFO) << __func__ << " - SessionType=" << toString(session_type); std::shared_ptr provider = nullptr; switch (session_type) { case SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH: provider = ndk::SharedRefBase::make(); break; case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH: provider = ndk::SharedRefBase::make( a2dp_offload_codec_factory_); break; case SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH: provider = ndk::SharedRefBase::make(); break; case SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH: provider = ndk::SharedRefBase::make(); break; case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH: provider = ndk::SharedRefBase::make(); break; case SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH: provider = ndk::SharedRefBase::make(); break; case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH: provider = ndk::SharedRefBase::make(); break; case SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH: provider = ndk::SharedRefBase::make(); break; case SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH: provider = ndk::SharedRefBase::make(); break; case SessionType::A2DP_SOFTWARE_DECODING_DATAPATH: provider = ndk::SharedRefBase::make(); break; case SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH: provider = ndk::SharedRefBase::make( a2dp_offload_codec_factory_); break; case SessionType::HFP_SOFTWARE_ENCODING_DATAPATH: provider = ndk::SharedRefBase::make(); break; case SessionType::HFP_SOFTWARE_DECODING_DATAPATH: provider = ndk::SharedRefBase::make(); break; case SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH: provider = ndk::SharedRefBase::make(); break; default: provider = nullptr; break; } if (provider == nullptr || !provider->isValid(session_type)) { provider = nullptr; LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type); return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } *_aidl_return = provider; return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus BluetoothAudioProviderFactory::getProviderCapabilities( const SessionType session_type, std::vector* _aidl_return) { if (session_type == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH || session_type == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) { auto codec_capabilities = BluetoothAudioCodecs::GetA2dpOffloadCodecCapabilities(session_type); _aidl_return->resize(codec_capabilities.size()); for (int i = 0; i < codec_capabilities.size(); i++) { _aidl_return->at(i).set( codec_capabilities[i]); } } else if (session_type == SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH || session_type == SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH || session_type == SessionType:: LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) { std::vector db_codec_capabilities = BluetoothAudioCodecs::GetLeAudioOffloadCodecCapabilities(session_type); if (db_codec_capabilities.size()) { _aidl_return->resize(db_codec_capabilities.size()); for (int i = 0; i < db_codec_capabilities.size(); ++i) { _aidl_return->at(i).set( db_codec_capabilities[i]); } } } else if (session_type != SessionType::UNKNOWN) { auto pcm_capabilities = BluetoothAudioCodecs::GetSoftwarePcmCapabilities(); _aidl_return->resize(pcm_capabilities.size()); for (int i = 0; i < pcm_capabilities.size(); i++) { _aidl_return->at(i).set( pcm_capabilities[i]); } } LOG(INFO) << __func__ << " - SessionType=" << toString(session_type) << " supports " << _aidl_return->size() << " codecs"; return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus BluetoothAudioProviderFactory::getProviderInfo( SessionType session_type, std::optional* _aidl_return) { *_aidl_return = std::nullopt; LOG(INFO) << __func__ << " - SessionType=" << toString(session_type); if (session_type == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH || session_type == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) { if (!kEnableA2dpCodecExtensibility) { // Implementing getProviderInfo equates supporting // A2dp codec extensibility. return ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_TRANSACTION); } auto& provider_info = _aidl_return->emplace(); provider_info.name = a2dp_offload_codec_factory_.name; for (auto codec : a2dp_offload_codec_factory_.codecs) provider_info.codecInfos.push_back(codec->info); return ndk::ScopedAStatus::ok(); } if (session_type == SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH || session_type == SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH || session_type == SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) { std::vector db_codec_info = BluetoothAudioCodecs::GetLeAudioOffloadCodecInfo(session_type); // Return provider info supports without checking db_codec_info // This help with various flow implementation for multidirectional support. auto& provider_info = _aidl_return->emplace(); provider_info.supportsMultidirectionalCapabilities = true; provider_info.name = kLeAudioOffloadProviderName; provider_info.codecInfos = db_codec_info; return ndk::ScopedAStatus::ok(); } if (session_type == SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH) { std::vector db_codec_info = BluetoothAudioCodecs::GetHfpOffloadCodecInfo(); if (!db_codec_info.empty()) { auto& provider_info = _aidl_return->emplace(); provider_info.name = kHfpOffloadProviderName; provider_info.codecInfos = db_codec_info; return ndk::ScopedAStatus::ok(); } } // Unsupported for other sessions return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); } } // namespace audio } // namespace bluetooth } // namespace hardware } // namespace android } // namespace aidl