// // Copyright (C) 2017 Google, Inc. // // 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. // #include "service/ipc/binder/bluetooth_a2dp_source_binder_server.h" #include <base/logging.h> #include "service/adapter.h" #define AIDL_RET(value) \ do { \ *_aidl_return = (value); \ return Status::ok(); \ } while (0) #define TRY_GET_SOURCE() \ ({ \ auto source = GetA2dpSource(); \ if (!source) { \ LOG(ERROR) << __func__ << ": " \ << "Failed to get A2DP source interface"; \ AIDL_RET(false); \ } \ source; \ }) #define TRY_GET_CB() \ ({ \ auto cb = GetA2dpSourceCallback(); \ if (!cb.get()) { \ LOG(WARNING) << "Callback for A2DP SOURCE was deleted"; \ return; \ } \ cb; \ }) #define TRY_RET(expr, msg) \ do { \ if (!(expr)) { \ LOG(ERROR) << msg; \ AIDL_RET(false); \ } \ AIDL_RET(true); \ } while (0) #define TRY_RET_FUNC(expr) TRY_RET(expr, __func__ << " failed") using android::String16; using android::String8; using android::binder::Status; using android::bluetooth::BluetoothA2dpCodecConfig; using android::bluetooth::IBluetoothA2dpSourceCallback; using LockGuard = std::lock_guard<std::mutex>; namespace ipc { namespace binder { namespace { std::vector<bluetooth::A2dpCodecConfig> A2dpCodecsFromBinder( const std::vector<BluetoothA2dpCodecConfig>& codecs) { std::vector<bluetooth::A2dpCodecConfig> ret; ret.reserve(codecs.size()); for (const auto& config : codecs) { ret.push_back(config); } return ret; } std::vector<BluetoothA2dpCodecConfig> A2dpCodecsToBinder( const std::vector<bluetooth::A2dpCodecConfig>& codecs) { std::vector<BluetoothA2dpCodecConfig> ret; ret.reserve(codecs.size()); for (const auto& config : codecs) { ret.push_back(config); } return ret; } } // namespace BluetoothA2dpSourceBinderServer::BluetoothA2dpSourceBinderServer( bluetooth::Adapter* adapter) : adapter_(adapter) { CHECK(adapter); } BluetoothA2dpSourceBinderServer::~BluetoothA2dpSourceBinderServer() = default; bool BluetoothA2dpSourceBinderServer::HasInstance() { return GetA2dpSource() != nullptr; } Status BluetoothA2dpSourceBinderServer::Register( const android::sp<IBluetoothA2dpSourceCallback>& callback, bool* _aidl_return) { auto factory = adapter_->GetA2dpSourceFactory(); *_aidl_return = RegisterInstanceBase(callback, factory); return Status::ok(); } Status BluetoothA2dpSourceBinderServer::Unregister() { UnregisterAllBase(); return Status::ok(); } Status BluetoothA2dpSourceBinderServer::Enable( const std::vector<android::bluetooth::BluetoothA2dpCodecConfig>& codec_priorities, bool* _aidl_return) { auto codec_priorities_non_binder = A2dpCodecsFromBinder(codec_priorities); LockGuard lock(*maps_lock()); auto a2dp_source = TRY_GET_SOURCE(); TRY_RET_FUNC(a2dp_source->Enable(codec_priorities_non_binder)); } Status BluetoothA2dpSourceBinderServer::Disable(bool* _aidl_return) { LockGuard lock(*maps_lock()); auto a2dp_source = TRY_GET_SOURCE(); a2dp_source->Disable(); AIDL_RET(true); } Status BluetoothA2dpSourceBinderServer::Connect(const String16& device_address, bool* _aidl_return) { LockGuard lock(*maps_lock()); auto a2dp_source = TRY_GET_SOURCE(); TRY_RET_FUNC(a2dp_source->Connect(String8(device_address).string())); } Status BluetoothA2dpSourceBinderServer::Disconnect( const String16& device_address, bool* _aidl_return) { LockGuard lock(*maps_lock()); auto a2dp_source = TRY_GET_SOURCE(); TRY_RET_FUNC(a2dp_source->Disconnect(String8(device_address).string())); } Status BluetoothA2dpSourceBinderServer::ConfigCodec( const android::String16& device_address, const std::vector<android::bluetooth::BluetoothA2dpCodecConfig>& codec_preferences, bool* _aidl_return) { auto codec_preferences_non_binder = A2dpCodecsFromBinder(codec_preferences); LockGuard lock(*maps_lock()); auto a2dp_source = TRY_GET_SOURCE(); TRY_RET_FUNC(a2dp_source->ConfigCodec(String8(device_address).string(), codec_preferences_non_binder)); } void BluetoothA2dpSourceBinderServer::OnConnectionState( const std::string& device_address, int state) { LockGuard lock(*maps_lock()); auto cb = TRY_GET_CB(); cb->OnConnectionState(String16(device_address.c_str()), state); } void BluetoothA2dpSourceBinderServer::OnAudioState( const std::string& device_address, int state) { LockGuard lock(*maps_lock()); auto cb = TRY_GET_CB(); cb->OnAudioState(String16(device_address.c_str()), state); } void BluetoothA2dpSourceBinderServer::OnAudioConfig( const std::string& device_address, bluetooth::A2dpCodecConfig codec_config, const std::vector<bluetooth::A2dpCodecConfig>& codecs_local_capabilities, const std::vector<bluetooth::A2dpCodecConfig>& codecs_selectable_capabilities) { auto binder_codecs_local_capabilities = A2dpCodecsToBinder(codecs_local_capabilities); auto binder_codecs_selectable_capabilities = A2dpCodecsToBinder(codecs_selectable_capabilities); LockGuard lock(*maps_lock()); auto cb = TRY_GET_CB(); cb->OnAudioConfig(String16(device_address.c_str()), codec_config, binder_codecs_local_capabilities, binder_codecs_selectable_capabilities); } android::sp<IBluetoothA2dpSourceCallback> BluetoothA2dpSourceBinderServer::GetA2dpSourceCallback() { auto cb = GetCallback(bluetooth::A2dpSource::kSingletonInstanceId); return android::sp<IBluetoothA2dpSourceCallback>( static_cast<IBluetoothA2dpSourceCallback*>(cb.get())); } std::shared_ptr<bluetooth::A2dpSource> BluetoothA2dpSourceBinderServer::GetA2dpSource() { return std::static_pointer_cast<bluetooth::A2dpSource>( GetInstance(bluetooth::A2dpSource::kSingletonInstanceId)); } void BluetoothA2dpSourceBinderServer::OnRegisterInstanceImpl( bluetooth::BLEStatus status, android::sp<IInterface> callback, bluetooth::BluetoothInstance* instance) { VLOG(1) << __func__ << " instance ID: " << instance->GetInstanceId() << " status: " << status; bluetooth::A2dpSource* a2dp_source = static_cast<bluetooth::A2dpSource*>(instance); a2dp_source->SetDelegate(this); android::sp<IBluetoothA2dpSourceCallback> cb( static_cast<IBluetoothA2dpSourceCallback*>(callback.get())); cb->OnRegistered(status); } } // namespace binder } // namespace ipc