// Copyright 2016 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. // // Implementation of brillo_audio_client.h #include "brillo_audio_client.h" #include #include #include #include "brillo_audio_client_helpers.h" #include "brillo_audio_device_info_def.h" #include "brillo_audio_device_info_internal.h" using android::binder::Status; namespace brillo { static const char kBrilloAudioServiceName[] = "android.brillo.brilloaudioservice.BrilloAudioService"; std::shared_ptr BrilloAudioClient::instance_ = nullptr; int BrilloAudioClient::callback_id_counter_ = 1; BrilloAudioClient::~BrilloAudioClient() {} std::weak_ptr BrilloAudioClient::GetClientInstance() { if (!instance_) { instance_ = std::shared_ptr(new BrilloAudioClient()); if (!instance_->Initialize()) { LOG(ERROR) << "Could not Initialize the brillo audio client."; instance_.reset(); return instance_; } } return instance_; } android::sp BrilloAudioClient::ConnectToService( const std::string& service_name, const base::Closure& callback) { android::BinderWrapper* binder_wrapper = android::BinderWrapper::GetOrCreateInstance(); auto service = binder_wrapper->GetService(service_name); if (!service.get()) { return service; } binder_wrapper->RegisterForDeathNotifications(service, callback); return service; } void BrilloAudioClient::OnBASDisconnect() { LOG(WARNING) << "The brillo audio service died! Please reset the " << "BAudioManager."; instance_.reset(); } bool BrilloAudioClient::Initialize() { auto service = ConnectToService( kBrilloAudioServiceName, base::Bind(&BrilloAudioClient::OnBASDisconnect, weak_ptr_factory_.GetWeakPtr())); if (!service.get()) { LOG(ERROR) << "Could not connect to brillo audio service."; return false; } brillo_audio_service_ = android::interface_cast(service); return true; } int BrilloAudioClient::GetDevices(int flag, std::vector& devices) { if (!brillo_audio_service_.get()) { OnBASDisconnect(); return ECONNABORTED; } auto status = brillo_audio_service_->GetDevices(flag, &devices); return status.serviceSpecificErrorCode(); } int BrilloAudioClient::SetDevice(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config) { if (!brillo_audio_service_.get()) { OnBASDisconnect(); return ECONNABORTED; } auto status = brillo_audio_service_->SetDevice(usage, config); return status.serviceSpecificErrorCode(); } int BrilloAudioClient::GetMaxVolumeSteps(BAudioUsage usage, int* max_steps) { if (!brillo_audio_service_.get()) { OnBASDisconnect(); return ECONNABORTED; } auto status = brillo_audio_service_->GetMaxVolumeSteps( BrilloAudioClientHelpers::GetStreamType(usage), max_steps); return status.serviceSpecificErrorCode(); } int BrilloAudioClient::SetMaxVolumeSteps(BAudioUsage usage, int max_steps) { if (!brillo_audio_service_.get()) { OnBASDisconnect(); return ECONNABORTED; } auto status = brillo_audio_service_->SetMaxVolumeSteps( BrilloAudioClientHelpers::GetStreamType(usage), max_steps); return status.serviceSpecificErrorCode(); } int BrilloAudioClient::SetVolumeIndex(BAudioUsage usage, audio_devices_t device, int index) { if (!brillo_audio_service_.get()) { OnBASDisconnect(); return ECONNABORTED; } auto status = brillo_audio_service_->SetVolumeIndex( BrilloAudioClientHelpers::GetStreamType(usage), device, index); return status.serviceSpecificErrorCode(); } int BrilloAudioClient::GetVolumeIndex(BAudioUsage usage, audio_devices_t device, int* index) { if (!brillo_audio_service_.get()) { OnBASDisconnect(); return ECONNABORTED; } auto status = brillo_audio_service_->GetVolumeIndex( BrilloAudioClientHelpers::GetStreamType(usage), device, index); return status.serviceSpecificErrorCode(); } int BrilloAudioClient::GetVolumeControlStream(BAudioUsage* usage) { if (!brillo_audio_service_.get()) { OnBASDisconnect(); return ECONNABORTED; } int stream; auto status = brillo_audio_service_->GetVolumeControlStream(&stream); *usage = BrilloAudioClientHelpers::GetBAudioUsage( static_cast(stream)); return status.serviceSpecificErrorCode(); } int BrilloAudioClient::SetVolumeControlStream(BAudioUsage usage) { if (!brillo_audio_service_.get()) { OnBASDisconnect(); return ECONNABORTED; } auto status = brillo_audio_service_->SetVolumeControlStream( BrilloAudioClientHelpers::GetStreamType(usage)); return status.serviceSpecificErrorCode(); } int BrilloAudioClient::IncrementVolume() { if (!brillo_audio_service_.get()) { OnBASDisconnect(); return ECONNABORTED; } auto status = brillo_audio_service_->IncrementVolume(); return status.serviceSpecificErrorCode(); } int BrilloAudioClient::DecrementVolume() { if (!brillo_audio_service_.get()) { OnBASDisconnect(); return ECONNABORTED; } auto status = brillo_audio_service_->DecrementVolume(); return status.serviceSpecificErrorCode(); } int BrilloAudioClient::RegisterAudioCallback( android::sp callback, int* callback_id) { if (!brillo_audio_service_.get()) { OnBASDisconnect(); return ECONNABORTED; } if (!brillo_audio_service_->RegisterServiceCallback(callback).isOk()) { *callback_id = 0; return ECONNABORTED; } for (auto& entry : callback_map_) { if (entry.second->Equals(callback)) { LOG(ERROR) << "Callback has already been registered."; *callback_id = 0; return EINVAL; } } *callback_id = callback_id_counter_++; callback_map_.emplace(*callback_id, callback); return 0; } int BrilloAudioClient::UnregisterAudioCallback(int callback_id) { if (!brillo_audio_service_.get()) { OnBASDisconnect(); return ECONNABORTED; } auto callback_elem = callback_map_.find(callback_id); if (callback_elem == callback_map_.end()) { // If we were passed an invalid callback_id, do nothing. LOG(ERROR) << "Unregister called with invalid callback ID."; return EINVAL; } brillo_audio_service_->UnregisterServiceCallback(callback_elem->second.get()); callback_map_.erase(callback_elem); return 0; } } // namespace brillo