/* * 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 "BTAudioProviderStub" #include "BluetoothAudioProvider.h" #include #include #include "A2dpOffloadCodecFactory.h" namespace aidl { namespace android { namespace hardware { namespace bluetooth { namespace audio { struct BluetoothAudioProviderContext { SessionType session_type; }; static void binderUnlinkedCallbackAidl(void* cookie) { LOG(INFO) << __func__; BluetoothAudioProviderContext* ctx = static_cast(cookie); delete ctx; } static void binderDiedCallbackAidl(void* cookie) { LOG(INFO) << __func__; BluetoothAudioProviderContext* ctx = static_cast(cookie); CHECK_NE(ctx, nullptr); BluetoothAudioSessionReport::OnSessionEnded(ctx->session_type); } BluetoothAudioProvider::BluetoothAudioProvider() { death_recipient_ = ::ndk::ScopedAIBinder_DeathRecipient( AIBinder_DeathRecipient_new(binderDiedCallbackAidl)); AIBinder_DeathRecipient_setOnUnlinked(death_recipient_.get(), binderUnlinkedCallbackAidl); } ndk::ScopedAStatus BluetoothAudioProvider::startSession( const std::shared_ptr& host_if, const AudioConfiguration& audio_config, const std::vector& latencyModes, DataMQDesc* _aidl_return) { if (host_if == nullptr) { *_aidl_return = DataMQDesc(); LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_) << " Illegal argument"; return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } latency_modes_ = latencyModes; audio_config_ = std::make_unique(audio_config); stack_iface_ = host_if; BluetoothAudioProviderContext* cookie = new BluetoothAudioProviderContext{session_type_}; AIBinder_linkToDeath(stack_iface_->asBinder().get(), death_recipient_.get(), cookie); LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_); onSessionReady(_aidl_return); return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus BluetoothAudioProvider::endSession() { LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_); if (stack_iface_ != nullptr) { BluetoothAudioSessionReport::OnSessionEnded(session_type_); AIBinder_unlinkToDeath(stack_iface_->asBinder().get(), death_recipient_.get(), this); } else { LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << " has NO session"; } stack_iface_ = nullptr; audio_config_ = nullptr; return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus BluetoothAudioProvider::streamStarted( BluetoothAudioStatus status) { if (stack_iface_ != nullptr) { LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ", status=" << toString(status); BluetoothAudioSessionReport::ReportControlStatus(session_type_, true, status); } else { LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_) << ", status=" << toString(status) << " has NO session"; } return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus BluetoothAudioProvider::streamSuspended( BluetoothAudioStatus status) { LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ", status=" << toString(status); if (stack_iface_ != nullptr) { BluetoothAudioSessionReport::ReportControlStatus(session_type_, false, status); } else { LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_) << ", status=" << toString(status) << " has NO session"; } return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus BluetoothAudioProvider::updateAudioConfiguration( const AudioConfiguration& audio_config) { if (stack_iface_ == nullptr || audio_config_ == nullptr) { LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << " has NO session"; return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } if (audio_config.getTag() != audio_config_->getTag()) { LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << " audio config type is not match"; return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } audio_config_ = std::make_unique(audio_config); BluetoothAudioSessionReport::ReportAudioConfigChanged(session_type_, *audio_config_); LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << " | audio_config=" << audio_config.toString(); return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus BluetoothAudioProvider::setLowLatencyModeAllowed( bool allowed) { if (stack_iface_ == nullptr) { LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << " has NO session"; return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } LOG(INFO) << __func__ << " - allowed " << allowed; BluetoothAudioSessionReport::ReportLowLatencyModeAllowedChanged( session_type_, allowed); return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus BluetoothAudioProvider::parseA2dpConfiguration( [[maybe_unused]] const CodecId& codec_id, [[maybe_unused]] const std::vector& configuration, [[maybe_unused]] CodecParameters* codec_parameters, [[maybe_unused]] A2dpStatus* _aidl_return) { LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << " is illegal"; return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } ndk::ScopedAStatus BluetoothAudioProvider::getA2dpConfiguration( [[maybe_unused]] const std::vector& remote_a2dp_capabilities, [[maybe_unused]] const A2dpConfigurationHint& hint, [[maybe_unused]] std::optional* _aidl_return) { LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << " is illegal"; return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } ndk::ScopedAStatus BluetoothAudioProvider::setCodecPriority( const ::aidl::android::hardware::bluetooth::audio::CodecId& in_codecId, int32_t in_priority) { /* TODO: Implement */ (void)in_codecId; (void)in_priority; return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); }; ndk::ScopedAStatus BluetoothAudioProvider::getLeAudioAseConfiguration( const std::optional>>& in_remoteSinkAudioCapabilities, const std::optional>>& in_remoteSourceAudioCapabilities, const std::vector< ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider:: LeAudioConfigurationRequirement>& in_requirements, std::vector<::aidl::android::hardware::bluetooth::audio:: IBluetoothAudioProvider::LeAudioAseConfigurationSetting>* _aidl_return) { /* TODO: Implement */ (void)in_remoteSinkAudioCapabilities; (void)in_remoteSourceAudioCapabilities; (void)in_requirements; (void)_aidl_return; return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); }; ndk::ScopedAStatus BluetoothAudioProvider::getLeAudioAseQosConfiguration( const ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider:: LeAudioAseQosConfigurationRequirement& in_qosRequirement, ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider:: LeAudioAseQosConfigurationPair* _aidl_return) { /* TODO: Implement */ (void)in_qosRequirement; (void)_aidl_return; return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); }; ndk::ScopedAStatus BluetoothAudioProvider::getLeAudioAseDatapathConfiguration( const std::optional<::aidl::android::hardware::bluetooth::audio:: IBluetoothAudioProvider::StreamConfig>& in_sinkConfig, const std::optional<::aidl::android::hardware::bluetooth::audio:: IBluetoothAudioProvider::StreamConfig>& in_sourceConfig, ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider:: LeAudioDataPathConfigurationPair* _aidl_return) { /* TODO: Implement */ (void)in_sinkConfig; (void)in_sourceConfig; (void)_aidl_return; return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); } ndk::ScopedAStatus BluetoothAudioProvider::onSinkAseMetadataChanged( ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider:: AseState in_state, int32_t cigId, int32_t cisId, const std::optional>>& in_metadata) { /* TODO: Implement */ (void)in_state; (void)cigId; (void)cisId; (void)in_metadata; return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); }; ndk::ScopedAStatus BluetoothAudioProvider::onSourceAseMetadataChanged( ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider:: AseState in_state, int32_t cigId, int32_t cisId, const std::optional>>& in_metadata) { /* TODO: Implement */ (void)in_state; (void)cigId; (void)cisId; (void)in_metadata; return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); }; ndk::ScopedAStatus BluetoothAudioProvider::getLeAudioBroadcastConfiguration( const std::optional>>& in_remoteSinkAudioCapabilities, const ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider:: LeAudioBroadcastConfigurationRequirement& in_requirement, ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider:: LeAudioBroadcastConfigurationSetting* _aidl_return) { /* TODO: Implement */ (void)in_remoteSinkAudioCapabilities; (void)in_requirement; (void)_aidl_return; return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); }; ndk::ScopedAStatus BluetoothAudioProvider::getLeAudioBroadcastDatapathConfiguration( const ::aidl::android::hardware::bluetooth::audio::AudioContext& in_context, const std::vector<::aidl::android::hardware::bluetooth::audio:: LeAudioBroadcastConfiguration::BroadcastStreamMap>& in_streamMap, ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider:: LeAudioDataPathConfiguration* _aidl_return) { /* TODO: Implement */ (void)in_context; (void)in_streamMap; (void)_aidl_return; return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); } } // namespace audio } // namespace bluetooth } // namespace hardware } // namespace android } // namespace aidl